1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file impl.hpp
3 /// Contains definition of transform<> and transform_impl<> helpers.
4 //
5 //  Copyright 2008 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_IMPL_HPP_EAN_04_03_2008
10 #define BOOST_PROTO_TRANSFORM_IMPL_HPP_EAN_04_03_2008
11 
12 #include <boost/config.hpp>
13 #include <boost/mpl/bool.hpp>
14 #include <boost/type_traits/add_const.hpp>
15 #include <boost/type_traits/add_reference.hpp>
16 #include <boost/proto/proto_fwd.hpp>
17 #include <boost/proto/detail/any.hpp>
18 #include <boost/proto/detail/static_const.hpp>
19 
20 #if defined(_MSC_VER)
21 # pragma warning(push)
22 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
23 #endif
24 
25 namespace boost { namespace proto
26 {
27     namespace envns_
28     {
29         ////////////////////////////////////////////////////////////////////////////////////////////
30         struct key_not_found
31         {};
32 
33         ////////////////////////////////////////////////////////////////////////////////////////////
34         // empty_env
35         struct empty_env
36         {
37             typedef void proto_environment_;
38 
39             template<typename OtherTag, typename OtherValue = key_not_found>
40             struct lookup
41             {
42                 typedef OtherValue type;
43                 typedef
44                     typename add_reference<typename add_const<OtherValue>::type>::type
45                 const_reference;
46             };
47 
operator []boost::proto::envns_::empty_env48             key_not_found operator[](detail::any) const
49             {
50                 return key_not_found();
51             }
52 
53             template<typename T>
atboost::proto::envns_::empty_env54             T const &at(detail::any, T const &t) const
55             {
56                 return t;
57             }
58         };
59     }
60 
61     ////////////////////////////////////////////////////////////////////////////////////////////
62     // is_env
63     template<typename T, typename Void>
64     struct is_env
65       : mpl::false_
66     {};
67 
68     template<typename T>
69     struct is_env<T, typename T::proto_environment_>
70       : mpl::true_
71     {};
72 
73     template<typename T>
74     struct is_env<T &, void>
75       : is_env<T>
76     {};
77 
78 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
79 
80     /// INTERNAL ONLY
81     ///
82     #define BOOST_PROTO_TRANSFORM_(PrimitiveTransform, X)                                                       \
83     BOOST_PROTO_CALLABLE()                                                                                      \
84     typedef X proto_is_transform_;                                                                              \
85     typedef PrimitiveTransform transform_type;                                                                  \
86                                                                                                                 \
87     template<typename Sig>                                                                                      \
88     struct result                                                                                               \
89     {                                                                                                           \
90         typedef typename boost::proto::detail::apply_transform<Sig>::result_type type;                          \
91     };                                                                                                          \
92                                                                                                                 \
93     template<typename Expr>                                                                                     \
94     BOOST_FORCEINLINE                                                                                           \
95     typename boost::proto::detail::apply_transform<transform_type(Expr &)>::result_type                         \
96     operator ()(Expr &e) const                                                                                  \
97     {                                                                                                           \
98         boost::proto::empty_state s = 0;                                                                        \
99         boost::proto::empty_env d;                                                                              \
100         return boost::proto::detail::apply_transform<transform_type(Expr &)>()(e, s, d);                        \
101     }                                                                                                           \
102                                                                                                                 \
103     template<typename Expr>                                                                                     \
104     BOOST_FORCEINLINE                                                                                           \
105     typename boost::proto::detail::apply_transform<transform_type(Expr const &)>::result_type                   \
106     operator ()(Expr const &e) const                                                                            \
107     {                                                                                                           \
108         boost::proto::empty_state s = 0;                                                                        \
109         boost::proto::empty_env d;                                                                              \
110         return boost::proto::detail::apply_transform<transform_type(Expr const &)>()(e, s, d);                  \
111     }                                                                                                           \
112                                                                                                                 \
113     template<typename Expr, typename State>                                                                     \
114     BOOST_FORCEINLINE                                                                                           \
115     typename boost::proto::detail::apply_transform<transform_type(Expr &, State &)>::result_type                \
116     operator ()(Expr &e, State &s) const                                                                        \
117     {                                                                                                           \
118         boost::proto::empty_env d;                                                                              \
119         return boost::proto::detail::apply_transform<transform_type(Expr &, State &)>()(e, s, d);               \
120     }                                                                                                           \
121                                                                                                                 \
122     template<typename Expr, typename State>                                                                     \
123     BOOST_FORCEINLINE                                                                                           \
124     typename boost::proto::detail::apply_transform<transform_type(Expr const &, State &)>::result_type          \
125     operator ()(Expr const &e, State &s) const                                                                  \
126     {                                                                                                           \
127         boost::proto::empty_env d;                                                                              \
128         return boost::proto::detail::apply_transform<transform_type(Expr const &, State &)>()(e, s, d);         \
129     }                                                                                                           \
130                                                                                                                 \
131     template<typename Expr, typename State>                                                                     \
132     BOOST_FORCEINLINE                                                                                           \
133     typename boost::proto::detail::apply_transform<transform_type(Expr &, State const &)>::result_type          \
134     operator ()(Expr &e, State const &s) const                                                                  \
135     {                                                                                                           \
136         boost::proto::empty_env d;                                                                              \
137         return boost::proto::detail::apply_transform<transform_type(Expr &, State const &)>()(e, s, d);         \
138     }                                                                                                           \
139                                                                                                                 \
140     template<typename Expr, typename State>                                                                     \
141     BOOST_FORCEINLINE                                                                                           \
142     typename boost::proto::detail::apply_transform<transform_type(Expr const &, State const &)>::result_type    \
143     operator ()(Expr const &e, State const &s) const                                                            \
144     {                                                                                                           \
145         boost::proto::empty_env d;                                                                              \
146         return boost::proto::detail::apply_transform<transform_type(Expr const &, State const &)>()(e, s, d);   \
147     }                                                                                                           \
148                                                                                                                 \
149     template<typename Expr, typename State, typename Data>                                                      \
150     BOOST_FORCEINLINE                                                                                           \
151     typename boost::proto::detail::apply_transform<transform_type(Expr &, State &, Data &)>::result_type        \
152     operator ()(Expr &e, State &s, Data &d) const                                                               \
153     {                                                                                                           \
154         return boost::proto::detail::apply_transform<transform_type(Expr &, State &, Data &)>()(e, s, d);       \
155     }                                                                                                           \
156                                                                                                                 \
157     template<typename Expr, typename State, typename Data>                                                      \
158     BOOST_FORCEINLINE                                                                                           \
159     typename boost::proto::detail::apply_transform<transform_type(Expr const &, State &, Data &)>::result_type  \
160     operator ()(Expr const &e, State &s, Data &d) const                                                         \
161     {                                                                                                           \
162         return boost::proto::detail::apply_transform<transform_type(Expr const &, State &, Data &)>()(e, s, d); \
163     }                                                                                                           \
164                                                                                                                 \
165     template<typename Expr, typename State, typename Data>                                                      \
166     BOOST_FORCEINLINE                                                                                           \
167     typename boost::proto::detail::apply_transform<transform_type(Expr &, State const &, Data &)>::result_type  \
168     operator ()(Expr &e, State const &s, Data &d) const                                                         \
169     {                                                                                                           \
170         return boost::proto::detail::apply_transform<transform_type(Expr &, State const &, Data &)>()(e, s, d); \
171     }                                                                                                           \
172                                                                                                                 \
173     template<typename Expr, typename State, typename Data>                                                      \
174     BOOST_FORCEINLINE                                                                                           \
175     typename boost::proto::detail::apply_transform<transform_type(Expr const &, State const &, Data &)>::result_type  \
176     operator ()(Expr const &e, State const &s, Data &d) const                                                   \
177     {                                                                                                           \
178         return boost::proto::detail::apply_transform<transform_type(Expr const &, State const &, Data &)>()(e, s, d); \
179     }                                                                                                           \
180     /**/
181 
182 #else
183 
184     /// INTERNAL ONLY
185     ///
186     #define BOOST_PROTO_TRANSFORM_(PrimitiveTransform, X)                                                       \
187     BOOST_PROTO_CALLABLE()                                                                                      \
188     typedef X proto_is_transform_;                                                                              \
189     typedef PrimitiveTransform transform_type;                                                                  \
190                                                                                                                 \
191     template<typename Sig>                                                                                      \
192     struct result                                                                                               \
193     {                                                                                                           \
194         typedef typename boost::proto::detail::apply_transform<Sig>::result_type type;                          \
195     };                                                                                                          \
196                                                                                                                 \
197     template<typename Expr>                                                                                     \
198     BOOST_FORCEINLINE                                                                                           \
199     typename boost::proto::detail::apply_transform<transform_type(Expr const &)>::result_type                   \
200     operator ()(Expr &&e) const                                                                                 \
201     {                                                                                                           \
202         boost::proto::empty_state s = 0;                                                                        \
203         boost::proto::empty_env d;                                                                              \
204         return boost::proto::detail::apply_transform<transform_type(Expr const &)>()(e, s, d);                  \
205     }                                                                                                           \
206                                                                                                                 \
207     template<typename Expr, typename State>                                                                     \
208     BOOST_FORCEINLINE                                                                                           \
209     typename boost::proto::detail::apply_transform<transform_type(Expr const &, State const &)>::result_type    \
210     operator ()(Expr &&e, State &&s) const                                                                      \
211     {                                                                                                           \
212         boost::proto::empty_env d;                                                                              \
213         return boost::proto::detail::apply_transform<transform_type(Expr const &, State const &)>()(e, s, d);   \
214     }                                                                                                           \
215                                                                                                                 \
216     template<typename Expr, typename State, typename Data>                                                      \
217     BOOST_FORCEINLINE                                                                                           \
218     typename boost::proto::detail::apply_transform<transform_type(Expr const &, State const &, Data const &)>::result_type \
219     operator ()(Expr &&e, State &&s, Data &&d) const                                                            \
220     {                                                                                                           \
221         return boost::proto::detail::apply_transform<transform_type(Expr const &, State const &, Data const &)>()(e, s, d); \
222     }                                                                                                           \
223     /**/
224 
225 #endif
226 
227     #define BOOST_PROTO_TRANSFORM(PrimitiveTransform)                                                           \
228         BOOST_PROTO_TRANSFORM_(PrimitiveTransform, void)                                                        \
229         /**/
230 
231     namespace detail
232     {
233         template<typename Sig>
234         struct apply_transform;
235 
236         template<typename PrimitiveTransform, typename Expr>
237         struct apply_transform<PrimitiveTransform(Expr)>
238           : PrimitiveTransform::template impl<Expr, empty_state, empty_env>
239         {};
240 
241         template<typename PrimitiveTransform, typename Expr, typename State>
242         struct apply_transform<PrimitiveTransform(Expr, State)>
243           : PrimitiveTransform::template impl<Expr, State, empty_env>
244         {};
245 
246         template<typename PrimitiveTransform, typename Expr, typename State, typename Data>
247         struct apply_transform<PrimitiveTransform(Expr, State, Data)>
248           : PrimitiveTransform::template impl<Expr, State, Data>
249         {};
250     }
251 
252     template<typename PrimitiveTransform, typename X>
253     struct transform
254     {
255         BOOST_PROTO_TRANSFORM_(PrimitiveTransform, X)
256     };
257 
258     template<typename Expr, typename State, typename Data>
259     struct transform_impl
260     {
261         typedef Expr const expr;
262         typedef Expr const &expr_param;
263         typedef State const state;
264         typedef State const &state_param;
265         typedef Data const data;
266         typedef Data const &data_param;
267     };
268 
269     template<typename Expr, typename State, typename Data>
270     struct transform_impl<Expr &, State, Data>
271     {
272         typedef Expr expr;
273         typedef Expr &expr_param;
274         typedef State const state;
275         typedef State const &state_param;
276         typedef Data const data;
277         typedef Data const &data_param;
278     };
279 
280     template<typename Expr, typename State, typename Data>
281     struct transform_impl<Expr, State &, Data>
282     {
283         typedef Expr const expr;
284         typedef Expr const &expr_param;
285         typedef State state;
286         typedef State &state_param;
287         typedef Data const data;
288         typedef Data const &data_param;
289     };
290 
291     template<typename Expr, typename State, typename Data>
292     struct transform_impl<Expr, State, Data &>
293     {
294         typedef Expr const expr;
295         typedef Expr const &expr_param;
296         typedef State const state;
297         typedef State const &state_param;
298         typedef Data data;
299         typedef Data &data_param;
300     };
301 
302     template<typename Expr, typename State, typename Data>
303     struct transform_impl<Expr &, State &, Data>
304     {
305         typedef Expr expr;
306         typedef Expr &expr_param;
307         typedef State state;
308         typedef State &state_param;
309         typedef Data const data;
310         typedef Data const &data_param;
311     };
312 
313     template<typename Expr, typename State, typename Data>
314     struct transform_impl<Expr &, State, Data &>
315     {
316         typedef Expr expr;
317         typedef Expr &expr_param;
318         typedef State const state;
319         typedef State const &state_param;
320         typedef Data data;
321         typedef Data &data_param;
322     };
323 
324     template<typename Expr, typename State, typename Data>
325     struct transform_impl<Expr, State &, Data &>
326     {
327         typedef Expr const expr;
328         typedef Expr const &expr_param;
329         typedef State state;
330         typedef State &state_param;
331         typedef Data data;
332         typedef Data &data_param;
333     };
334 
335     template<typename Expr, typename State, typename Data>
336     struct transform_impl<Expr &, State &, Data &>
337     {
338         typedef Expr expr;
339         typedef Expr &expr_param;
340         typedef State state;
341         typedef State &state_param;
342         typedef Data data;
343         typedef Data &data_param;
344     };
345 
346 }} // namespace boost::proto
347 
348 #if defined(_MSC_VER)
349 # pragma warning(pop)
350 #endif
351 
352 #endif
353