#ifndef BOOST_PP_IS_ITERATING /////////////////////////////////////////////////////////////////////////////// /// \file traits.hpp /// Contains definitions for arg\<\>, arg_c\<\>, left\<\>, /// right\<\>, tag\<\>, and the helper functions arg(), arg_c(), /// left() and right(). // // Copyright 2007 Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if BOOST_WORKAROUND( BOOST_MSVC, == 1310 ) #define BOOST_PROTO_IS_ARRAY_(T) boost::is_array::type> #else #define BOOST_PROTO_IS_ARRAY_(T) boost::is_array #endif #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 ) #pragma warning(push) #pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored #endif namespace boost { namespace proto { template struct is_transform : mpl::false_ {}; template<> struct is_transform : mpl::true_ {}; namespace result_of { // is_ref template struct is_ref : mpl::false_ {}; template struct is_ref : mpl::true_ {}; // is_expr template struct is_expr : mpl::false_ {}; template struct is_expr : mpl::true_ {}; // tag_of template struct tag_of { typedef typename Expr::proto_tag type; }; // id template struct id : result_of::deep_copy {}; // as_expr template struct as_expr { typedef typename mpl::eval_if< mpl::or_ > , add_reference , remove_cv >::type proto_arg0; typedef expr > expr_type; typedef typename Domain::template apply::type type; typedef type const result_type; template static result_type call(T2 &t) { return Domain::make(expr_type::make(t)); } }; template struct as_expr { typedef typename T::proto_derived_expr type; typedef T &result_type; template static result_type call(T2 &t) { return t; } }; // as_arg template struct as_arg { typedef expr > expr_type; typedef typename Domain::template apply::type type; template static type call(T2 &t) { return Domain::make(expr_type::make(t)); } }; template struct as_arg { typedef ref_ type; template static type call(T2 &t) { return type::make(t); } }; template struct arg : arg_c {}; // left // BUGBUG this forces the instantiation of Expr. Couldn't we // partially specialize left<> on expr< T, A > and // ref_< expr< T, A > > and return A::arg0 ? template struct left : unref {}; // right template struct right : unref {}; } namespace detail { template struct if_vararg {}; template struct if_vararg : T {}; } namespace op { // terminal template struct terminal : has_identity_transform { terminal(); typedef expr > type; typedef type proto_base_expr; typedef proto::tag::terminal proto_tag; typedef T proto_arg0; }; // if_else template struct if_else_ : has_pass_through_transform > { if_else_(); typedef expr > type; typedef type proto_base_expr; typedef proto::tag::if_else_ proto_tag; typedef T proto_arg0; typedef U proto_arg1; typedef V proto_arg2; }; // unary_expr template struct unary_expr : has_pass_through_transform > { unary_expr(); typedef expr > type; typedef type proto_base_expr; typedef Tag proto_tag; typedef T proto_arg0; }; // binary_expr template struct binary_expr : has_pass_through_transform > { binary_expr(); typedef expr > type; typedef type proto_base_expr; typedef Tag proto_tag; typedef T proto_arg0; typedef U proto_arg1; }; #define BOOST_PROTO_UNARY_GENERATOR(Name) \ template \ struct Name : has_pass_through_transform > \ { \ Name(); \ typedef expr > type; \ typedef type proto_base_expr; \ typedef proto::tag::Name proto_tag; \ typedef T proto_arg0; \ }; \ /**/ #define BOOST_PROTO_BINARY_GENERATOR(Name) \ template \ struct Name : has_pass_through_transform > \ { \ Name(); \ typedef expr > type; \ typedef type proto_base_expr; \ typedef proto::tag::Name proto_tag; \ typedef T proto_arg0; \ typedef U proto_arg1; \ }; \ /**/ BOOST_PROTO_UNARY_GENERATOR(posit) BOOST_PROTO_UNARY_GENERATOR(negate) BOOST_PROTO_UNARY_GENERATOR(dereference) BOOST_PROTO_UNARY_GENERATOR(complement) BOOST_PROTO_UNARY_GENERATOR(address_of) BOOST_PROTO_UNARY_GENERATOR(logical_not) BOOST_PROTO_UNARY_GENERATOR(pre_inc) BOOST_PROTO_UNARY_GENERATOR(pre_dec) BOOST_PROTO_UNARY_GENERATOR(post_inc) BOOST_PROTO_UNARY_GENERATOR(post_dec) BOOST_PROTO_BINARY_GENERATOR(shift_left) BOOST_PROTO_BINARY_GENERATOR(shift_right) BOOST_PROTO_BINARY_GENERATOR(multiplies) BOOST_PROTO_BINARY_GENERATOR(divides) BOOST_PROTO_BINARY_GENERATOR(modulus) BOOST_PROTO_BINARY_GENERATOR(plus) BOOST_PROTO_BINARY_GENERATOR(minus) BOOST_PROTO_BINARY_GENERATOR(less) BOOST_PROTO_BINARY_GENERATOR(greater) BOOST_PROTO_BINARY_GENERATOR(less_equal) BOOST_PROTO_BINARY_GENERATOR(greater_equal) BOOST_PROTO_BINARY_GENERATOR(equal_to) BOOST_PROTO_BINARY_GENERATOR(not_equal_to) BOOST_PROTO_BINARY_GENERATOR(logical_or) BOOST_PROTO_BINARY_GENERATOR(logical_and) BOOST_PROTO_BINARY_GENERATOR(bitwise_and) BOOST_PROTO_BINARY_GENERATOR(bitwise_or) BOOST_PROTO_BINARY_GENERATOR(bitwise_xor) BOOST_PROTO_BINARY_GENERATOR(comma) BOOST_PROTO_BINARY_GENERATOR(mem_ptr) BOOST_PROTO_BINARY_GENERATOR(assign) BOOST_PROTO_BINARY_GENERATOR(shift_left_assign) BOOST_PROTO_BINARY_GENERATOR(shift_right_assign) BOOST_PROTO_BINARY_GENERATOR(multiplies_assign) BOOST_PROTO_BINARY_GENERATOR(divides_assign) BOOST_PROTO_BINARY_GENERATOR(modulus_assign) BOOST_PROTO_BINARY_GENERATOR(plus_assign) BOOST_PROTO_BINARY_GENERATOR(minus_assign) BOOST_PROTO_BINARY_GENERATOR(bitwise_and_assign) BOOST_PROTO_BINARY_GENERATOR(bitwise_or_assign) BOOST_PROTO_BINARY_GENERATOR(bitwise_xor_assign) BOOST_PROTO_BINARY_GENERATOR(subscript) } // namespace op #undef BOOST_PROTO_UNARY_GENERATOR #undef BOOST_PROTO_BINARY_GENERATOR #define BOOST_PROTO_ARG(z, n, data)\ typedef BOOST_PP_CAT(data, n) BOOST_PP_CAT(proto_arg, n);\ /**/ #define BOOST_PROTO_IMPLICIT_ARG(z, n, data)\ BOOST_PP_CAT(data, n) &BOOST_PP_CAT(a, n);\ /**/ #define BOOST_PROTO_ARG_N_TYPE(z, n, data)\ typename proto::result_of::unref<\ typename Expr::BOOST_PP_CAT(proto_arg, n)\ >::const_reference\ /**/ #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, )) #include BOOST_PP_ITERATE() #undef BOOST_PROTO_ARG #undef BOOST_PROTO_ARG_N_TYPE #undef BOOST_PROTO_IMPLICIT_ARG namespace functional { template struct as_expr { template struct result {}; template struct result : result_of::as_expr::type, Domain> {}; template typename result_of::as_expr::result_type operator ()(T &t) const { return result_of::as_expr::call(t); } template typename result_of::as_expr::result_type operator ()(T const &t) const { return result_of::as_expr::call(t); } #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) template typename result_of::as_expr::result_type operator ()(T (&t)[N_]) const { return result_of::as_expr::call(t); } template typename result_of::as_expr::result_type operator ()(T const (&t)[N_]) const { return result_of::as_expr::call(t); } #endif }; template struct as_arg { template struct result {}; template struct result : result_of::as_arg::type, Domain> {}; template typename result_of::as_arg::type operator ()(T &t) const { return result_of::as_arg::call(t); } template typename result_of::as_arg::type operator ()(T const &t) const { return result_of::as_arg::call(t); } }; template struct arg_c { template struct result {}; template struct result : result_of::arg_c::type, N> {}; template typename result_of::arg_c::reference operator ()(Expr &expr) const { return result_of::arg_c::call(expr); } template typename result_of::arg_c::const_reference operator ()(Expr const &expr) const { return result_of::arg_c::call(expr); } }; template struct arg { template struct result {}; template struct result : result_of::arg::type, N> {}; template typename result_of::arg::reference operator ()(Expr &expr) const { return result_of::arg::call(expr); } template typename result_of::arg::const_reference operator ()(Expr const &expr) const { return result_of::arg::call(expr); } }; struct left { template struct result {}; template struct result : result_of::left::type> {}; template typename result_of::left::reference operator ()(Expr &expr) const { return proto::unref(expr.proto_base().arg0); } template typename result_of::left::const_reference operator ()(Expr const &expr) const { return proto::unref(expr.proto_base().arg0); } }; struct right { template struct result {}; template struct result : result_of::right::type> {}; template typename result_of::right::reference operator ()(Expr &expr) const { return proto::unref(expr.proto_base().arg1); } template typename result_of::right::const_reference operator ()(Expr const &expr) const { return proto::unref(expr.proto_base().arg1); } }; } functional::left const left = {}; functional::right const right = {}; /// as_expr /// template typename result_of::as_expr::result_type as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) { return result_of::as_expr::call(t); } /// \overload /// template typename result_of::as_expr::result_type as_expr(T const &t) { return result_of::as_expr::call(t); } /// \overload /// template typename result_of::as_expr::result_type as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) { return result_of::as_expr::call(t); } /// \overload /// template typename result_of::as_expr::result_type as_expr(T const &t) { return result_of::as_expr::call(t); } /// as_arg /// template typename result_of::as_arg::type as_arg(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) { return result_of::as_arg::call(t); } /// \overload /// template typename result_of::as_arg::type as_arg(T const &t) { return result_of::as_arg::call(t); } /// \overload /// template typename result_of::as_arg::type as_arg(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T)) { return result_of::as_arg::call(t); } /// \overload /// template typename result_of::as_arg::type as_arg(T const &t) { return result_of::as_arg::call(t); } /// arg /// template typename result_of::unref::reference arg(Expr &expr BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) { return proto::unref(expr.proto_base().arg0); } /// \overload /// template typename result_of::unref::const_reference arg(Expr const &expr) { return proto::unref(expr.proto_base().arg0); } /// \overload /// template typename result_of::arg::reference arg(Expr &expr BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) { return result_of::arg::call(expr); } /// \overload /// template typename result_of::arg::const_reference arg(Expr const &expr) { return result_of::arg::call(expr); } /// arg_c /// template typename result_of::arg_c::reference arg_c(Expr &expr BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) { return result_of::arg_c::call(expr); } /// \overload /// template typename result_of::arg_c::const_reference arg_c(Expr const &expr) { return result_of::arg_c::call(expr); } }} #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 ) #pragma warning(pop) #endif #endif #else // PP_IS_ITERATING #define N BOOST_PP_ITERATION() #if N > 0 namespace op { template struct function< BOOST_PP_ENUM_PARAMS(N, A) BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_PROTO_MAX_ARITY, N), void BOOST_PP_INTERCEPT), void > : has_pass_through_transform< function< BOOST_PP_ENUM_PARAMS(N, A) BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_PROTO_MAX_ARITY, N), void BOOST_PP_INTERCEPT), void > > { typedef expr > type; typedef type proto_base_expr; typedef proto::tag::function proto_tag; BOOST_PP_REPEAT(N, BOOST_PROTO_ARG, A) BOOST_PP_REPEAT_FROM_TO(N, BOOST_PROTO_MAX_ARITY, BOOST_PROTO_ARG, detail::if_vararg BOOST_PP_INTERCEPT) }; template struct nary_expr< Tag BOOST_PP_ENUM_TRAILING_PARAMS(N, A) BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_PROTO_MAX_ARITY, N), void BOOST_PP_INTERCEPT), void > : has_pass_through_transform< nary_expr< Tag BOOST_PP_ENUM_TRAILING_PARAMS(N, A) BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_PROTO_MAX_ARITY, N), void BOOST_PP_INTERCEPT), void > > { typedef expr > type; typedef type proto_base_expr; typedef Tag proto_tag; BOOST_PP_REPEAT(N, BOOST_PROTO_ARG, A) BOOST_PP_REPEAT_FROM_TO(N, BOOST_PROTO_MAX_ARITY, BOOST_PROTO_ARG, detail::if_vararg BOOST_PP_INTERCEPT) }; } // namespace op namespace detail { template struct BOOST_PP_CAT(implicit_expr_, N) { BOOST_PP_REPEAT(N, BOOST_PROTO_IMPLICIT_ARG, A) template operator expr () const { expr that = {BOOST_PP_ENUM_PARAMS(N, a)}; return that; } }; } template detail::BOOST_PP_CAT(implicit_expr_, N) implicit_expr(BOOST_PP_ENUM_BINARY_PARAMS(N, A, &a)) { detail::BOOST_PP_CAT(implicit_expr_, N) that = {BOOST_PP_ENUM_PARAMS(N, a)}; return that; } #endif namespace result_of { template struct arg_c : unref { static typename arg_c::reference call(Expr &expr) { return proto::unref(expr.proto_base().BOOST_PP_CAT(arg, N)); } static typename arg_c::const_reference call(Expr const &expr) { return proto::unref(expr.proto_base().BOOST_PP_CAT(arg, N)); } }; template struct arg_c : arg_c {}; } #undef N #endif