1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file apply.hpp
3 /// Proto transforms for applying MPL placeholder expressions.
4 //
5 //  Copyright 2007 Eric Niebler. Distributed under the Boost
6 //  Software License, Version 1.0. (See accompanying file
7 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef BOOST_PROTO_TRANSFORM_APPLY_HPP_EAN_06_23_2007
10 #define BOOST_PROTO_TRANSFORM_APPLY_HPP_EAN_06_23_2007
11 
12 #include <boost/xpressive/proto/detail/prefix.hpp>
13 #include <boost/mpl/apply.hpp>
14 #include <boost/xpressive/proto/detail/suffix.hpp>
15 
16 namespace boost { namespace proto { namespace transform
17 {
18     namespace detail
19     {
20         struct any
21         {
22             template<typename T>
anyboost::proto::transform::detail::any23             any(T const &)
24             {}
25         };
26 
27         struct default_factory
28         {
default_factoryboost::proto::transform::detail::default_factory29             default_factory()
30             {}
31 
operator ()boost::proto::transform::detail::default_factory32             default_factory const &operator()() const
33             {
34                 return *this;
35             }
36 
operator ()boost::proto::transform::detail::default_factory37             default_factory const &operator()(any) const
38             {
39                 return *this;
40             }
41 
operator ()boost::proto::transform::detail::default_factory42             default_factory const &operator()(any, any) const
43             {
44                 return *this;
45             }
46 
operator ()boost::proto::transform::detail::default_factory47             default_factory const &operator()(any, any, any) const
48             {
49                 return *this;
50             }
51 
52             template<typename T>
operator Tboost::proto::transform::detail::default_factory53             operator T() const
54             {
55                 return T();
56             }
57         };
58     }
59 
60     // Always return the specified type/object
61     template<typename Grammar, typename Always, typename Factory>
62     struct always
63       : Grammar
64     {
alwaysboost::proto::transform::always65         always() {}
66 
67         template<typename, typename, typename>
68         struct apply
69         {
70             typedef Always type;
71         };
72 
73         template<typename Expr, typename State, typename Visitor>
74         static Always
callboost::proto::transform::always75         call(Expr const &, State const &, Visitor &)
76         {
77             return Factory()();
78         }
79     };
80 
81     // Apply an MPL lambda, passing just Expr
82     template<typename Grammar, typename Lambda, typename Factory>
83     struct apply1
84       : Grammar
85     {
apply1boost::proto::transform::apply186         apply1() {}
87 
88         template<typename Expr, typename State, typename Visitor>
89         struct apply
90           : mpl::apply1<Lambda, typename Grammar::template apply<Expr, State, Visitor>::type>
91         {};
92 
93         template<typename Expr, typename State, typename Visitor>
94         static typename apply<Expr, State, Visitor>::type
callboost::proto::transform::apply195         call(Expr const &expr, State const &state, Visitor &visitor)
96         {
97             return Factory()(Grammar::call(expr, state, visitor));
98         }
99     };
100 
101     // Apply an MPL lambda, passing Expr and State
102     template<typename Grammar, typename Lambda, typename Factory>
103     struct apply2
104       : Grammar
105     {
apply2boost::proto::transform::apply2106         apply2() {}
107 
108         template<typename Expr, typename State, typename Visitor>
109         struct apply
110           : mpl::apply2<Lambda, typename Grammar::template apply<Expr, State, Visitor>::type, State>
111         {};
112 
113         template<typename Expr, typename State, typename Visitor>
114         static typename apply<Expr, State, Visitor>::type
callboost::proto::transform::apply2115         call(Expr const &expr, State const &state, Visitor &visitor)
116         {
117             return Factory()(Grammar::call(expr, state, visitor), state);
118         }
119     };
120 
121     // Apply an MPL lambda, passing Expr, State and Visitor
122     template<typename Grammar, typename Lambda, typename Factory>
123     struct apply3
124       : Grammar
125     {
apply3boost::proto::transform::apply3126         apply3() {}
127 
128         template<typename Expr, typename State, typename Visitor>
129         struct apply
130           : mpl::apply3<Lambda, typename Grammar::template apply<Expr, State, Visitor>::type, State, Visitor>
131         {};
132 
133         template<typename Expr, typename State, typename Visitor>
134         static typename apply<Expr, State, Visitor>::type
callboost::proto::transform::apply3135         call(Expr const &expr, State const &state, Visitor &visitor)
136         {
137             return Factory()(Grammar::call(expr, state, visitor), state, visitor);
138         }
139     };
140 
141 }}}
142 
143 namespace boost { namespace proto
144 {
145     template<typename Grammar, typename Always, typename Factory>
146     struct is_transform<transform::always<Grammar, Always, Factory> >
147       : mpl::true_
148     {};
149 
150     template<typename Grammar, typename Lambda, typename Factory>
151     struct is_transform<transform::apply1<Grammar, Lambda, Factory> >
152       : mpl::true_
153     {};
154 
155     template<typename Grammar, typename Lambda, typename Factory>
156     struct is_transform<transform::apply2<Grammar, Lambda, Factory> >
157       : mpl::true_
158     {};
159 
160     template<typename Grammar, typename Lambda, typename Factory>
161     struct is_transform<transform::apply3<Grammar, Lambda, Factory> >
162       : mpl::true_
163     {};
164 }}
165 
166 #endif
167