1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file pass_through.hpp 3 /// 4 /// Definition of the pass_through transform, which is the default transform 5 /// of all of the expression generator metafunctions such as unary_plus<>, plus<> 6 /// and nary_expr<>. 7 // 8 // Copyright 2008 Eric Niebler. Distributed under the Boost 9 // Software License, Version 1.0. (See accompanying file 10 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 12 #ifndef BOOST_PROTO_TRANSFORM_PASS_THROUGH_HPP_EAN_12_26_2006 13 #define BOOST_PROTO_TRANSFORM_PASS_THROUGH_HPP_EAN_12_26_2006 14 15 #include <boost/preprocessor/cat.hpp> 16 #include <boost/preprocessor/repetition/enum.hpp> 17 #include <boost/preprocessor/iteration/iterate.hpp> 18 #include <boost/mpl/bool.hpp> 19 #include <boost/mpl/if.hpp> 20 #include <boost/type_traits/is_same.hpp> 21 #include <boost/type_traits/remove_reference.hpp> 22 #include <boost/proto/proto_fwd.hpp> 23 #include <boost/proto/args.hpp> 24 #include <boost/proto/transform/impl.hpp> 25 #include <boost/proto/detail/ignore_unused.hpp> 26 27 #if defined(_MSC_VER) 28 # pragma warning(push) 29 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined 30 #endif 31 32 namespace boost { namespace proto 33 { 34 namespace detail 35 { 36 template< 37 typename Grammar 38 , typename Domain 39 , typename Expr 40 , typename State 41 , typename Data 42 , long Arity = arity_of<Expr>::value 43 > 44 struct pass_through_impl 45 {}; 46 47 #include <boost/proto/transform/detail/pass_through_impl.hpp> 48 49 template<typename Grammar, typename Domain, typename Expr, typename State, typename Data> 50 struct pass_through_impl<Grammar, Domain, Expr, State, Data, 0> 51 : transform_impl<Expr, State, Data> 52 { 53 typedef Expr result_type; 54 55 /// \param e An expression 56 /// \return \c e 57 /// \throw nothrow 58 BOOST_FORCEINLINE BOOST_PROTO_RETURN_TYPE_STRICT_LOOSEboost::proto::detail::pass_through_impl59 BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename pass_through_impl::expr_param) 60 operator()( 61 typename pass_through_impl::expr_param e 62 , typename pass_through_impl::state_param 63 , typename pass_through_impl::data_param 64 ) const 65 { 66 return e; 67 } 68 }; 69 70 } // namespace detail 71 72 /// \brief A PrimitiveTransform that transforms the child expressions 73 /// of an expression node according to the corresponding children of 74 /// a Grammar. 75 /// 76 /// Given a Grammar such as <tt>plus\<T0, T1\></tt>, an expression type 77 /// that matches the grammar such as <tt>plus\<E0, E1\>::type</tt>, a 78 /// state \c S and a data \c V, the result of applying the 79 /// <tt>pass_through\<plus\<T0, T1\> \></tt> transform is: 80 /// 81 /// \code 82 /// plus< 83 /// T0::result<T0(E0, S, V)>::type 84 /// , T1::result<T1(E1, S, V)>::type 85 /// >::type 86 /// \endcode 87 /// 88 /// The above demonstrates how child transforms and child expressions 89 /// are applied pairwise, and how the results are reassembled into a new 90 /// expression node with the same tag type as the original. 91 /// 92 /// The explicit use of <tt>pass_through\<\></tt> is not usually needed, 93 /// since the expression generator metafunctions such as 94 /// <tt>plus\<\></tt> have <tt>pass_through\<\></tt> as their default 95 /// transform. So, for instance, these are equivalent: 96 /// 97 /// \code 98 /// // Within a grammar definition, these are equivalent: 99 /// when< plus<X, Y>, pass_through< plus<X, Y> > > 100 /// when< plus<X, Y>, plus<X, Y> > 101 /// when< plus<X, Y> > // because of when<class X, class Y=X> 102 /// plus<X, Y> // because plus<> is both a 103 /// // grammar and a transform 104 /// \endcode 105 /// 106 /// For example, consider the following transform that promotes all 107 /// \c float terminals in an expression to \c double. 108 /// 109 /// \code 110 /// // This transform finds all float terminals in an expression and promotes 111 /// // them to doubles. 112 /// struct Promote 113 /// : or_< 114 /// when<terminal<float>, terminal<double>::type(_value) > 115 /// // terminal<>'s default transform is a no-op: 116 /// , terminal<_> 117 /// // nary_expr<> has a pass_through<> transform: 118 /// , nary_expr<_, vararg<Promote> > 119 /// > 120 /// {}; 121 /// \endcode 122 template<typename Grammar, typename Domain /* = deduce_domain*/> 123 struct pass_through 124 : transform<pass_through<Grammar, Domain> > 125 { 126 template<typename Expr, typename State, typename Data> 127 struct impl 128 : detail::pass_through_impl<Grammar, Domain, Expr, State, Data> 129 {}; 130 }; 131 132 /// INTERNAL ONLY 133 /// 134 template<typename Grammar, typename Domain> 135 struct is_callable<pass_through<Grammar, Domain> > 136 : mpl::true_ 137 {}; 138 139 }} // namespace boost::proto 140 141 #if defined(_MSC_VER) 142 # pragma warning(pop) 143 #endif 144 145 #endif 146