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

source code of boost/libs/proto/include/boost/proto/traits.hpp