1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file arg.hpp
3 /// Contains definition of the argN transforms.
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_ARG_HPP_EAN_11_01_2007
10 #define BOOST_PROTO_TRANSFORM_ARG_HPP_EAN_11_01_2007
11 
12 #include <boost/mpl/if.hpp>
13 #include <boost/proto/proto_fwd.hpp>
14 #include <boost/proto/traits.hpp>
15 #include <boost/proto/transform/impl.hpp>
16 #include <boost/type_traits/is_array.hpp>
17 #include <boost/proto/transform/env.hpp>
18 
19 namespace boost { namespace proto
20 {
21 
22     /// \brief A PrimitiveTransform that returns the current expression
23     /// unmodified
24     ///
25     /// Example:
26     ///
27     /// \code
28     /// proto::terminal<int>::type i = {42};
29     /// proto::terminal<int>::type & j = proto::_expr()(i);
30     /// assert( boost::addressof(i) == boost::addressof(j) );
31     /// \endcode
32     struct _expr : transform<_expr>
33     {
34         template<typename Expr, typename State, typename Data>
35         struct impl : transform_impl<Expr, State, Data>
36         {
37             typedef Expr result_type;
38 
39             /// Returns the current expression.
40             /// \param e The current expression.
41             /// \return \c e
42             /// \throw nothrow
BOOST_PROTO_RETURN_TYPE_STRICT_LOOSEboost::proto::_expr::impl43             BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
44             operator()(
45                 typename impl::expr_param e
46               , typename impl::state_param
47               , typename impl::data_param
48             ) const
49             {
50                 return e;
51             }
52         };
53     };
54 
55     /// \brief A PrimitiveTransform that returns the current state
56     /// unmodified
57     ///
58     /// Example:
59     ///
60     /// \code
61     /// proto::terminal<int>::type i = {42};
62     /// char ch = proto::_state()(i, 'a');
63     /// assert( ch == 'a' );
64     /// \endcode
65     struct _state : transform<_state>
66     {
67         template<typename Expr, typename State, typename Data>
68         struct impl : transform_impl<Expr, State, Data>
69         {
70             typedef State result_type;
71 
72             /// Returns the current state.
73             /// \param s The current state.
74             /// \return \c s
75             /// \throw nothrow
BOOST_PROTO_RETURN_TYPE_STRICT_LOOSEboost::proto::_state::impl76             BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::state_param)
77             operator ()(
78                 typename impl::expr_param
79               , typename impl::state_param s
80               , typename impl::data_param
81             ) const
82             {
83                 return s;
84             }
85         };
86     };
87 
88     /// \brief A PrimitiveTransform that returns the current data
89     /// unmodified
90     ///
91     /// Example:
92     ///
93     /// \code
94     /// proto::terminal<int>::type i = {42};
95     /// std::string str("hello");
96     /// std::string & data = proto::_data()(i, 'a', str);
97     /// assert( &str == &data );
98     /// \endcode
99     struct _data : transform<_data>
100     {
101         template<typename Expr, typename State, typename Data>
102         struct impl
103           : mpl::if_c<
104                 is_env<Data>::value
105               , _env_var<data_type>
106               , _env
107             >::type::template impl<Expr, State, Data>
108         {};
109     };
110 
111     /// \brief A PrimitiveTransform that returns N-th child of the current
112     /// expression.
113     ///
114     /// Example:
115     ///
116     /// \code
117     /// proto::terminal<int>::type i = {42};
118     /// proto::terminal<int>::type & j = proto::_child_c<0>()(-i);
119     /// assert( boost::addressof(i) == boost::addressof(j) );
120     /// \endcode
121     template<int N>
122     struct _child_c : transform<_child_c<N> >
123     {
124         template<typename Expr, typename State, typename Data>
125         struct impl : transform_impl<Expr, State, Data>
126         {
127             typedef
128                 typename result_of::child_c<Expr, N>::type
129             result_type;
130 
131             /// Returns the N-th child of \c e
132             /// \pre <tt>arity_of\<Expr\>::value \> N</tt>
133             /// \param e The current expression.
134             /// \return <tt>proto::child_c\<N\>(e)</tt>
135             /// \throw nothrow
136             #ifdef BOOST_PROTO_STRICT_RESULT_OF
137             result_type
138             #else
139             typename result_of::child_c<typename impl::expr_param, N>::type
140             #endif
operator ()boost::proto::_child_c::impl141             operator ()(
142                 typename impl::expr_param e
143               , typename impl::state_param
144               , typename impl::data_param
145             ) const
146             {
147                 return proto::child_c<N>(e);
148             }
149         };
150     };
151 
152     /// \brief A PrimitiveTransform that returns the value of the
153     /// current terminal expression.
154     ///
155     /// Example:
156     ///
157     /// \code
158     /// proto::terminal<int>::type i = {42};
159     /// int j = proto::_value()(i);
160     /// assert( 42 == j );
161     /// \endcode
162     struct _value : transform<_value>
163     {
164         template<typename Expr, typename State, typename Data>
165         struct impl : transform_impl<Expr, State, Data>
166         {
167             typedef
168                 typename result_of::value<Expr>::type
169             result_type;
170 
171             /// Returns the value of the specified terminal expression.
172             /// \pre <tt>arity_of\<Expr\>::value == 0</tt>.
173             /// \param e The current expression.
174             /// \return <tt>proto::value(e)</tt>
175             /// \throw nothrow
176             #ifdef BOOST_PROTO_STRICT_RESULT_OF
177             typename mpl::if_c<is_array<result_type>::value, result_type &, result_type>::type
178             #else
179             typename result_of::value<typename impl::expr_param>::type
180             #endif
operator ()boost::proto::_value::impl181             operator ()(
182                 typename impl::expr_param e
183               , typename impl::state_param
184               , typename impl::data_param
185             ) const
186             {
187                 return proto::value(e);
188             }
189         };
190     };
191 
192     /// \brief A PrimitiveTransform that does nothing
193     /// and returns void.
194     struct _void : transform<_void>
195     {
196         template<typename Expr, typename State, typename Data>
197         struct impl : transform_impl<Expr, State, Data>
198         {
199             typedef void result_type;
200 
201             /// Does nothing and returns void
operator ()boost::proto::_void::impl202             void operator ()(
203                 typename impl::expr_param
204               , typename impl::state_param
205               , typename impl::data_param
206             ) const
207             {}
208         };
209     };
210 
211     /// \brief A unary CallableTransform that wraps its argument
212     /// in a \c boost::reference_wrapper\<\>.
213     ///
214     /// Example:
215     ///
216     /// \code
217     /// proto::terminal<int>::type i = {42};
218     /// boost::reference_wrapper<proto::terminal<int>::type> j
219     ///     = proto::when<_, proto::_byref(_)>()(i);
220     /// assert( boost::addressof(i) == boost::addressof(j.get()) );
221     /// \endcode
222     struct _byref : callable
223     {
224         template<typename Sig>
225         struct result;
226 
227         template<typename This, typename T>
228         struct result<This(T)>
229         {
230             typedef boost::reference_wrapper<T const> const type;
231         };
232 
233         template<typename This, typename T>
234         struct result<This(T &)>
235         {
236             typedef boost::reference_wrapper<T> const type;
237         };
238 
239         /// Wrap the parameter \c t in a \c boost::reference_wrapper\<\>
240         /// \param t The object to wrap
241         /// \return <tt>boost::ref(t)</tt>
242         /// \throw nothrow
243         template<typename T>
operator ()boost::proto::_byref244         boost::reference_wrapper<T> const operator ()(T &t) const
245         {
246             return boost::reference_wrapper<T>(t);
247         }
248 
249         /// \overload
250         ///
251         template<typename T>
operator ()boost::proto::_byref252         boost::reference_wrapper<T const> const operator ()(T const &t) const
253         {
254             return boost::reference_wrapper<T const>(t);
255         }
256     };
257 
258     /// \brief A unary CallableTransform that strips references
259     /// and \c boost::reference_wrapper\<\> from its argument.
260     ///
261     /// Example:
262     ///
263     /// \code
264     /// proto::terminal<int>::type i = {42};
265     /// int j = 67;
266     /// int k = proto::when<_, proto::_byval(proto::_state)>()(i, boost::ref(j));
267     /// assert( 67 == k );
268     /// \endcode
269     struct _byval : callable
270     {
271         template<typename Sig>
272         struct result;
273 
274         template<typename This, typename T>
275         struct result<This(T)>
276         {
277             typedef T type;
278         };
279 
280         template<typename This, typename T>
281         struct result<This(T &)>
282           : result<This(T)>
283         {};
284 
285         template<typename This, typename T>
286         struct result<This(boost::reference_wrapper<T>)>
287           : result<This(T)>
288         {};
289 
290         /// \param t The object to unref
291         /// \return <tt>t</tt>
292         /// \throw nothrow
293         template<typename T>
operator ()boost::proto::_byval294         T operator ()(T const &t) const
295         {
296             return t;
297         }
298 
299         /// \overload
300         ///
301         template<typename T>
operator ()boost::proto::_byval302         T operator ()(boost::reference_wrapper<T> const &t) const
303         {
304             return t;
305         }
306     };
307 
308     /// INTERNAL ONLY
309     ///
310     template<>
311     struct is_callable<_expr>
312       : mpl::true_
313     {};
314 
315     /// INTERNAL ONLY
316     ///
317     template<>
318     struct is_callable<_state>
319       : mpl::true_
320     {};
321 
322     /// INTERNAL ONLY
323     ///
324     template<>
325     struct is_callable<_data>
326       : mpl::true_
327     {};
328 
329     /// INTERNAL ONLY
330     ///
331     template<int N>
332     struct is_callable<_child_c<N> >
333       : mpl::true_
334     {};
335 
336     /// INTERNAL ONLY
337     ///
338     template<>
339     struct is_callable<_value>
340       : mpl::true_
341     {};
342 
343     /// INTERNAL ONLY
344     ///
345     template<>
346     struct is_callable<_byref>
347       : mpl::true_
348     {};
349 
350     /// INTERNAL ONLY
351     ///
352     template<>
353     struct is_callable<_byval>
354       : mpl::true_
355     {};
356 
357 }}
358 
359 #endif
360