diff --git a/sprout/breed/detail/as_lvalue.hpp b/sprout/breed/detail/as_lvalue.hpp new file mode 100644 index 00000000..3a3e2357 --- /dev/null +++ b/sprout/breed/detail/as_lvalue.hpp @@ -0,0 +1,22 @@ +#ifndef SPROUT_BREED_DETAIL_AS_LVALUE_HPP +#define SPROUT_BREED_DETAIL_AS_LVALUE_HPP + +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template + SPROUT_CONSTEXPR T& as_lvalue(T& t) { + return t; + } + template + SPROUT_CONSTEXPR T const& as_lvalue(T const& t) { + return t; + } + } // namespace detail + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_DETAIL_AS_LVALUE_HPP diff --git a/sprout/breed/detail/poly_function.hpp b/sprout/breed/detail/poly_function.hpp new file mode 100644 index 00000000..8df3f908 --- /dev/null +++ b/sprout/breed/detail/poly_function.hpp @@ -0,0 +1,207 @@ +#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&) = delete; + }; + 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&) = delete; + }; + + 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 diff --git a/sprout/breed/matches.hpp b/sprout/breed/matches.hpp index cdca04fe..d1fc8eeb 100644 --- a/sprout/breed/matches.hpp +++ b/sprout/breed/matches.hpp @@ -10,6 +10,8 @@ namespace sprout { namespace breed { + namespace detail { + } // namespace detail } // namespace breed } // namespace sprout diff --git a/sprout/variant/variant.hpp b/sprout/variant/variant.hpp index 99087fec..3d69819a 100644 --- a/sprout/variant/variant.hpp +++ b/sprout/variant/variant.hpp @@ -18,8 +18,8 @@ namespace sprout { template class variant_impl { protected: - typedef sprout::tuples::tuple tuple_type;; - typedef sprout::types::type_tuple::type...> uncvref_tuple_type;; + typedef sprout::tuples::tuple tuple_type; + typedef sprout::types::type_tuple::type...> uncvref_tuple_type; private: template static SPROUT_CONSTEXPR tuple_type init(T&& operand, sprout::index_tuple) { @@ -62,10 +62,10 @@ namespace sprout { : private sprout::detail::variant_impl { private: - typedef sprout::detail::variant_impl impl_type;; - typedef typename impl_type::uncvref_tuple_type uncvref_tuple_type;; + typedef sprout::detail::variant_impl impl_type; + typedef typename impl_type::uncvref_tuple_type uncvref_tuple_type; public: - typedef typename impl_type::tuple_type tuple_type;; + typedef typename impl_type::tuple_type tuple_type; private: template static SPROUT_CONSTEXPR typename std::enable_if<