#ifndef SPROUT_BREED_TRAITS_HPP #define SPROUT_BREED_TRAITS_HPP #include #include #include #include #include #include #include #include #include namespace sprout { namespace breed { namespace detail { template struct if_vararg {}; template struct if_vararg : public T {}; template struct is_callable2_ : public std::false_type {}; template struct is_callable2_ : public std::true_type {}; template::value> struct is_callable_ : public sprout::breed::detail::is_callable2_ {}; } // namespace detail // // is_callable // template struct is_callable : public sprout::breed::detail::is_callable_ {}; template<> struct is_callable : public std::true_type {}; template<> struct is_callable : public std::false_type {}; template struct is_callable > : public std::false_type {}; namespace detail { template struct is_transform_ : public std::false_type {}; template struct is_transform_ : public std::true_type {}; } // namespace detail // // is_transform // template struct is_transform : public sprout::breed::detail::is_transform_ {}; namespace detail { template struct is_aggregate_ : public std::is_pod {}; template struct is_aggregate_, void> : public std::false_type {}; template struct is_aggregate_, void> : public std::false_type {}; template struct is_aggregate_ : public std::true_type {}; } // namespace detail // // is_transform // template struct is_aggregate : public sprout::breed::detail::is_aggregate_ {}; // // is_transform // template struct is_expr : public std::false_type {}; template struct is_expr : public std::true_type {}; template struct is_expr : public is_expr {}; // // tag_of // template struct tag_of { public: typedef typename Expr::breed_tag type; }; template struct tag_of { public: typedef typename Expr::breed_tag type; }; // // arity_of // template struct arity_of : public Expr::breed_arity {}; template struct arity_of : public Expr::breed_arity {}; namespace result_of { // // as_expr // template struct as_expr { public: typedef typename Domain::template as_expr::result_type type; }; // // as_child // template struct as_child { public: typedef typename Domain::template as_child::result_type type; }; // // child // template struct child : public child_c {}; // // value // template struct value { static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c"); public: typedef typename Expr::template breed_child<0>::type value_type; typedef typename sprout::breed::detail::term_traits::value_type type; }; template struct value { static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c"); public: typedef typename Expr:template breed_child<0>::type value_type; typedef typename sprout::breed::detail::term_traits::reference type; }; template struct value { static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c"); public: typedef typename Expr:template breed_child<0>::type value_type; typedef typename sprout::breed::detail::term_traits::const_reference type; }; // // left // template struct left : public sprout::breed::result_of::child_c {}; // // right // template struct right : public child_c {}; } // namespace result_of // // terminal // template struct terminal : public sprout::breed::transform, int> { public: typedef sprout::breed::tag::terminal breed_tag; typedef sprout::breed::expr, 0> type; typedef sprout::breed::basic_expr, 0> breed_grammar; public: template struct breed_child : public sprout::tppack_at {}; public: template struct impl : public sprout::breed::transform_impl { public: typedef Expr result_type; public: #ifdef SPROUT_BREED_STRICT_RESULT_OF SPROUT_CONSTEXPR result_type #else SPROUT_CONSTEXPR typename impl::expr_param #endif operator()( typename impl::expr_param e, typename impl::state_param, typename impl::data_param ) const { return e; } }; }; // // if_else_ // template struct if_else_ : public sprout::breed::transform, int> { public: typedef sprout::breed::tag::if_else_ breed_tag; typedef sprout::breed::expr< sprout::breed::tag::if_else_, sprout::breed::sprout::breed::list, 3 > type; typedef sprout::breed::basic_expr< sprout::breed::tag::if_else_, sprout::breed::sprout::breed::list, 3 > breed_grammar; public: template struct breed_child : public sprout::tppack_at {}; public: template struct impl : public sprout::breed::detail::pass_through_impl {}; }; // // nullary_expr // template struct nullary_expr : public sprout::breed::transform, int> { public: typedef Tag breed_tag; typedef sprout::breed::expr, 0> type; typedef sprout::breed::basic_expr, 0> breed_grammar; public: template struct breed_child : public sprout::tppack_at {}; public: template struct impl : public sprout::breed::transform_impl { public: typedef Expr result_type; public: #ifdef SPROUT_BREED_STRICT_RESULT_OF SPROUT_CONSTEXPR result_type #else SPROUT_CONSTEXPR typename impl::expr_param #endif operator()( typename impl::expr_param e, typename impl::state_param, typename impl::data_param ) const { return e; } }; }; // // unary_expr // template struct unary_expr : public sprout::breed::transform, int> { public: typedef Tag breed_tag; typedef sprout::breed::expr, 1> type; typedef sprout::breed::basic_expr, 1> breed_grammar; public: template struct breed_child : public sprout::tppack_at {}; public: template struct impl : public sprout::breed::detail::pass_through_impl {}; }; // // binary_expr // template struct binary_expr : public sprout::breed::transform, int> { public: typedef Tag breed_tag; typedef sprout::breed::expr, 2> type; typedef sprout::breed::basic_expr, 2> breed_grammar; public: template struct breed_child : public sprout::tppack_at {}; public: template struct impl : public sprout::breed::detail::pass_through_impl {}; }; # define SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(op) \ template \ struct op \ : public sprout::breed::transform, int> \ { \ public: \ typedef sprout::breed::tag::op breed_tag; \ typedef sprout::breed::expr, 1> type; \ typedef sprout::breed::basic_expr, 1> breed_grammar; \ public: \ template \ struct breed_child \ : public sprout::tppack_at \ {}; \ public: \ template \ struct impl \ : public sprout::breed::detail::pass_through_impl \ {}; \ }; # define SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(op) \ template \ struct op \ : public sprout::breed::transform, int> \ { \ public: \ typedef sprout::breed::tag::op breed_tag; \ typedef sprout::breed::expr, 2> type; \ typedef sprout::breed::basic_expr, 2> breed_grammar; \ public: \ template \ struct breed_child \ : public sprout::tppack_at \ {}; \ public: \ template \ struct impl \ : public sprout::breed::detail::pass_through_impl \ {}; \ }; SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(unary_plus) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(negate) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(dereference) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(complement) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(address_of) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(logical_not) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(pre_inc) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(pre_dec) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(post_inc) SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(post_dec) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_left) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_right) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(multiplies) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(divides) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(modulus) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(plus) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(minus) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(less) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(greater) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(less_equal) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(greater_equal) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(equal_to) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(not_equal_to) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(logical_or) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(logical_and) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_or) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_and) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_xor) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(comma) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(mem_ptr) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_left_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_right_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(multiplies_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(divides_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(modulus_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(plus_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(minus_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(subscript) SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(member) # undef SPROUT_BREED_DEFINE_UNARY_METAFUNCTION # undef SPROUT_BREED_DEFINE_BINARY_METAFUNCTION // // function // template struct function : public sprout::breed::transform< sprout::breed::function, int > { public: typedef sprout::breed::tag::function breed_tag; typedef sprout::breed::expr< sprout::breed::tag::function, sprout::breed::list, sizeof...(Args) > type; typedef sprout::breed::basic_expr< sprout::breed::tag::function, sprout::breed::list, sizeof...(Args) > breed_grammar; public: template struct breed_child { public: typedef std::conditional< N < sizeof...(Args), sprout::tppack_at, sprout::breed::detail::if_vararg::type> >::type::type }; template struct impl : public sprout::breed::detail::pass_through_impl {}; }; // // nary_expr // template struct nary_expr : public sprout::breed::transform< sprout::breed::nary_expr, int > { public: typedef Tag breed_tag; typedef sprout::breed::expr< Tag, sprout::breed::list, sizeof...(Args) > type; typedef sprout::breed::basic_expr< Tag, sprout::breed::list, sizeof...(Args) > breed_grammar; public: template struct breed_child { public: typedef std::conditional< N < sizeof...(Args), sprout::tppack_at, sprout::breed::detail::if_vararg::type> >::type::type }; template struct impl : public sprout::breed::detail::pass_through_impl {}; }; namespace detail { template class T, typename... Args> struct is_callable_, sizeof...(Args)> : public std::is_same< typename sprout::tppack_at::type, sprout::breed::callable > {}; } // namespace detail namespace result_of { // // child_c // template struct child_c { static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c"); public: typedef typename Expr::template breed_child::type value_type; typedef typename sprout::breed::detail::expr_traits::value_type type; }; template struct child_c { static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c"); public: typedef typename Expr::template breed_child::type value_type; typedef typename detail::expr_traits::reference type; public: static type call(Expr& e) { return e.proto_base().breed child(); } }; template struct child_c { static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c"); public: typedef typename Expr::template breed_child::type value_type; typedef typename detail::expr_traits::const_reference type; public: static SPROUT_CONSTEXPR type call(Expr const& e) { return e.proto_base().breed child(); } }; } // namespace result_of namespace functional { // // as_expr // template struct as_expr { public: SPROUT_BREED_CALLABLE() public: template struct result; template struct result { typedef typename Domain::template as_expr::result_type type; }; template struct result { typedef typename Domain::template as_expr::result_type type; }; public: template SPROUT_CONSTEXPR typename std::add_const< typename result::type >::type operator()(T const& t) const { return typename Domain::template as_expr()(t); } template typename std::add_const< typename result::type >::type operator()(T& t) const { return typename Domain::template as_expr()(t); } }; // // as_child // template struct as_child { public: SPROUT_BREED_CALLABLE() public: template struct result; template struct result { public: typedef typename Domain::template as_child::result_type type; }; template struct result { public: typedef typename Domain::template as_child::result_type type; }; public: template SPROUT_CONSTEXPR typename std::add_const< typename result::type >::type operator()(T const& t) const { return typename Domain::template as_child()(t); } template typename std::add_const< typename result::type >::type operator()(T& t) const { return typename Domain::template as_child()(t); } }; // // child_c // template struct child_c { public: SPROUT_BREED_CALLABLE() public: template struct result; template struct result { public: typedef typename result_of::child_c::type type; }; public: template SPROUT_CONSTEXPR typename result_of::child_c::type operator()(Expr const& e) const { return result_of::child_c::call(e); } template typename result_of::child_c::type operator()(Expr& e) const { return result_of::child_c::call(e); } }; // // child // template struct child { public: SPROUT_BREED_CALLABLE() public: template struct result; template struct result { public: typedef typename result_of::child::type type; }; public: template SPROUT_CONSTEXPR typename result_of::child::type operator()(Expr const& e) const { return result_of::child::call(e); } template typename result_of::child::type operator()(Expr const& e) const { return result_of::child::call(e); } }; // // value // struct value { public: SPROUT_BREED_CALLABLE() public: template struct result; template struct result { public: typedef typename result_of::value::type type; }; public: template SPROUT_CONSTEXPR typename result_of::value::type operator()(Expr const& e) const { return e.breed_base().template child<0>(); } template typename result_of::value::type operator()(Expr& e) const { return e.breed_base().template child<0>(); } }; // // left // struct left { public: SPROUT_BREED_CALLABLE() public: template struct result; template struct result { public: typedef typename result_of::left::type type; }; public: template SPROUT_CONSTEXPR typename result_of::value::type operator()(Expr const& e) const { return e.breed_base().template child<0>(); } template typename result_of::value::type operator()(Expr& e) const { return e.breed_base().template child<0>(); } }; // // right // struct right { public: SPROUT_BREED_CALLABLE() public: template struct result; template struct result { public: typedef typename result_of::right::type type; }; public: template SPROUT_CONSTEXPR typename result_of::value::type operator()(Expr const& e) const { return e.breed_base().template child<1>(); } template typename result_of::value::type operator()(Expr& e) const { return e.breed_base().template child<1>(); } }; } // namespace functional // // as_expr // template SPROUT_CONSTEXPR typename std::add_const< typename sprout::breed::result_of::as_expr::type >::type as_expr(T const& t) { return sprout::breed::default_domain::as_expr()(t); } template typename std::add_const< typename sprout::breed::result_of::as_expr::type >::type as_expr(T& t) { return sprout::breed::default_domain::as_expr()(t); } template SPROUT_CONSTEXPR typename std::add_const< typename sprout::breed::result_of::as_expr::type >::type as_expr(T const& t) { return typename Domain::template as_expr()(t); } template typename std::add_const< typename sprout::breed::result_of::as_expr::type >::type as_expr(T& t) { return typename Domain::template as_expr()(t); } // // as_child // template SPROUT_CONSTEXPR typename std::add_const< typename sprout::breed::result_of::as_child::type >::type as_child(T const& t) { return sprout::breed::default_domain::as_child()(t); } template typename std::add_const< typename sprout::breed::result_of::as_child::type >::type as_child(T& t) { return sprout::breed::default_domain::as_child()(t); } template SPROUT_CONSTEXPR typename std::add_const< typename sprout::breed::result_of::as_child::type >::type as_child(T const& t) { return typename Domain::template as_child()(t); } template typename std::add_const< typename sprout::breed::result_of::as_child::type >::type as_child(T& t) { return typename Domain::template as_child()(t); } // // child // template SPROUT_CONSTEXPR typename sprout::breed::result_of::child::type child(Expr const& e) { return sprout::breed::result_of::child::call(e); } template typename sprout::breed::result_of::child::type child(Expr& e) { return sprout::breed::result_of::child::call(e); } template SPROUT_CONSTEXPR typename sprout::breed::detail::expr_traits< typename Expr2::breed_base_expr:template breed_child<0>::type >::const_reference child(Expr2 const& expr2) { return expr2.breed_base().template child<0>(); } template typename sprout::breed::detail::expr_traits< typename Expr2::breed_base_expr:template breed_child<0>::type >::reference child(Expr2& expr2) { return expr2.breed_base().template child<0>(); } // // child_c // template SPROUT_CONSTEXPR typename sprout::breed::result_of::child_c::type child_c(Expr const& e) { return sprout::breed::result_of::child_c::call(e); } template typename sprout::breed::result_of::child_c::type child_c(Expr& e) { return sprout::breed::result_of::child_c::call(e); } // // value // template SPROUT_CONSTEXPR typename sprout::breed::result_of::value::type value(Expr const& e) { return e.breed_base().template child<0>(); } template typename sprout::breed::result_of::value::type value(Expr& e) { return e.breed_base().template child<0>(); } // // left // template SPROUT_CONSTEXPR typename sprout::breed::result_of::left::type left(Expr const& e) { return e.breed_base().template child<0>(); } template typename sprout::breed::result_of::left::type left(Expr& e) { return e.breed_base().template child<0>(); } // // right // template SPROUT_CONSTEXPR typename sprout::breed::result_of::right::type right(Expr const& e) { return e.breed_base().template child<1>(); } template typename sprout::breed::result_of::right::type right(Expr& e) { return e.breed_base().template child<1>(); } // // is_callable // template struct is_callable > : public std::true_type {}; template struct is_callable > : public std::true_type {}; template struct is_callable > : public std::true_type {}; template struct is_callable > : public std::true_type {}; } // namespace breed } // namespace sprout #endif // #ifndef SPROUT_BREED_TRAITS_HPP