1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file traits.hpp
3 /// Contains definitions for child\<\>, child_c\<\>, left\<\>,
4 /// right\<\>, tag_of\<\>, and the helper functions child(), child_c(),
5 /// value(), left() and right().
6 //
7 //  Copyright 2008 Eric Niebler. Distributed under the Boost
8 //  Software License, Version 1.0. (See accompanying file
9 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005
12 #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005
13 
14 #include <boost/config.hpp>
15 #include <boost/detail/workaround.hpp>
16 #include <boost/preprocessor/iteration/iterate.hpp>
17 #include <boost/preprocessor/repetition/enum.hpp>
18 #include <boost/preprocessor/repetition/enum_params.hpp>
19 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
20 #include <boost/preprocessor/repetition/repeat.hpp>
21 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
22 #include <boost/preprocessor/facilities/intercept.hpp>
23 #include <boost/preprocessor/arithmetic/sub.hpp>
24 #include <boost/static_assert.hpp>
25 #include <boost/mpl/bool.hpp>
26 #include <boost/proto/detail/template_arity.hpp>
27 #include <boost/type_traits/is_pod.hpp>
28 #include <boost/type_traits/is_same.hpp>
29 #include <boost/type_traits/add_const.hpp>
30 #include <boost/proto/proto_fwd.hpp>
31 #include <boost/proto/args.hpp>
32 #include <boost/proto/domain.hpp>
33 #include <boost/proto/transform/pass_through.hpp>
34 
35 #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 )
36     #pragma warning(push)
37     #pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored
38 #endif
39 
40 namespace boost { namespace proto
41 {
42     namespace detail
43     {
44         template<typename T, typename Void = void>
45         struct if_vararg
46         {};
47 
48         template<typename T>
49         struct if_vararg<T, typename T::proto_is_vararg_>
50           : T
51         {};
52 
53         template<typename T, typename Void = void>
54         struct is_callable2_
55           : mpl::false_
56         {};
57 
58         template<typename T>
59         struct is_callable2_<T, typename T::proto_is_callable_>
60           : mpl::true_
61         {};
62 
63         template<typename T BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = boost::proto::detail::template_arity<T>::value)>
64         struct is_callable_
65           : is_callable2_<T>
66         {};
67 
68     }
69 
70     /// \brief Boolean metafunction which detects whether a type is
71     /// a callable function object type or not.
72     ///
73     /// <tt>is_callable\<\></tt> is used by the <tt>when\<\></tt> transform
74     /// to determine whether a function type <tt>R(A1,A2,...AN)</tt> is a
75     /// callable transform or an object transform. (The former are evaluated
76     /// using <tt>call\<\></tt> and the later with <tt>make\<\></tt>.) If
77     /// <tt>is_callable\<R\>::value</tt> is \c true, the function type is
78     /// a callable transform; otherwise, it is an object transform.
79     ///
80     /// Unless specialized for a type \c T, <tt>is_callable\<T\>::value</tt>
81     /// is computed as follows:
82     ///
83     /// \li If \c T is a template type <tt>X\<Y0,Y1,...YN\></tt>, where all \c Yx
84     /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::value</tt>
85     /// is <tt>is_same\<YN, proto::callable\>::value</tt>.
86     /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef
87     /// for \c void, <tt>is_callable\<T\>::value</tt> is \c true. (Note: this is
88     /// the case for any type that derives from \c proto::callable.)
89     /// \li Otherwise, <tt>is_callable\<T\>::value</tt> is \c false.
90     template<typename T>
91     struct is_callable
92       : proto::detail::is_callable_<T>
93     {};
94 
95     /// INTERNAL ONLY
96     ///
97     template<>
98     struct is_callable<proto::_>
99       : mpl::true_
100     {};
101 
102     /// INTERNAL ONLY
103     ///
104     template<>
105     struct is_callable<proto::callable>
106       : mpl::false_
107     {};
108 
109     /// INTERNAL ONLY
110     ///
111     template<typename PrimitiveTransform, typename X>
112     struct is_callable<proto::transform<PrimitiveTransform, X> >
113       : mpl::false_
114     {};
115 
116     #if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
117     // work around GCC bug
118     template<typename Tag, typename Args, long N>
119     struct is_callable<proto::expr<Tag, Args, N> >
120       : mpl::false_
121     {};
122 
123     // work around GCC bug
124     template<typename Tag, typename Args, long N>
125     struct is_callable<proto::basic_expr<Tag, Args, N> >
126       : mpl::false_
127     {};
128     #endif
129 
130     /// \brief Boolean metafunction which detects whether a type is
131     /// a PrimitiveTransform type or not.
132     ///
133     /// <tt>is_transform\<\></tt> is used by the <tt>call\<\></tt> transform
134     /// to determine whether the function types <tt>R()</tt>, <tt>R(A1)</tt>,
135     /// and <tt>R(A1, A2)</tt> should be passed the expression, state and data
136     /// parameters (as needed).
137     ///
138     /// Unless specialized for a type \c T, <tt>is_transform\<T\>::value</tt>
139     /// is computed as follows:
140     ///
141     /// \li If \c T has a nested type \c proto_is_transform_ that is a typedef
142     /// for \c void, <tt>is_transform\<T\>::value</tt> is \c true. (Note: this is
143     /// the case for any type that derives from an instantiation of \c proto::transform.)
144     /// \li Otherwise, <tt>is_transform\<T\>::value</tt> is \c false.
145     template<typename T, typename Void /*= void*/>
146     struct is_transform
147       : mpl::false_
148     {};
149 
150     template<typename T>
151     struct is_transform<T, typename T::proto_is_transform_>
152       : mpl::true_
153     {};
154 
155     /// \brief A Boolean metafunction that indicates whether a type requires
156     /// aggregate initialization.
157     ///
158     /// <tt>is_aggregate\<\></tt> is used by the <tt>make\<\></tt> transform
159     /// to determine how to construct an object of some type \c T, given some
160     /// initialization arguments <tt>a0,a1,...aN</tt>.
161     /// If <tt>is_aggregate\<T\>::value</tt> is \c true, then an object of
162     /// type T will be initialized as <tt>T t = {a0,a1,...aN};</tt>. Otherwise,
163     /// it will be initialized as <tt>T t(a0,a1,...aN)</tt>.
164     template<typename T, typename Void>
165     struct is_aggregate
166       : is_pod<T>
167     {};
168 
169     /// \brief Specialization of <tt>is_aggregate\<\></tt> that indicates
170     /// that objects of <tt>expr\<\></tt> type require aggregate initialization.
171     template<typename Tag, typename Args, long N>
172     struct is_aggregate<proto::expr<Tag, Args, N>, void>
173       : mpl::true_
174     {};
175 
176     template<typename Tag, typename Args, long N>
177     struct is_aggregate<proto::basic_expr<Tag, Args, N>, void>
178       : mpl::true_
179     {};
180 
181     /// INTERNAL ONLY
182     template<typename T>
183     struct is_aggregate<T, typename T::proto_is_aggregate_>
184       : mpl::true_
185     {};
186 
187     /// \brief A Boolean metafunction that indicates whether a given
188     /// type \c T is a Proto expression type.
189     ///
190     /// If \c T has a nested type \c proto_is_expr_ that is a typedef
191     /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
192     /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
193     /// from <tt>proto::extends\<\></tt> or that uses the
194     /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
195     /// <tt>is_expr\<T\>::value</tt> is \c false.
196     template<typename T, typename Void /* = void*/>
197     struct is_expr
198       : mpl::false_
199     {};
200 
201     /// \brief A Boolean metafunction that indicates whether a given
202     /// type \c T is a Proto expression type.
203     ///
204     /// If \c T has a nested type \c proto_is_expr_ that is a typedef
205     /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
206     /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
207     /// from <tt>proto::extends\<\></tt> or that uses the
208     /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
209     /// <tt>is_expr\<T\>::value</tt> is \c false.
210     template<typename T>
211     struct is_expr<T, typename T::proto_is_expr_>
212       : mpl::true_
213     {};
214 
215     template<typename T>
216     struct is_expr<T &, void>
217       : is_expr<T>
218     {};
219 
220     /// \brief A metafunction that returns the tag type of a
221     /// Proto expression.
222     template<typename Expr>
223     struct tag_of
224     {
225         typedef typename Expr::proto_tag type;
226     };
227 
228     template<typename Expr>
229     struct tag_of<Expr &>
230     {
231         typedef typename Expr::proto_tag type;
232     };
233 
234     /// \brief A metafunction that returns the arity of a
235     /// Proto expression.
236     template<typename Expr>
237     struct arity_of
238       : Expr::proto_arity
239     {};
240 
241     template<typename Expr>
242     struct arity_of<Expr &>
243       : Expr::proto_arity
244     {};
245 
246     namespace result_of
247     {
248         /// \brief A metafunction that computes the return type of the \c as_expr()
249         /// function.
250         template<typename T, typename Domain /*= default_domain*/>
251         struct as_expr
252         {
253             typedef typename Domain::template as_expr<T>::result_type type;
254         };
255 
256         /// \brief A metafunction that computes the return type of the \c as_child()
257         /// function.
258         template<typename T, typename Domain /*= default_domain*/>
259         struct as_child
260         {
261             typedef typename Domain::template as_child<T>::result_type type;
262         };
263 
264         /// \brief A metafunction that returns the type of the Nth child
265         /// of a Proto expression, where N is an MPL Integral Constant.
266         ///
267         /// <tt>result_of::child\<Expr, N\></tt> is equivalent to
268         /// <tt>result_of::child_c\<Expr, N::value\></tt>.
269         template<typename Expr, typename N /* = mpl::long_<0>*/>
270         struct child
271           : child_c<Expr, N::value>
272         {};
273 
274         /// \brief A metafunction that returns the type of the value
275         /// of a terminal Proto expression.
276         ///
277         template<typename Expr>
278         struct value
279         {
280             /// Verify that we are actually operating on a terminal
281             BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
282 
283             /// The raw type of the Nth child as it is stored within
284             /// \c Expr. This may be a value or a reference
285             typedef typename Expr::proto_child0 value_type;
286 
287             /// The "value" type of the child, suitable for storage by value,
288             /// computed as follows:
289             /// \li <tt>T const(&)[N]</tt> becomes <tt>T[N]</tt>
290             /// \li <tt>T[N]</tt> becomes <tt>T[N]</tt>
291             /// \li <tt>T(&)[N]</tt> becomes <tt>T[N]</tt>
292             /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
293             /// \li <tt>T const &</tt> becomes <tt>T</tt>
294             /// \li <tt>T &</tt> becomes <tt>T</tt>
295             /// \li <tt>T</tt> becomes <tt>T</tt>
296             typedef typename detail::term_traits<typename Expr::proto_child0>::value_type type;
297         };
298 
299         template<typename Expr>
300         struct value<Expr &>
301         {
302             /// Verify that we are actually operating on a terminal
303             BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
304 
305             /// The raw type of the Nth child as it is stored within
306             /// \c Expr. This may be a value or a reference
307             typedef typename Expr::proto_child0 value_type;
308 
309             /// The "reference" type of the child, suitable for storage by
310             /// reference, computed as follows:
311             /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt>
312             /// \li <tt>T[N]</tt> becomes <tt>T(&)[N]</tt>
313             /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt>
314             /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
315             /// \li <tt>T const &</tt> becomes <tt>T const &</tt>
316             /// \li <tt>T &</tt> becomes <tt>T &</tt>
317             /// \li <tt>T</tt> becomes <tt>T &</tt>
318             typedef typename detail::term_traits<typename Expr::proto_child0>::reference type;
319         };
320 
321         template<typename Expr>
322         struct value<Expr const &>
323         {
324             /// Verify that we are actually operating on a terminal
325             BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
326 
327             /// The raw type of the Nth child as it is stored within
328             /// \c Expr. This may be a value or a reference
329             typedef typename Expr::proto_child0 value_type;
330 
331             /// The "const reference" type of the child, suitable for storage by
332             /// const reference, computed as follows:
333             /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt>
334             /// \li <tt>T[N]</tt> becomes <tt>T const(&)[N]</tt>
335             /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt>
336             /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
337             /// \li <tt>T const &</tt> becomes <tt>T const &</tt>
338             /// \li <tt>T &</tt> becomes <tt>T &</tt>
339             /// \li <tt>T</tt> becomes <tt>T const &</tt>
340             typedef typename detail::term_traits<typename Expr::proto_child0>::const_reference type;
341         };
342 
343         /// \brief A metafunction that returns the type of the left child
344         /// of a binary Proto expression.
345         ///
346         /// <tt>result_of::left\<Expr\></tt> is equivalent to
347         /// <tt>result_of::child_c\<Expr, 0\></tt>.
348         template<typename Expr>
349         struct left
350           : child_c<Expr, 0>
351         {};
352 
353         /// \brief A metafunction that returns the type of the right child
354         /// of a binary Proto expression.
355         ///
356         /// <tt>result_of::right\<Expr\></tt> is equivalent to
357         /// <tt>result_of::child_c\<Expr, 1\></tt>.
358         template<typename Expr>
359         struct right
360           : child_c<Expr, 1>
361         {};
362 
363     } // namespace result_of
364 
365     /// \brief A metafunction for generating terminal expression types,
366     /// a grammar element for matching terminal expressions, and a
367     /// PrimitiveTransform that returns the current expression unchanged.
368     template<typename T>
369     struct terminal
370       : proto::transform<terminal<T>, int>
371     {
372         typedef proto::expr<proto::tag::terminal, term<T>, 0> type;
373         typedef proto::basic_expr<proto::tag::terminal, term<T>, 0> proto_grammar;
374 
375         template<typename Expr, typename State, typename Data>
376         struct impl : transform_impl<Expr, State, Data>
377         {
378             typedef Expr result_type;
379 
380             /// \param e The current expression
381             /// \pre <tt>matches\<Expr, terminal\<T\> \>::value</tt> is \c true.
382             /// \return \c e
383             /// \throw nothrow
384             #ifdef BOOST_PROTO_STRICT_RESULT_OF
385             result_type
386             #else
387             typename impl::expr_param
388             #endif
operator ()boost::proto::terminal::impl389             operator ()(
390                 typename impl::expr_param e
391               , typename impl::state_param
392               , typename impl::data_param
393             ) const
394             {
395                 return e;
396             }
397         };
398 
399         /// INTERNAL ONLY
400         typedef proto::tag::terminal proto_tag;
401         /// INTERNAL ONLY
402         typedef T proto_child0;
403     };
404 
405     /// \brief A metafunction for generating ternary conditional expression types,
406     /// a grammar element for matching ternary conditional expressions, and a
407     /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
408     /// transform.
409     template<typename T, typename U, typename V>
410     struct if_else_
411       : proto::transform<if_else_<T, U, V>, int>
412     {
413         typedef proto::expr<proto::tag::if_else_, list3<T, U, V>, 3> type;
414         typedef proto::basic_expr<proto::tag::if_else_, list3<T, U, V>, 3> proto_grammar;
415 
416         template<typename Expr, typename State, typename Data>
417         struct impl
418           : detail::pass_through_impl<if_else_, Expr, State, Data>
419         {};
420 
421         /// INTERNAL ONLY
422         typedef proto::tag::if_else_ proto_tag;
423         /// INTERNAL ONLY
424         typedef T proto_child0;
425         /// INTERNAL ONLY
426         typedef U proto_child1;
427         /// INTERNAL ONLY
428         typedef V proto_child2;
429     };
430 
431     /// \brief A metafunction for generating nullary expression types with a
432     /// specified tag type,
433     /// a grammar element for matching nullary expressions, and a
434     /// PrimitiveTransform that returns the current expression unchanged.
435     ///
436     /// Use <tt>nullary_expr\<_, _\></tt> as a grammar element to match any
437     /// nullary expression.
438     template<typename Tag, typename T>
439     struct nullary_expr
440       : proto::transform<nullary_expr<Tag, T>, int>
441     {
442         typedef proto::expr<Tag, term<T>, 0> type;
443         typedef proto::basic_expr<Tag, term<T>, 0> proto_grammar;
444 
445         template<typename Expr, typename State, typename Data>
446         struct impl : transform_impl<Expr, State, Data>
447         {
448             typedef Expr result_type;
449 
450             /// \param e The current expression
451             /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::value</tt> is \c true.
452             /// \return \c e
453             /// \throw nothrow
454             #ifdef BOOST_PROTO_STRICT_RESULT_OF
455             result_type
456             #else
457             typename impl::expr_param
458             #endif
operator ()boost::proto::nullary_expr::impl459             operator ()(
460                 typename impl::expr_param e
461               , typename impl::state_param
462               , typename impl::data_param
463             ) const
464             {
465                 return e;
466             }
467         };
468 
469         /// INTERNAL ONLY
470         typedef Tag proto_tag;
471         /// INTERNAL ONLY
472         typedef T proto_child0;
473     };
474 
475     /// \brief A metafunction for generating unary expression types with a
476     /// specified tag type,
477     /// a grammar element for matching unary expressions, and a
478     /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
479     /// transform.
480     ///
481     /// Use <tt>unary_expr\<_, _\></tt> as a grammar element to match any
482     /// unary expression.
483     template<typename Tag, typename T>
484     struct unary_expr
485       : proto::transform<unary_expr<Tag, T>, int>
486     {
487         typedef proto::expr<Tag, list1<T>, 1> type;
488         typedef proto::basic_expr<Tag, list1<T>, 1> proto_grammar;
489 
490         template<typename Expr, typename State, typename Data>
491         struct impl
492           : detail::pass_through_impl<unary_expr, Expr, State, Data>
493         {};
494 
495         /// INTERNAL ONLY
496         typedef Tag proto_tag;
497         /// INTERNAL ONLY
498         typedef T proto_child0;
499     };
500 
501     /// \brief A metafunction for generating binary expression types with a
502     /// specified tag type,
503     /// a grammar element for matching binary expressions, and a
504     /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
505     /// transform.
506     ///
507     /// Use <tt>binary_expr\<_, _, _\></tt> as a grammar element to match any
508     /// binary expression.
509     template<typename Tag, typename T, typename U>
510     struct binary_expr
511       : proto::transform<binary_expr<Tag, T, U>, int>
512     {
513         typedef proto::expr<Tag, list2<T, U>, 2> type;
514         typedef proto::basic_expr<Tag, list2<T, U>, 2> proto_grammar;
515 
516         template<typename Expr, typename State, typename Data>
517         struct impl
518           : detail::pass_through_impl<binary_expr, Expr, State, Data>
519         {};
520 
521         /// INTERNAL ONLY
522         typedef Tag proto_tag;
523         /// INTERNAL ONLY
524         typedef T proto_child0;
525         /// INTERNAL ONLY
526         typedef U proto_child1;
527     };
528 
529 #define BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(Op)                                               \
530     template<typename T>                                                                        \
531     struct Op                                                                                   \
532       : proto::transform<Op<T>, int>                                                            \
533     {                                                                                           \
534         typedef proto::expr<proto::tag::Op, list1<T>, 1> type;                                  \
535         typedef proto::basic_expr<proto::tag::Op, list1<T>, 1> proto_grammar;                   \
536                                                                                                 \
537         template<typename Expr, typename State, typename Data>                                  \
538         struct impl                                                                             \
539           : detail::pass_through_impl<Op, Expr, State, Data>                                    \
540         {};                                                                                     \
541                                                                                                 \
542         typedef proto::tag::Op proto_tag;                                                       \
543         typedef T proto_child0;                                                                 \
544     };                                                                                          \
545     /**/
546 
547 #define BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(Op)                                              \
548     template<typename T, typename U>                                                            \
549     struct Op                                                                                   \
550       : proto::transform<Op<T, U>, int>                                                         \
551     {                                                                                           \
552         typedef proto::expr<proto::tag::Op, list2<T, U>, 2> type;                               \
553         typedef proto::basic_expr<proto::tag::Op, list2<T, U>, 2> proto_grammar;                \
554                                                                                                 \
555         template<typename Expr, typename State, typename Data>                                  \
556         struct impl                                                                             \
557           : detail::pass_through_impl<Op, Expr, State, Data>                                    \
558         {};                                                                                     \
559                                                                                                 \
560         typedef proto::tag::Op proto_tag;                                                       \
561         typedef T proto_child0;                                                                 \
562         typedef U proto_child1;                                                                 \
563     };                                                                                          \
564     /**/
565 
566     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(unary_plus)
567     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(negate)
568     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(dereference)
569     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(complement)
570     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(address_of)
571     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(logical_not)
572     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_inc)
573     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_dec)
574     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_inc)
575     BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_dec)
576 
577     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left)
578     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right)
579     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies)
580     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides)
581     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus)
582     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus)
583     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus)
584     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less)
585     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater)
586     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less_equal)
587     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater_equal)
588     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(equal_to)
589     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(not_equal_to)
590     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_or)
591     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_and)
592     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or)
593     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and)
594     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor)
595     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(comma)
596     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(mem_ptr)
597     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(assign)
598     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left_assign)
599     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right_assign)
600     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies_assign)
601     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides_assign)
602     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus_assign)
603     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus_assign)
604     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus_assign)
605     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign)
606     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign)
607     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign)
608     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(subscript)
609     BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(member)
610 
611     #undef BOOST_PROTO_DEFINE_UNARY_METAFUNCTION
612     #undef BOOST_PROTO_DEFINE_BINARY_METAFUNCTION
613 
614     #include <boost/proto/detail/traits.hpp>
615 
616     namespace functional
617     {
618         /// \brief A callable PolymorphicFunctionObject that is
619         /// equivalent to the \c as_expr() function.
620         template<typename Domain   /* = default_domain*/>
621         struct as_expr
622         {
623             BOOST_PROTO_CALLABLE()
624 
625             template<typename Sig>
626             struct result;
627 
628             template<typename This, typename T>
629             struct result<This(T)>
630             {
631                 typedef typename Domain::template as_expr<T>::result_type type;
632             };
633 
634             template<typename This, typename T>
635             struct result<This(T &)>
636             {
637                 typedef typename Domain::template as_expr<T>::result_type type;
638             };
639 
640             /// \brief Wrap an object in a Proto terminal if it isn't a
641             /// Proto expression already.
642             /// \param t The object to wrap.
643             /// \return <tt>proto::as_expr\<Domain\>(t)</tt>
644             template<typename T>
645             typename add_const<typename result<as_expr(T &)>::type>::type
operator ()boost::proto::functional::as_expr646             operator ()(T &t) const
647             {
648                 return typename Domain::template as_expr<T>()(t);
649             }
650 
651             /// \overload
652             ///
653             template<typename T>
654             typename add_const<typename result<as_expr(T const &)>::type>::type
operator ()boost::proto::functional::as_expr655             operator ()(T const &t) const
656             {
657                 return typename Domain::template as_expr<T const>()(t);
658             }
659 
660             #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
661             template<typename T, std::size_t N_>
662             typename add_const<typename result<as_expr(T (&)[N_])>::type>::type
operator ()boost::proto::functional::as_expr663             operator ()(T (&t)[N_]) const
664             {
665                 return typename Domain::template as_expr<T[N_]>()(t);
666             }
667 
668             template<typename T, std::size_t N_>
669             typename add_const<typename result<as_expr(T const (&)[N_])>::type>::type
operator ()boost::proto::functional::as_expr670             operator ()(T const (&t)[N_]) const
671             {
672                 return typename Domain::template as_expr<T const[N_]>()(t);
673             }
674             #endif
675         };
676 
677         /// \brief A callable PolymorphicFunctionObject that is
678         /// equivalent to the \c as_child() function.
679         template<typename Domain   /* = default_domain*/>
680         struct as_child
681         {
682             BOOST_PROTO_CALLABLE()
683 
684             template<typename Sig>
685             struct result;
686 
687             template<typename This, typename T>
688             struct result<This(T)>
689             {
690                 typedef typename Domain::template as_child<T>::result_type type;
691             };
692 
693             template<typename This, typename T>
694             struct result<This(T &)>
695             {
696                 typedef typename Domain::template as_child<T>::result_type type;
697             };
698 
699             /// \brief Wrap an object in a Proto terminal if it isn't a
700             /// Proto expression already.
701             /// \param t The object to wrap.
702             /// \return <tt>proto::as_child\<Domain\>(t)</tt>
703             template<typename T>
704             typename add_const<typename result<as_child(T &)>::type>::type
operator ()boost::proto::functional::as_child705             operator ()(T &t) const
706             {
707                 return typename Domain::template as_child<T>()(t);
708             }
709 
710             /// \overload
711             ///
712             template<typename T>
713             typename add_const<typename result<as_child(T const &)>::type>::type
operator ()boost::proto::functional::as_child714             operator ()(T const &t) const
715             {
716                 return typename Domain::template as_child<T const>()(t);
717             }
718         };
719 
720         /// \brief A callable PolymorphicFunctionObject that is
721         /// equivalent to the \c child_c() function.
722         template<long N>
723         struct child_c
724         {
725             BOOST_PROTO_CALLABLE()
726 
727             template<typename Sig>
728             struct result;
729 
730             template<typename This, typename Expr>
731             struct result<This(Expr)>
732             {
733                 typedef typename result_of::child_c<Expr, N>::type type;
734             };
735 
736             /// \brief Return the Nth child of the given expression.
737             /// \param expr The expression node.
738             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
739             /// \pre <tt>N \< Expr::proto_arity::value</tt>
740             /// \return <tt>proto::child_c\<N\>(expr)</tt>
741             /// \throw nothrow
742             template<typename Expr>
743             typename result_of::child_c<Expr &, N>::type
operator ()boost::proto::functional::child_c744             operator ()(Expr &e) const
745             {
746                 return result_of::child_c<Expr &, N>::call(e);
747             }
748 
749             /// \overload
750             ///
751             template<typename Expr>
752             typename result_of::child_c<Expr const &, N>::type
operator ()boost::proto::functional::child_c753             operator ()(Expr const &e) const
754             {
755                 return result_of::child_c<Expr const &, N>::call(e);
756             }
757         };
758 
759         /// \brief A callable PolymorphicFunctionObject that is
760         /// equivalent to the \c child() function.
761         ///
762         /// A callable PolymorphicFunctionObject that is
763         /// equivalent to the \c child() function. \c N is required
764         /// to be an MPL Integral Constant.
765         template<typename N /* = mpl::long_<0>*/>
766         struct child
767         {
768             BOOST_PROTO_CALLABLE()
769 
770             template<typename Sig>
771             struct result;
772 
773             template<typename This, typename Expr>
774             struct result<This(Expr)>
775             {
776                 typedef typename result_of::child<Expr, N>::type type;
777             };
778 
779             /// \brief Return the Nth child of the given expression.
780             /// \param expr The expression node.
781             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
782             /// \pre <tt>N::value \< Expr::proto_arity::value</tt>
783             /// \return <tt>proto::child\<N\>(expr)</tt>
784             /// \throw nothrow
785             template<typename Expr>
786             typename result_of::child<Expr &, N>::type
operator ()boost::proto::functional::child787             operator ()(Expr &e) const
788             {
789                 return result_of::child<Expr &, N>::call(e);
790             }
791 
792             /// \overload
793             ///
794             template<typename Expr>
795             typename result_of::child<Expr const &, N>::type
operator ()boost::proto::functional::child796             operator ()(Expr const &e) const
797             {
798                 return result_of::child<Expr const &, N>::call(e);
799             }
800         };
801 
802         /// \brief A callable PolymorphicFunctionObject that is
803         /// equivalent to the \c value() function.
804         struct value
805         {
806             BOOST_PROTO_CALLABLE()
807 
808             template<typename Sig>
809             struct result;
810 
811             template<typename This, typename Expr>
812             struct result<This(Expr)>
813             {
814                 typedef typename result_of::value<Expr>::type type;
815             };
816 
817             /// \brief Return the value of the given terminal expression.
818             /// \param expr The terminal expression node.
819             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
820             /// \pre <tt>0 == Expr::proto_arity::value</tt>
821             /// \return <tt>proto::value(expr)</tt>
822             /// \throw nothrow
823             template<typename Expr>
824             typename result_of::value<Expr &>::type
operator ()boost::proto::functional::value825             operator ()(Expr &e) const
826             {
827                 return e.proto_base().child0;
828             }
829 
830             /// \overload
831             ///
832             template<typename Expr>
833             typename result_of::value<Expr const &>::type
operator ()boost::proto::functional::value834             operator ()(Expr const &e) const
835             {
836                 return e.proto_base().child0;
837             }
838         };
839 
840         /// \brief A callable PolymorphicFunctionObject that is
841         /// equivalent to the \c left() function.
842         struct left
843         {
844             BOOST_PROTO_CALLABLE()
845 
846             template<typename Sig>
847             struct result;
848 
849             template<typename This, typename Expr>
850             struct result<This(Expr)>
851             {
852                 typedef typename result_of::left<Expr>::type type;
853             };
854 
855             /// \brief Return the left child of the given binary expression.
856             /// \param expr The expression node.
857             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
858             /// \pre <tt>2 == Expr::proto_arity::value</tt>
859             /// \return <tt>proto::left(expr)</tt>
860             /// \throw nothrow
861             template<typename Expr>
862             typename result_of::left<Expr &>::type
operator ()boost::proto::functional::left863             operator ()(Expr &e) const
864             {
865                 return e.proto_base().child0;
866             }
867 
868             /// \overload
869             ///
870             template<typename Expr>
871             typename result_of::left<Expr const &>::type
operator ()boost::proto::functional::left872             operator ()(Expr const &e) const
873             {
874                 return e.proto_base().child0;
875             }
876         };
877 
878         /// \brief A callable PolymorphicFunctionObject that is
879         /// equivalent to the \c right() function.
880         struct right
881         {
882             BOOST_PROTO_CALLABLE()
883 
884             template<typename Sig>
885             struct result;
886 
887             template<typename This, typename Expr>
888             struct result<This(Expr)>
889             {
890                 typedef typename result_of::right<Expr>::type type;
891             };
892 
893             /// \brief Return the right child of the given binary expression.
894             /// \param expr The expression node.
895             /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
896             /// \pre <tt>2 == Expr::proto_arity::value</tt>
897             /// \return <tt>proto::right(expr)</tt>
898             /// \throw nothrow
899             template<typename Expr>
900             typename result_of::right<Expr &>::type
operator ()boost::proto::functional::right901             operator ()(Expr &e) const
902             {
903                 return e.proto_base().child1;
904             }
905 
906             template<typename Expr>
907             typename result_of::right<Expr const &>::type
operator ()boost::proto::functional::right908             operator ()(Expr const &e) const
909             {
910                 return e.proto_base().child1;
911             }
912         };
913 
914     }
915 
916     /// \brief A function that wraps non-Proto expression types in Proto
917     /// terminals and leaves Proto expression types alone.
918     ///
919     /// The <tt>as_expr()</tt> function turns objects into Proto terminals if
920     /// they are not Proto expression types already. Non-Proto types are
921     /// held by value, if possible. Types which are already Proto types are
922     /// left alone and returned by reference.
923     ///
924     /// This function can be called either with an explicitly specified
925     /// \c Domain parameter (i.e., <tt>as_expr\<Domain\>(t)</tt>), or
926     /// without (i.e., <tt>as_expr(t)</tt>). If no domain is
927     /// specified, \c default_domain is assumed.
928     ///
929     /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is
930     /// returned unmodified, by reference. Otherwise, the argument is wrapped
931     /// in a Proto terminal expression node according to the following rules.
932     /// If \c T is a function type, let \c A be <tt>T &</tt>. Otherwise, let
933     /// \c A be the type \c T stripped of cv-qualifiers. Then, \c as_expr()
934     /// returns <tt>Domain()(terminal\<A\>::type::make(t))</tt>.
935     ///
936     /// \param t The object to wrap.
937     template<typename T>
938     typename add_const<typename result_of::as_expr<T, default_domain>::type>::type
as_expr(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))939     as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
940     {
941         return default_domain::as_expr<T>()(t);
942     }
943 
944     /// \overload
945     ///
946     template<typename T>
947     typename add_const<typename result_of::as_expr<T const, default_domain>::type>::type
as_expr(T const & t)948     as_expr(T const &t)
949     {
950         return default_domain::as_expr<T const>()(t);
951     }
952 
953     /// \overload
954     ///
955     template<typename Domain, typename T>
956     typename add_const<typename result_of::as_expr<T, Domain>::type>::type
as_expr(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))957     as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
958     {
959         return typename Domain::template as_expr<T>()(t);
960     }
961 
962     /// \overload
963     ///
964     template<typename Domain, typename T>
965     typename add_const<typename result_of::as_expr<T const, Domain>::type>::type
as_expr(T const & t)966     as_expr(T const &t)
967     {
968         return typename Domain::template as_expr<T const>()(t);
969     }
970 
971     /// \brief A function that wraps non-Proto expression types in Proto
972     /// terminals (by reference) and returns Proto expression types by
973     /// reference
974     ///
975     /// The <tt>as_child()</tt> function turns objects into Proto terminals if
976     /// they are not Proto expression types already. Non-Proto types are
977     /// held by reference. Types which are already Proto types are simply
978     /// returned as-is.
979     ///
980     /// This function can be called either with an explicitly specified
981     /// \c Domain parameter (i.e., <tt>as_child\<Domain\>(t)</tt>), or
982     /// without (i.e., <tt>as_child(t)</tt>). If no domain is
983     /// specified, \c default_domain is assumed.
984     ///
985     /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is
986     /// returned as-is. Otherwise, \c as_child() returns
987     /// <tt>Domain()(terminal\<T &\>::type::make(t))</tt>.
988     ///
989     /// \param t The object to wrap.
990     template<typename T>
991     typename add_const<typename result_of::as_child<T, default_domain>::type>::type
as_child(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))992     as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
993     {
994         return default_domain::as_child<T>()(t);
995     }
996 
997     /// \overload
998     ///
999     template<typename T>
1000     typename add_const<typename result_of::as_child<T const, default_domain>::type>::type
as_child(T const & t)1001     as_child(T const &t)
1002     {
1003         return default_domain::as_child<T const>()(t);
1004     }
1005 
1006     /// \overload
1007     ///
1008     template<typename Domain, typename T>
1009     typename add_const<typename result_of::as_child<T, Domain>::type>::type
as_child(T & t BOOST_PROTO_DISABLE_IF_IS_CONST (T)BOOST_PROTO_DISABLE_IF_IS_FUNCTION (T))1010     as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
1011     {
1012         return typename Domain::template as_child<T>()(t);
1013     }
1014 
1015     /// \overload
1016     ///
1017     template<typename Domain, typename T>
1018     typename add_const<typename result_of::as_child<T const, Domain>::type>::type
as_child(T const & t)1019     as_child(T const &t)
1020     {
1021         return typename Domain::template as_child<T const>()(t);
1022     }
1023 
1024     /// \brief Return the Nth child of the specified Proto expression.
1025     ///
1026     /// Return the Nth child of the specified Proto expression. If
1027     /// \c N is not specified, as in \c child(expr), then \c N is assumed
1028     /// to be <tt>mpl::long_\<0\></tt>. The child is returned by
1029     /// reference.
1030     ///
1031     /// \param expr The Proto expression.
1032     /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
1033     /// \pre \c N is an MPL Integral Constant.
1034     /// \pre <tt>N::value \< Expr::proto_arity::value</tt>
1035     /// \throw nothrow
1036     /// \return A reference to the Nth child
1037     template<typename N, typename Expr>
1038     typename result_of::child<Expr &, N>::type
child(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1039     child(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1040     {
1041         return result_of::child<Expr &, N>::call(e);
1042     }
1043 
1044     /// \overload
1045     ///
1046     template<typename N, typename Expr>
1047     typename result_of::child<Expr const &, N>::type
child(Expr const & e)1048     child(Expr const &e)
1049     {
1050         return result_of::child<Expr const &, N>::call(e);
1051     }
1052 
1053     /// \overload
1054     ///
1055     template<typename Expr2>
1056     typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::reference
child(Expr2 & expr2 BOOST_PROTO_DISABLE_IF_IS_CONST (Expr2))1057     child(Expr2 &expr2 BOOST_PROTO_DISABLE_IF_IS_CONST(Expr2))
1058     {
1059         return expr2.proto_base().child0;
1060     }
1061 
1062     /// \overload
1063     ///
1064     template<typename Expr2>
1065     typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::const_reference
child(Expr2 const & expr2)1066     child(Expr2 const &expr2)
1067     {
1068         return expr2.proto_base().child0;
1069     }
1070 
1071     /// \brief Return the Nth child of the specified Proto expression.
1072     ///
1073     /// Return the Nth child of the specified Proto expression. The child
1074     /// is returned by reference.
1075     ///
1076     /// \param expr The Proto expression.
1077     /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
1078     /// \pre <tt>N \< Expr::proto_arity::value</tt>
1079     /// \throw nothrow
1080     /// \return A reference to the Nth child
1081     template<long N, typename Expr>
1082     typename result_of::child_c<Expr &, N>::type
child_c(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1083     child_c(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1084     {
1085         return result_of::child_c<Expr &, N>::call(e);
1086     }
1087 
1088     /// \overload
1089     ///
1090     template<long N, typename Expr>
1091     typename result_of::child_c<Expr const &, N>::type
child_c(Expr const & e)1092     child_c(Expr const &e)
1093     {
1094         return result_of::child_c<Expr const &, N>::call(e);
1095     }
1096 
1097     /// \brief Return the value stored within the specified Proto
1098     /// terminal expression.
1099     ///
1100     /// Return the the value stored within the specified Proto
1101     /// terminal expression. The value is returned by
1102     /// reference.
1103     ///
1104     /// \param expr The Proto terminal expression.
1105     /// \pre <tt>N::value == 0</tt>
1106     /// \throw nothrow
1107     /// \return A reference to the terminal's value
1108     template<typename Expr>
1109     typename result_of::value<Expr &>::type
value(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1110     value(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1111     {
1112         return e.proto_base().child0;
1113     }
1114 
1115     /// \overload
1116     ///
1117     template<typename Expr>
1118     typename result_of::value<Expr const &>::type
value(Expr const & e)1119     value(Expr const &e)
1120     {
1121         return e.proto_base().child0;
1122     }
1123 
1124     /// \brief Return the left child of the specified binary Proto
1125     /// expression.
1126     ///
1127     /// Return the left child of the specified binary Proto expression. The
1128     /// child is returned by reference.
1129     ///
1130     /// \param expr The Proto expression.
1131     /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
1132     /// \pre <tt>2 == Expr::proto_arity::value</tt>
1133     /// \throw nothrow
1134     /// \return A reference to the left child
1135     template<typename Expr>
1136     typename result_of::left<Expr &>::type
left(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1137     left(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1138     {
1139         return e.proto_base().child0;
1140     }
1141 
1142     /// \overload
1143     ///
1144     template<typename Expr>
1145     typename result_of::left<Expr const &>::type
left(Expr const & e)1146     left(Expr const &e)
1147     {
1148         return e.proto_base().child0;
1149     }
1150 
1151     /// \brief Return the right child of the specified binary Proto
1152     /// expression.
1153     ///
1154     /// Return the right child of the specified binary Proto expression. The
1155     /// child is returned by reference.
1156     ///
1157     /// \param expr The Proto expression.
1158     /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
1159     /// \pre <tt>2 == Expr::proto_arity::value</tt>
1160     /// \throw nothrow
1161     /// \return A reference to the right child
1162     template<typename Expr>
1163     typename result_of::right<Expr &>::type
right(Expr & e BOOST_PROTO_DISABLE_IF_IS_CONST (Expr))1164     right(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
1165     {
1166         return e.proto_base().child1;
1167     }
1168 
1169     /// \overload
1170     ///
1171     template<typename Expr>
1172     typename result_of::right<Expr const &>::type
right(Expr const & e)1173     right(Expr const &e)
1174     {
1175         return e.proto_base().child1;
1176     }
1177 
1178     /// INTERNAL ONLY
1179     ///
1180     template<typename Domain>
1181     struct is_callable<functional::as_expr<Domain> >
1182       : mpl::true_
1183     {};
1184 
1185     /// INTERNAL ONLY
1186     ///
1187     template<typename Domain>
1188     struct is_callable<functional::as_child<Domain> >
1189       : mpl::true_
1190     {};
1191 
1192     /// INTERNAL ONLY
1193     ///
1194     template<long N>
1195     struct is_callable<functional::child_c<N> >
1196       : mpl::true_
1197     {};
1198 
1199     /// INTERNAL ONLY
1200     ///
1201     template<typename N>
1202     struct is_callable<functional::child<N> >
1203       : mpl::true_
1204     {};
1205 
1206 }}
1207 
1208 #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 )
1209     #pragma warning(pop)
1210 #endif
1211 
1212 #endif
1213