#ifndef SPROUT_BREED_DETAIL_POLY_FUNCTION_HPP #define SPROUT_BREED_DETAIL_POLY_FUNCTION_HPP #include #include #include namespace sprout { namespace breed { namespace detail { template struct normalize_arg { public: typedef T type; typedef T const& reference; }; template struct normalize_arg { public: typedef T type; typedef T const& reference; }; template struct normalize_arg { public: typedef T type; typedef T const& reference; }; template struct arg { public: typedef T const& type; private: type value; public: SPROUT_CONSTEXPR arg(type t) : value(t) {} SPROUT_CONSTEXPR operator type() const { return this->value; } SPROUT_CONSTEXPR type operator()() const { return *this; } private: arg& operator=(arg const&) SPROUT_DELETED_FUNCTION_DECL }; template struct arg { public: typedef T& type; private: type value; public: SPROUT_CONSTEXPR arg(type t) : value(t) {} SPROUT_CONSTEXPR operator type() const { return this->value; } SPROUT_CONSTEXPR type operator()() const { return *this; } private: arg& operator=(arg const&) SPROUT_DELETED_FUNCTION_DECL }; template struct is_poly_function : public std::false_type {}; template struct is_poly_function : public std::true_type {}; # define SPROUT_BREED_POLY_FUNCTION() \ typedef void is_poly_function_base_; struct poly_function_base { public: SPROUT_BREED_POLY_FUNCTION(); }; template struct poly_function : public psprout::breed::detail::poly_function_base { public: template struct result; template struct result : public Derived::template impl<> { public: typedef typename result::result_type type; }; template struct result : public Derived::template impl< typename normalize_arg::type... > { public: typedef typename result::result_type type; }; public: SPROUT_CONSTEXPR NullaryResult operator()() const { return result().operator()(); } template SPROUT_CONSTEXPR typename result::type operator()(Args const&... args) const { return result().operator()( static_cast::reference>(args)... ); } }; template struct wrap_t; typedef char poly_function_t; typedef char (&mono_function_t)[2]; typedef char (&unknown_function_t)[3]; template sprout::breed::detail::poly_function_t test_poly_function( T const*, sprout::breed::detail::wrap_t const* = 0 ); template sprout::breed::detail::mono_function_t test_poly_function( T const*, sprout::breed::detail::wrap_t const* = 0 ); template sprout::breed::detail::unknown_function_t test_poly_function( T const*, ... ); template< typename Fun, typename Sig, typename Switch = std::integral_constant< std::size_t, sizeof(sprout::breed::detail::test_poly_function(0, 0)) > > struct poly_function_traits { public: typedef typename Fun::template result::type result_type; typedef Fun function_type; }; template struct poly_function_traits< Fun, Sig, std::integral_constant< std::size_t, sizeof(sprout::breed::detail::mono_function_t) > > { public: typedef typename Fun::result_type result_type; typedef Fun function_type; }; template struct poly_function_traits< PolyFun, PolyFun( Args..., std::integral_constant { public: typedef typename PolyFun::template impl function_type; typedef typename function_type::result_type result_type; }; template struct as_mono_function_impl; template struct as_mono_function_impl { public: typedef typename PolyFun::template impl type; }; template struct as_mono_function_impl { public: typedef PolyFun type; }; template struct as_mono_function; template struct as_mono_function : public sprout::breed::detail::as_mono_function_impl< PolyFun(Args...), sprout::breed::detail::is_poly_function::value > {}; } // namespace detail } // namespace breed } // namespace sprout #endif // #ifndef SPROUT_BREED_DETAIL_POLY_FUNCTION_HPP