1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file proto_fwd.hpp
3 /// Forward declarations of all of proto's public types and functions.
5 // Copyright 2008 Eric Niebler. Distributed under the Boost
6 // Software License, Version 1.0. (See accompanying file
7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_PROTO_FWD_HPP_EAN_04_01_2005
10 #define BOOST_PROTO_FWD_HPP_EAN_04_01_2005
14 #include <boost/config.hpp>
15 #include <boost/detail/workaround.hpp>
16 #include <boost/preprocessor/cat.hpp>
17 #include <boost/preprocessor/arithmetic/inc.hpp>
18 #include <boost/preprocessor/punctuation/comma.hpp>
19 #include <boost/preprocessor/repetition/enum_params.hpp>
20 #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
21 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
22 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
23 #include <boost/ref.hpp>
24 #include <boost/mpl/long.hpp>
25 #include <boost/type_traits/remove_const.hpp>
26 #include <boost/type_traits/remove_reference.hpp>
27 #include <boost/mpl/aux_/config/ttp.hpp>
28 #include <boost/utility/result_of.hpp>
30 #ifndef BOOST_PROTO_MAX_ARITY
31 # define BOOST_PROTO_MAX_ARITY 10
34 #ifndef BOOST_PROTO_MAX_LOGICAL_ARITY
35 # define BOOST_PROTO_MAX_LOGICAL_ARITY 10
38 #ifndef BOOST_PROTO_MAX_FUNCTION_CALL_ARITY
39 # define BOOST_PROTO_MAX_FUNCTION_CALL_ARITY BOOST_PROTO_MAX_ARITY
42 #if BOOST_PROTO_MAX_ARITY < 3
43 # error BOOST_PROTO_MAX_ARITY must be at least 3
46 #if BOOST_PROTO_MAX_FUNCTION_CALL_ARITY > BOOST_PROTO_MAX_ARITY
47 # error BOOST_PROTO_MAX_FUNCTION_CALL_ARITY cannot be larger than BOOST_PROTO_MAX_ARITY
50 #ifndef BOOST_PROTO_DONT_USE_PREPROCESSED_FILES
51 #if 10 < BOOST_PROTO_MAX_ARITY || \
52 10 < BOOST_PROTO_MAX_LOGICAL_ARITY || \
53 10 < BOOST_PROTO_MAX_FUNCTION_CALL_ARITY
54 #define BOOST_PROTO_DONT_USE_PREPROCESSED_FILES
58 #ifndef BOOST_PROTO_BROKEN_CONST_OVERLOADS
59 # if BOOST_WORKAROUND(__GNUC__, == 3) \
60 || BOOST_WORKAROUND(__EDG_VERSION__, BOOST_TESTED_AT(310))
61 # define BOOST_PROTO_BROKEN_CONST_OVERLOADS
65 #ifndef BOOST_PROTO_BROKEN_CONST_QUALIFIED_FUNCTIONS
66 # if BOOST_WORKAROUND(__GNUC__, == 3) \
67 || BOOST_WORKAROUND(__EDG_VERSION__, BOOST_TESTED_AT(310))
68 # define BOOST_PROTO_BROKEN_CONST_QUALIFIED_FUNCTIONS
72 #ifdef BOOST_PROTO_BROKEN_CONST_OVERLOADS
73 # include <boost/utility/enable_if.hpp>
74 # include <boost/type_traits/is_const.hpp>
75 # define BOOST_PROTO_DISABLE_IF_IS_CONST(T)\
76 , typename boost::disable_if_c<boost::is_const<T>::value, boost::proto::detail::undefined>::type * = 0
78 # define BOOST_PROTO_DISABLE_IF_IS_CONST(T)
81 #ifdef BOOST_PROTO_BROKEN_CONST_QUALIFIED_FUNCTIONS
82 # include <boost/utility/enable_if.hpp>
83 # include <boost/type_traits/is_function.hpp>
84 # define BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)\
85 , typename boost::disable_if_c<boost::is_function<T>::value, boost::proto::detail::undefined>::type * = 0
87 # define BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)
90 #ifndef BOOST_PROTO_BROKEN_PTS
91 # if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
92 # define BOOST_PROTO_BROKEN_PTS
96 #ifdef BOOST_NO_CXX11_DECLTYPE_N3276
97 # // Proto can only use the decltype-based result_of if N3276 has been
98 # // implemented by the compiler.
99 # // See http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf
100 # ifndef BOOST_PROTO_USE_NORMAL_RESULT_OF
101 # define BOOST_PROTO_USE_NORMAL_RESULT_OF
105 // Unless compiler support is there, use tr1_result_of instead of
106 // result_of to avoid the problems addressed by N3276.
107 #ifdef BOOST_PROTO_USE_NORMAL_RESULT_OF
108 # define BOOST_PROTO_RESULT_OF boost::result_of
110 # define BOOST_PROTO_RESULT_OF boost::tr1_result_of
113 // If we're using the decltype-based result_of, we need to be a bit
114 // stricter about the return types of some functions.
115 #if defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_PROTO_USE_NORMAL_RESULT_OF)
116 # define BOOST_PROTO_STRICT_RESULT_OF
117 # define BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(X, Y) X
119 # define BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(X, Y) Y
122 #ifdef BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING
123 # define BOOST_PROTO_EXTENDED_TEMPLATE_PARAMETERS_MATCHING
126 #if defined(_MSC_VER)
127 # define BOOST_PROTO_PUSH_WARNINGS __pragma(warning(push))
128 # define BOOST_PROTO_POP_WARNINGS __pragma(warning(pop))
129 # define BOOST_PROTO_DISABLE_MSVC_C4180 __pragma(warning(disable : 4180)) // qualifier applied to function type has no meaning; ignored
130 # define BOOST_PROTO_DISABLE_MSVC_C4522 __pragma(warning(disable : 4522)) // 'class' : multiple assignment operators specified
131 # define BOOST_PROTO_DISABLE_MSVC_C4714 __pragma(warning(disable : 4714)) // function 'xxx' marked as __forceinline not inlined
133 # define BOOST_PROTO_PUSH_WARNINGS
134 # define BOOST_PROTO_POP_WARNINGS
135 # define BOOST_PROTO_DISABLE_MSVC_C4180
136 # define BOOST_PROTO_DISABLE_MSVC_C4522
137 # define BOOST_PROTO_DISABLE_MSVC_C4714
140 namespace boost { namespace proto
144 typedef char yes_type;
145 typedef char (&no_type)[2];
150 typedef char (&type)[N];
154 struct undefined; // leave this undefined
155 struct not_a_valid_type;
159 private_type_ operator ,(int) const;
169 struct uncvref<T const>
181 struct uncvref<T const &>
186 template<typename T, std::size_t N>
187 struct uncvref<T const[N]>
192 template<typename T, std::size_t N>
193 struct uncvref<T (&)[N]>
198 template<typename T, std::size_t N>
199 struct uncvref<T const (&)[N]>
216 #define BOOST_PROTO_UNCVREF(X) \
217 typename boost::proto::detail::uncvref<X>::type \
223 struct not_a_grammar;
224 struct not_a_generator;
226 template<typename T, typename Void = void>
227 struct is_transform_;
229 template<typename T, typename Void = void>
230 struct is_aggregate_;
232 template<typename Expr>
236 typedef detail::ignore const ignore;
240 template<typename Arg0>
243 #define M0(Z, N, DATA) \
244 template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename Arg)> struct BOOST_PP_CAT(list, N); \
246 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M0, ~)
250 using namespace argsns_;
252 ///////////////////////////////////////////////////////////////////////////////
280 struct greater_equal;
292 struct shift_left_assign;
293 struct shift_right_assign;
294 struct multiplies_assign;
295 struct divides_assign;
296 struct modulus_assign;
299 struct bitwise_and_assign;
300 struct bitwise_or_assign;
301 struct bitwise_xor_assign;
308 template<typename Tag, typename Domain> struct proto_expr;
309 template<typename Tag, typename Domain> struct proto_expr_iterator;
310 template<typename Tag, typename Domain> struct proto_flat_view;
314 using namespace tagns_;
316 template<typename Expr>
319 ////////////////////////////////////////////////////////////////////////////////////////////////
322 ////////////////////////////////////////////////////////////////////////////////////////////////
323 struct default_generator;
325 struct basic_default_generator;
327 template<template<typename> class Extends>
330 template<template<typename> class Extends>
331 struct pod_generator;
333 struct by_value_generator;
335 template<typename First, typename Second>
336 struct compose_generators;
338 template<typename Generator, typename Void = void>
339 struct wants_basic_expr;
341 template<typename Generator>
342 struct use_basic_expr;
344 ////////////////////////////////////////////////////////////////////////////////////////////////
347 typedef detail::not_a_domain no_super_domain;
350 typename Generator = default_generator
351 , typename Grammar = proto::_
352 , typename Super = no_super_domain
356 struct default_domain;
358 struct basic_default_domain;
360 struct deduce_domain;
362 template<typename Domain, typename Tag, typename Args, bool WantsBasicExpr = wants_basic_expr<typename Domain::proto_generator>::value>
366 using namespace domainns_;
368 ////////////////////////////////////////////////////////////////////////////////////////////////
371 template<typename Tag, typename Args, long Arity = Args::arity>
374 template<typename Tag, typename Args, long Arity = Args::arity>
380 , typename Domain = default_domain
381 , long Arity = Expr::proto_arity_c
385 template<typename This, typename Fun, typename Domain>
386 struct virtual_member;
388 struct is_proto_expr;
390 ////////////////////////////////////////////////////////////////////////////////////////////////
393 using exprns_::basic_expr;
394 using exprns_::extends;
395 using exprns_::is_proto_expr;
397 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_LOGICAL_ARITY, typename G, void)>
400 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_LOGICAL_ARITY, typename G, void)>
403 template<typename Grammar>
406 template<typename Condition, typename Then = _, typename Else = not_<_> >
409 template<typename Cases, typename Transform = tag_of<_>()>
416 struct convertible_to;
418 template<typename Grammar>
423 // Boost bug https://svn.boost.org/trac/boost/ticket/4602
424 //int const N = INT_MAX;
425 int const N = (INT_MAX >> 10);
431 template<typename Expr, typename Context, long Arity = Expr::proto_arity_c>
434 struct default_context;
436 template<typename Expr, typename Context, typename Tag = typename Expr::proto_tag, long Arity = Expr::proto_arity_c>
439 template<typename Derived, typename DefaultCtx = default_context>
440 struct callable_context;
442 template<typename Expr, typename Context, long Arity = Expr::proto_arity_c>
443 struct callable_eval;
446 using context::null_context;
447 using context::null_eval;
448 using context::default_context;
449 using context::default_eval;
450 using context::callable_context;
451 using context::callable_eval;
455 template<typename T, typename Domain = default_domain>
459 using utility::literal;
463 template<typename T, typename Domain = default_domain>
466 template<typename T, typename Domain = default_domain>
469 template<typename Expr, typename N = mpl::long_<0> >
472 template<typename Expr, long N>
475 template<typename Expr>
478 template<typename Expr>
481 template<typename Expr>
484 template<typename Expr, typename Context>
489 , typename DomainOrA0
490 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
491 BOOST_PROTO_MAX_ARITY
493 , = void BOOST_PP_INTERCEPT
495 , typename Void = void
499 template<typename Tag, typename DomainOrSequence, typename SequenceOrVoid = void, typename Void = void>
505 template<typename Env, typename Tag>
508 template<typename Env, typename Tag>
512 template<typename T, typename Void = void>
515 template<typename T, typename Void = void>
518 template<typename SubDomain, typename SuperDomain>
519 struct is_sub_domain_of;
521 template<typename T, typename Void = void>
524 template<typename Expr>
527 template<typename T, typename Void = void>
530 template<typename Expr, typename Grammar>
533 // Generic expression metafunctions and
535 template<typename Tag, typename Arg>
538 template<typename Tag, typename Left, typename Right>
541 template<typename Tag, BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_ARITY, typename A, void)>
544 // Specific expression metafunctions and
545 // grammar elements, for convenience
546 template<typename T> struct terminal;
547 template<typename T> struct unary_plus;
548 template<typename T> struct negate;
549 template<typename T> struct dereference;
550 template<typename T> struct complement;
551 template<typename T> struct address_of;
552 template<typename T> struct logical_not;
553 template<typename T> struct pre_inc;
554 template<typename T> struct pre_dec;
555 template<typename T> struct post_inc;
556 template<typename T> struct post_dec;
558 template<typename T, typename U> struct shift_left;
559 template<typename T, typename U> struct shift_right;
560 template<typename T, typename U> struct multiplies;
561 template<typename T, typename U> struct divides;
562 template<typename T, typename U> struct modulus;
563 template<typename T, typename U> struct plus;
564 template<typename T, typename U> struct minus;
565 template<typename T, typename U> struct less;
566 template<typename T, typename U> struct greater;
567 template<typename T, typename U> struct less_equal;
568 template<typename T, typename U> struct greater_equal;
569 template<typename T, typename U> struct equal_to;
570 template<typename T, typename U> struct not_equal_to;
571 template<typename T, typename U> struct logical_or;
572 template<typename T, typename U> struct logical_and;
573 template<typename T, typename U> struct bitwise_and;
574 template<typename T, typename U> struct bitwise_or;
575 template<typename T, typename U> struct bitwise_xor;
576 template<typename T, typename U> struct comma;
577 template<typename T, typename U> struct mem_ptr;
579 template<typename T, typename U> struct assign;
580 template<typename T, typename U> struct shift_left_assign;
581 template<typename T, typename U> struct shift_right_assign;
582 template<typename T, typename U> struct multiplies_assign;
583 template<typename T, typename U> struct divides_assign;
584 template<typename T, typename U> struct modulus_assign;
585 template<typename T, typename U> struct plus_assign;
586 template<typename T, typename U> struct minus_assign;
587 template<typename T, typename U> struct bitwise_and_assign;
588 template<typename T, typename U> struct bitwise_or_assign;
589 template<typename T, typename U> struct bitwise_xor_assign;
590 template<typename T, typename U> struct subscript;
591 template<typename T, typename U> struct member;
592 template<typename T, typename U, typename V> struct if_else_;
594 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_ARITY, typename A, void)>
604 template<typename Domain = default_domain>
607 template<typename Domain = default_domain>
610 template<typename N = mpl::long_<0> >
618 template<typename Tag>
621 template<typename Tag>
624 template<typename Tag, typename Domain = deduce_domain>
627 template<typename Tag, typename Domain = deduce_domain>
630 typedef make_expr<tag::terminal> make_terminal;
631 typedef make_expr<tag::unary_plus> make_unary_plus;
632 typedef make_expr<tag::negate> make_negate;
633 typedef make_expr<tag::dereference> make_dereference;
634 typedef make_expr<tag::complement> make_complement;
635 typedef make_expr<tag::address_of> make_address_of;
636 typedef make_expr<tag::logical_not> make_logical_not;
637 typedef make_expr<tag::pre_inc> make_pre_inc;
638 typedef make_expr<tag::pre_dec> make_pre_dec;
639 typedef make_expr<tag::post_inc> make_post_inc;
640 typedef make_expr<tag::post_dec> make_post_dec;
641 typedef make_expr<tag::shift_left> make_shift_left;
642 typedef make_expr<tag::shift_right> make_shift_right;
643 typedef make_expr<tag::multiplies> make_multiplies;
644 typedef make_expr<tag::divides> make_divides;
645 typedef make_expr<tag::modulus> make_modulus;
646 typedef make_expr<tag::plus> make_plus;
647 typedef make_expr<tag::minus> make_minus;
648 typedef make_expr<tag::less> make_less;
649 typedef make_expr<tag::greater> make_greater;
650 typedef make_expr<tag::less_equal> make_less_equal;
651 typedef make_expr<tag::greater_equal> make_greater_equal;
652 typedef make_expr<tag::equal_to> make_equal_to;
653 typedef make_expr<tag::not_equal_to> make_not_equal_to;
654 typedef make_expr<tag::logical_or> make_logical_or;
655 typedef make_expr<tag::logical_and> make_logical_and;
656 typedef make_expr<tag::bitwise_and> make_bitwise_and;
657 typedef make_expr<tag::bitwise_or> make_bitwise_or;
658 typedef make_expr<tag::bitwise_xor> make_bitwise_xor;
659 typedef make_expr<tag::comma> make_comma;
660 typedef make_expr<tag::mem_ptr> make_mem_ptr;
661 typedef make_expr<tag::assign> make_assign;
662 typedef make_expr<tag::shift_left_assign> make_shift_left_assign;
663 typedef make_expr<tag::shift_right_assign> make_shift_right_assign;
664 typedef make_expr<tag::multiplies_assign> make_multiplies_assign;
665 typedef make_expr<tag::divides_assign> make_divides_assign;
666 typedef make_expr<tag::modulus_assign> make_modulus_assign;
667 typedef make_expr<tag::plus_assign> make_plus_assign;
668 typedef make_expr<tag::minus_assign> make_minus_assign;
669 typedef make_expr<tag::bitwise_and_assign> make_bitwise_and_assign;
670 typedef make_expr<tag::bitwise_or_assign> make_bitwise_or_assign;
671 typedef make_expr<tag::bitwise_xor_assign> make_bitwise_xor_assign;
672 typedef make_expr<tag::subscript> make_subscript;
673 typedef make_expr<tag::if_else_> make_if_else;
674 typedef make_expr<tag::function> make_function;
688 typedef functional::flatten _flatten;
689 typedef functional::make_pair _make_pair;
690 typedef functional::first _first;
691 typedef functional::second _second;
692 typedef functional::at _at;
693 typedef functional::pop_front _pop_front;
694 typedef functional::push_front _push_front;
695 typedef functional::pop_back _pop_back;
696 typedef functional::push_back _push_back;
697 typedef functional::reverse _reverse;
698 typedef functional::eval _eval;
701 typedef functional::make_expr<tag::terminal> _make_terminal;
702 typedef functional::make_expr<tag::unary_plus> _make_unary_plus;
703 typedef functional::make_expr<tag::negate> _make_negate;
704 typedef functional::make_expr<tag::dereference> _make_dereference;
705 typedef functional::make_expr<tag::complement> _make_complement;
706 typedef functional::make_expr<tag::address_of> _make_address_of;
707 typedef functional::make_expr<tag::logical_not> _make_logical_not;
708 typedef functional::make_expr<tag::pre_inc> _make_pre_inc;
709 typedef functional::make_expr<tag::pre_dec> _make_pre_dec;
710 typedef functional::make_expr<tag::post_inc> _make_post_inc;
711 typedef functional::make_expr<tag::post_dec> _make_post_dec;
712 typedef functional::make_expr<tag::shift_left> _make_shift_left;
713 typedef functional::make_expr<tag::shift_right> _make_shift_right;
714 typedef functional::make_expr<tag::multiplies> _make_multiplies;
715 typedef functional::make_expr<tag::divides> _make_divides;
716 typedef functional::make_expr<tag::modulus> _make_modulus;
717 typedef functional::make_expr<tag::plus> _make_plus;
718 typedef functional::make_expr<tag::minus> _make_minus;
719 typedef functional::make_expr<tag::less> _make_less;
720 typedef functional::make_expr<tag::greater> _make_greater;
721 typedef functional::make_expr<tag::less_equal> _make_less_equal;
722 typedef functional::make_expr<tag::greater_equal> _make_greater_equal;
723 typedef functional::make_expr<tag::equal_to> _make_equal_to;
724 typedef functional::make_expr<tag::not_equal_to> _make_not_equal_to;
725 typedef functional::make_expr<tag::logical_or> _make_logical_or;
726 typedef functional::make_expr<tag::logical_and> _make_logical_and;
727 typedef functional::make_expr<tag::bitwise_and> _make_bitwise_and;
728 typedef functional::make_expr<tag::bitwise_or> _make_bitwise_or;
729 typedef functional::make_expr<tag::bitwise_xor> _make_bitwise_xor;
730 typedef functional::make_expr<tag::comma> _make_comma;
731 typedef functional::make_expr<tag::mem_ptr> _make_mem_ptr;
732 typedef functional::make_expr<tag::assign> _make_assign;
733 typedef functional::make_expr<tag::shift_left_assign> _make_shift_left_assign;
734 typedef functional::make_expr<tag::shift_right_assign> _make_shift_right_assign;
735 typedef functional::make_expr<tag::multiplies_assign> _make_multiplies_assign;
736 typedef functional::make_expr<tag::divides_assign> _make_divides_assign;
737 typedef functional::make_expr<tag::modulus_assign> _make_modulus_assign;
738 typedef functional::make_expr<tag::plus_assign> _make_plus_assign;
739 typedef functional::make_expr<tag::minus_assign> _make_minus_assign;
740 typedef functional::make_expr<tag::bitwise_and_assign> _make_bitwise_and_assign;
741 typedef functional::make_expr<tag::bitwise_or_assign> _make_bitwise_or_assign;
742 typedef functional::make_expr<tag::bitwise_xor_assign> _make_bitwise_xor_assign;
743 typedef functional::make_expr<tag::subscript> _make_subscript;
744 typedef functional::make_expr<tag::if_else_> _make_if_else;
745 typedef functional::make_expr<tag::function> _make_function;
756 #define BOOST_PROTO_UNEXPR() typedef int proto_is_expr_;
757 #define BOOST_PROTO_CALLABLE() typedef void proto_is_callable_;
758 #define BOOST_PROTO_AGGREGATE() typedef void proto_is_aggregate_;
759 #define BOOST_PROTO_USE_BASIC_EXPR() typedef void proto_use_basic_expr_;
763 BOOST_PROTO_CALLABLE()
768 struct key_not_found;
772 typedef int empty_state;
774 template<typename Tag, typename Value, typename Base = empty_env>
779 struct transforms_type;
782 using envns_::key_not_found;
783 using envns_::empty_env;
784 using envns_::empty_state;
786 using envns_::data_type;
787 using envns_::transforms_type;
789 struct external_transform;
791 template<typename PrimitiveTransform = void, typename X = void>
794 template<typename Grammar, typename Fun = Grammar>
797 template<typename Fun>
800 template<typename Fun>
803 template<typename Fun>
806 template<typename PrimitiveTransform>
812 template<typename Fun>
815 template<typename Sequence, typename State, typename Fun>
818 template<typename Sequence, typename State, typename Fun>
821 // Q: can we replace fold_tree with fold<flatten(_), state, fun> ?
822 // A: once segmented Fusion works well.
823 template<typename Sequence, typename State, typename Fun>
826 template<typename Sequence, typename State, typename Fun>
827 struct reverse_fold_tree;
829 template<typename Grammar, typename Domain = deduce_domain>
832 template<typename Grammar = detail::_default>
843 template<typename T, T I>
855 template<std::size_t I>
861 typedef _child_c<0> _child0;
862 typedef _child_c<1> _child1;
863 typedef _child0 _child;
864 typedef _child0 _left;
865 typedef _child1 _right;
867 // _child2, _child3, _child4, ...
868 #define M0(Z, N, DATA) typedef _child_c<N> BOOST_PP_CAT(_child, N);
869 BOOST_PP_REPEAT_FROM_TO(
871 , BOOST_PP_DEC(BOOST_PROTO_MAX_ARITY)
880 template<typename Tag>
888 namespace exops = exprns_;
890 }} // namespace boost::proto