1 #ifndef BOOST_PP_IS_ITERATING
2     ///////////////////////////////////////////////////////////////////////////////
3     //  Copyright 2008 Eric Niebler. Distributed under the Boost
4     //  Software License, Version 1.0. (See accompanying file
5     //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6     //
7     // This example contains a full-featured reimplementation of the old,
8     // now-deprecated Boost Lambda Library (BLL) on top of Boost.Proto. It
9     // is necessarily complex to accomodate all the quirks and inconsistencies
10     // of that old library, but it is a good example of how to build a
11     // complete and full-featured EDLS using Proto.
12     #ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008
13     #define BOOST_LAMBDA_HPP_EAN_04_19_2008
14 
15     #include <iosfwd>
16     #include <typeinfo>
17     #include <algorithm>
18     #include <boost/ref.hpp>
19     #include <boost/assert.hpp>
20     #include <boost/mpl/or.hpp>
21     #include <boost/mpl/int.hpp>
22     #include <boost/mpl/void.hpp>
23     #include <boost/mpl/identity.hpp>
24     #include <boost/mpl/next_prior.hpp>
25     #include <boost/mpl/min_max.hpp>
26     #include <boost/mpl/assert.hpp>
27     #include <boost/preprocessor.hpp>
28     #include <boost/utility/enable_if.hpp>
29     #include <boost/utility/result_of.hpp>
30     #include <boost/fusion/include/vector.hpp>
31     #include <boost/type_traits/add_reference.hpp>
32     #include <boost/type_traits/remove_reference.hpp>
33     #include <boost/type_traits/remove_const.hpp>
34     #include <boost/type_traits/is_same.hpp>
35     #include <boost/proto/proto.hpp>
36 
37     #ifndef BOOST_LAMBDA_MAX_ARITY
38     # define BOOST_LAMBDA_MAX_ARITY 3
39     #endif
40 
41     #ifdef _MSC_VER
42     # pragma warning(push)
43     # pragma warning(disable: 4355) // 'this' : used in base member initializer list
44     # pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels
45     #endif
46 
47     namespace boost { namespace lambda
48     {
49         namespace tag
50         {
51             struct if_ {};
52             struct if_else_ {};
53             struct for_ {};
54             struct while_ {};
55             struct do_while_ {};
56             struct protect {};
57             struct try_ {};
58             struct throw_ {};
59             struct rethrow_ {};
60             struct switch_ {};
61             struct default_ {};
62             template<int I> struct case_ { static const int value = I; };
63             template<typename E> struct catch_ { typedef E exception_type; };
64             struct catch_all_ { typedef catch_all_ exception_type; };
65         };
66 
67         template<typename Int>
68         struct placeholder
69         {
70             typedef typename Int::tag tag;
71             typedef typename Int::value_type value_type;
72             typedef placeholder<Int> type;
73             typedef placeholder<typename Int::next> next;
74             typedef placeholder<typename Int::prior> prior;
75             static const value_type value = Int::value;
76 
operator <<(std::ostream & sout,placeholder)77             friend std::ostream &operator<<(std::ostream &sout, placeholder)
78             {
79                 return sout << "boost::lambda::_" << (Int::value+1);
80             }
81         };
82 
83         struct exception_placeholder
84         {};
85 
86         struct no_exception_type {};
87         no_exception_type const no_exception = {};
88 
89         // Calculate the arity of a lambda expression
90         struct Arity
91           : proto::or_<
92                 proto::when<proto::terminal<placeholder<proto::_> >, mpl::next<proto::_value>()>
93               , proto::when<proto::terminal<proto::_>, mpl::int_<0>()>
94               , proto::otherwise<proto::fold<proto::_, mpl::int_<0>(), mpl::max<proto::_state, Arity>()> >
95             >
96         {};
97 
98         // True when a lambda expression can be applied with no arguments and
99         // without an active exception object
100         struct IsNullary
101           : proto::or_<
102                 proto::when<proto::terminal<placeholder<proto::_> >, mpl::false_()>
103               , proto::when<proto::terminal<exception_placeholder>, mpl::false_()>
104               , proto::when<proto::terminal<proto::_>, mpl::true_()>
105               , proto::otherwise<proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, IsNullary>()> >
106             >
107         {};
108 
109         struct Eval;
110 
111         struct EvalWhile : proto::transform<EvalWhile>
112         {
113             template<typename Expr, typename State, typename Data>
114             struct impl : proto::transform_impl<Expr, State, Data>
115             {
116                 typedef mpl::void_ result_type;
117 
operator ()boost::lambda::EvalWhile::impl118                 result_type operator()(
119                     typename impl::expr_param expr
120                   , typename impl::state_param state
121                   , typename impl::data_param data
122                 ) const
123                 {
124                     while(Eval()(proto::left(expr), state, data))
125                     {
126                         Eval()(proto::right(expr), state, data);
127                     }
128                     return result_type();
129                 }
130             };
131         };
132 
133         struct EvalDoWhile : proto::transform<EvalDoWhile>
134         {
135             template<typename Expr, typename State, typename Data>
136             struct impl : proto::transform_impl<Expr, State, Data>
137             {
138                 typedef mpl::void_ result_type;
139 
operator ()boost::lambda::EvalDoWhile::impl140                 result_type operator()(
141                     typename impl::expr_param expr
142                   , typename impl::state_param state
143                   , typename impl::data_param data
144                 ) const
145                 {
146                     do
147                     {
148                         Eval()(proto::child_c<0>(expr), state, data);
149                     }
150                     while(Eval()(proto::child_c<1>(expr), state, data));
151 
152                     return result_type();
153                 }
154             };
155         };
156 
157         struct EvalFor : proto::transform<EvalFor>
158         {
159             template<typename Expr, typename State, typename Data>
160             struct impl : proto::transform_impl<Expr, State, Data>
161             {
162                 typedef mpl::void_ result_type;
163 
operator ()boost::lambda::EvalFor::impl164                 result_type operator()(
165                     typename impl::expr_param expr
166                   , typename impl::state_param state
167                   , typename impl::data_param data
168                 ) const
169                 {
170                     for(Eval()(proto::child_c<0>(expr), state, data)
171                       ; Eval()(proto::child_c<1>(expr), state, data)
172                       ; Eval()(proto::child_c<2>(expr), state, data))
173                     {
174                         Eval()(proto::child_c<3>(expr), state, data);
175                     }
176                     return result_type();
177                 }
178             };
179         };
180 
181         struct EvalIf : proto::transform<EvalIf>
182         {
183             template<typename Expr, typename State, typename Data>
184             struct impl : proto::transform_impl<Expr, State, Data>
185             {
186                 typedef mpl::void_ result_type;
187 
operator ()boost::lambda::EvalIf::impl188                 result_type operator()(
189                     typename impl::expr_param expr
190                   , typename impl::state_param state
191                   , typename impl::data_param data
192                 ) const
193                 {
194                     if(Eval()(proto::left(expr), state, data))
195                     {
196                         Eval()(proto::right(expr), state, data);
197                     }
198                     return result_type();
199                 }
200             };
201         };
202 
203         struct EvalIfElse : proto::transform<EvalIfElse>
204         {
205             template<typename Expr, typename State, typename Data>
206             struct impl : proto::transform_impl<Expr, State, Data>
207             {
208                 typedef mpl::void_ result_type;
209 
operator ()boost::lambda::EvalIfElse::impl210                 result_type operator()(
211                     typename impl::expr_param expr
212                   , typename impl::state_param state
213                   , typename impl::data_param data
214                 ) const
215                 {
216                     if(Eval()(proto::child_c<0>(expr), state, data))
217                     {
218                         Eval()(proto::child_c<1>(expr), state, data);
219                     }
220                     else
221                     {
222                         Eval()(proto::child_c<2>(expr), state, data);
223                     }
224                     return result_type();
225                 }
226             };
227         };
228 
229         struct EvalException : proto::transform<EvalException>
230         {
231             template<typename Expr, typename State, typename Data>
232             struct impl : proto::transform_impl<Expr, State, Data>
233             {
234                 typedef typename remove_const<typename impl::state>::type result_type;
235                 BOOST_MPL_ASSERT_NOT((is_same<result_type, no_exception_type>));
236                 BOOST_MPL_ASSERT_NOT((is_same<result_type, tag::catch_all_>));
237 
operator ()boost::lambda::EvalException::impl238                 typename impl::state_param operator()(
239                     typename impl::expr_param
240                   , typename impl::state_param state
241                   , typename impl::data_param
242                 ) const
243                 {
244                     return state;
245                 }
246             };
247         };
248 
249         struct EvalSwitch : proto::transform<EvalSwitch>
250         {
251             template<typename Expr, typename State, typename Data, long Arity, typename BackTag>
252             struct impl2;
253 
254             #define M0(Z, N, DATA)                                                                  \
255                 case proto::tag_of<typename proto::result_of::child_c<Expr, N>::type>::type::value: \
256                     Eval()(proto::child_c<N>(expr), state, data);                                   \
257                     break;                                                                          \
258                     /**/
259 
260             #define M1(Z, N, DATA)                                                                  \
261             template<typename Expr, typename State, typename Data, typename BackTag>                \
262             struct impl2<Expr, State, Data, N, BackTag>                                             \
263               : proto::transform_impl<Expr, State, Data>                                            \
264             {                                                                                       \
265                 typedef void result_type;                                                           \
266                                                                                                     \
267                 void operator()(                                                                    \
268                     typename impl2::expr_param expr                                                 \
269                   , typename impl2::state_param state                                               \
270                   , typename impl2::data_param data                                                 \
271                 ) const                                                                             \
272                 {                                                                                   \
273                     switch(Eval()(proto::child_c<0>(expr), state, data))                            \
274                     {                                                                               \
275                         BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~)                                  \
276                     default:                                                                        \
277                         break;                                                                      \
278                     }                                                                               \
279                 }                                                                                   \
280             };                                                                                      \
281                                                                                                     \
282             template<typename Expr, typename State, typename Data>                                  \
283             struct impl2<Expr, State, Data, N, tag::default_>                                       \
284               : proto::transform_impl<Expr, State, Data>                                            \
285             {                                                                                       \
286                 typedef void result_type;                                                           \
287                                                                                                     \
288                 void operator()(                                                                    \
289                     typename impl2::expr_param expr                                                 \
290                   , typename impl2::state_param state                                               \
291                   , typename impl2::data_param data                                                 \
292                 ) const                                                                             \
293                 {                                                                                   \
294                     switch(Eval()(proto::child_c<0>(expr), state, data))                            \
295                     {                                                                               \
296                         BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~)                    \
297                     default:;                                                                       \
298                         Eval()(proto::child_c<BOOST_PP_DEC(N)>(expr), state, data);                 \
299                         break;                                                                      \
300                     }                                                                               \
301                 }                                                                                   \
302             };                                                                                      \
303             /**/
304             BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~)
305             #undef M0
306             #undef M1
307 
308             template<typename Expr, typename State, typename Data>
309             struct impl
310               : impl2<
311                     Expr
312                   , State
313                   , Data
314                   , proto::arity_of<Expr>::value
315                   , typename proto::tag_of<
316                         typename proto::result_of::child_c<
317                             Expr
318                           , proto::arity_of<Expr>::value-1
319                         >::type
320                     >::type
321                 >
322             {};
323         };
324 
325         struct throw_fun
326         {
327             BOOST_PROTO_CALLABLE()
328             typedef void result_type;
329             template<typename Expr>
operator ()boost::lambda::throw_fun330             void operator()(Expr const &e) const
331             {
332                 throw e;
333             }
334         };
335 
336         struct unwrap_ref : proto::callable
337         {
338             template<typename Sig>
339             struct result;
340 
341             template<typename This, typename T>
342             struct result<This(reference_wrapper<T>)>
343             {
344                 typedef T &type;
345             };
346 
347             template<typename This, typename T>
348             struct result<This(T &)>
349               : result<This(T)>
350             {};
351 
352             template<typename T>
operator ()boost::lambda::unwrap_ref353             T &operator()(reference_wrapper<T> const &ref) const
354             {
355                 return ref;
356             }
357         };
358 
359         struct anytype
360         {
361             template<typename T>
anytypeboost::lambda::anytype362             anytype(T &) { BOOST_ASSERT(false); }
363             template<typename T>
operator T&boost::lambda::anytype364             operator T &() const { BOOST_ASSERT(false); throw; }
365         private:
366             anytype();
367         };
368 
369         struct rethrow_fun
370         {
371             BOOST_PROTO_CALLABLE()
372             typedef anytype result_type;
373             template<typename State>
operator ()boost::lambda::rethrow_fun374             anytype operator()(State const &) const
375             {
376                 BOOST_MPL_ASSERT_NOT((is_same<State, no_exception_type>));
377                 throw;
378             }
379         };
380 
381         struct Cases
382         {
383             template<typename Tag>
384             struct case_
385               : proto::otherwise<proto::_default<Eval> >
386             {};
387 
388             template<typename E>
389             struct case_<tag::catch_<E> >
390               : proto::otherwise<Eval(proto::_child)>
391             {};
392 
393             template<int I>
394             struct case_<tag::case_<I> >
395               : proto::otherwise<Eval(proto::_child)>
396             {};
397         };
398 
399         template<> struct Cases::case_<tag::while_>     : proto::otherwise<EvalWhile> {};
400         template<> struct Cases::case_<tag::for_>       : proto::otherwise<EvalFor> {};
401         template<> struct Cases::case_<tag::if_>        : proto::otherwise<EvalIf> {};
402         template<> struct Cases::case_<tag::if_else_>   : proto::otherwise<EvalIfElse> {};
403         template<> struct Cases::case_<tag::do_while_>  : proto::otherwise<EvalDoWhile> {};
404         template<> struct Cases::case_<tag::switch_>    : proto::otherwise<EvalSwitch> {};
405         template<> struct Cases::case_<tag::protect>    : proto::otherwise<proto::_child> {};
406         template<> struct Cases::case_<tag::default_>   : proto::otherwise<Eval(proto::_child)> {};
407         template<> struct Cases::case_<tag::catch_all_> : proto::otherwise<Eval(proto::_child)> {};
408 
409         template<>
410         struct Cases::case_<proto::tag::terminal>
411           : proto::or_<
412                 proto::when<
413                     proto::terminal<placeholder<proto::_> >
414                   , proto::functional::at(proto::_data, proto::_value)
415                 >
416               , proto::when<
417                     proto::terminal<exception_placeholder>
418                   , EvalException
419                 >
420               , proto::when<
421                     proto::terminal<reference_wrapper<proto::_> >
422                   , unwrap_ref(proto::_value)
423                 >
424               , proto::otherwise<proto::_default<Eval> >
425             >
426         {};
427 
428         template<>
429         struct Cases::case_<proto::tag::function>
430           : proto::or_<
431                 proto::when<
432                     proto::function<proto::terminal<rethrow_fun> >
433                   , rethrow_fun(proto::_state)
434                 >
435               , proto::otherwise<proto::_default<Eval> >
436             >
437         {};
438 
439         struct Eval
440           : proto::switch_<Cases>
441         {};
442 
443         // Use a grammar to disable Proto's assignment operator overloads.
444         // We'll define our own because we want (x+=_1) to store x by
445         // reference. (In all other cases, variables are stored by value
446         // within lambda expressions.)
447         struct Grammar
448           : proto::switch_<struct AssignOps>
449         {};
450 
451         struct AssignOps
452         {
453             template<typename Tag> struct case_ : proto::_ {};
454         };
455 
456         template<> struct AssignOps::case_<proto::tag::shift_left_assign>   : proto::not_<proto::_> {};
457         template<> struct AssignOps::case_<proto::tag::shift_right_assign>  : proto::not_<proto::_> {};
458         template<> struct AssignOps::case_<proto::tag::multiplies_assign>   : proto::not_<proto::_> {};
459         template<> struct AssignOps::case_<proto::tag::divides_assign>      : proto::not_<proto::_> {};
460         template<> struct AssignOps::case_<proto::tag::modulus_assign>      : proto::not_<proto::_> {};
461         template<> struct AssignOps::case_<proto::tag::plus_assign>         : proto::not_<proto::_> {};
462         template<> struct AssignOps::case_<proto::tag::minus_assign>        : proto::not_<proto::_> {};
463         template<> struct AssignOps::case_<proto::tag::bitwise_and_assign>  : proto::not_<proto::_> {};
464         template<> struct AssignOps::case_<proto::tag::bitwise_or_assign>   : proto::not_<proto::_> {};
465         template<> struct AssignOps::case_<proto::tag::bitwise_xor_assign>  : proto::not_<proto::_> {};
466 
467         namespace exprns_
468         {
469             template<typename Expr>
470             struct llexpr;
471         }
472 
473         using exprns_::llexpr;
474 
475         // Wrap expressions in lambda::llexpr<>.
476         struct Generator
477           : proto::pod_generator<llexpr>
478         {};
479 
480         // The domain for the lambda library.
481         struct lldomain
482           : proto::domain<Generator, Grammar, proto::default_domain>
483         {
484             // Make all terminals and children held by value instead of by reference.
485             // Proto::domain<>::as_expr<> holds everything it can by value; the only
486             // exceptions are function types, abstract types, and iostreams.
487             template<typename T>
488             struct as_child
489               : proto_base_domain::as_expr<T>
490             {};
491 
492             // The exception is arrays, which should still be held by reference
493             template<typename T, std::size_t N>
494             struct as_child<T[N]>
495               : proto_base_domain::as_child<T[N]>
496             {};
497         };
498 
499         template<typename Sig>
500         struct llresult;
501 
502         template<typename This>
503         struct llresult<This()>
504           : mpl::if_c<
505                 result_of<IsNullary(This &)>::type::value
506               , result_of<Eval(This &, no_exception_type const &, fusion::vector0<> &)>
507               , mpl::identity<void>
508             >::type
509         {};
510 
511         #define M0(Z, N, DATA)                                                                      \
512         template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)>                   \
513         struct llresult<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))>                                      \
514           : result_of<                                                                              \
515                 Eval(                                                                               \
516                     This &                                                                          \
517                   , no_exception_type const &                                                       \
518                   , BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> &              \
519                 )                                                                                   \
520             >                                                                                       \
521         {};                                                                                         \
522         /**/
523         BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~)
524         #undef M0
525 
526         template<typename Expr>
527         struct llexpr
528         {
529             BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr<Expr>, lldomain)
530             BOOST_PROTO_EXTENDS_ASSIGN()
531             BOOST_PROTO_EXTENDS_SUBSCRIPT()
532 
533             template<typename Sig>
534             struct result
535               : llresult<Sig>
536             {};
537 
538             typename result<llexpr const()>::type
operator ()boost::lambda::llexpr539             operator()() const
540             {
541                 fusion::vector0<> args;
542                 return Eval()(*this, no_exception, args);
543             }
544 
545             #define M1(Z, N, _) ((0)(1))
546 
547             #define M2(R, PRODUCT) M3(R, BOOST_PP_SEQ_SIZE(PRODUCT), PRODUCT)
548 
549             #define M3(R, SIZE, PRODUCT)                                                                    \
550                 template<BOOST_PP_ENUM_PARAMS(SIZE, typename A)>                                            \
551                 typename result<llexpr const(BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT))>::type           \
552                 operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const                             \
553                 {                                                                                           \
554                     BOOST_MPL_ASSERT_RELATION(result_of<Arity(Expr const &)>::type::value, <=, SIZE);       \
555                     BOOST_PP_CAT(fusion::vector, SIZE)<BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT)> args   \
556                         (BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT));                                     \
557                     return Eval()(*this, no_exception, args);                                               \
558                 }                                                                                           \
559                 /**/
560 
561             #define M4(R, _, I, ELEM)                                                                       \
562                 BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM) &BOOST_PP_CAT(a, I)           \
563                 /**/
564 
565             #define M5(R, _, I, ELEM)                                                                       \
566                 BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM)&                              \
567                 /**/
568 
569             #define M6(R, _, I, ELEM)                                                                       \
570                 BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(a, I)                                                     \
571                 /**/
572 
573             #define C0
574 
575             #define C1 const
576 
577             #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_LAMBDA_MAX_ARITY, "./lambda.hpp"))
578             #include BOOST_PP_ITERATE()
579 
580             #undef C0
581             #undef C1
582             #undef M1
583             #undef M2
584             #undef M3
585             #undef M4
586             #undef M5
587             #undef M6
588         };
589 
590         typedef llexpr<proto::terminal<placeholder<mpl::int_<0> > >::type> placeholder1_type;
591         typedef llexpr<proto::terminal<placeholder<mpl::int_<1> > >::type> placeholder2_type;
592         typedef llexpr<proto::terminal<placeholder<mpl::int_<2> > >::type> placeholder3_type;
593 
594         placeholder1_type const _1 = {{{}}};
595         placeholder2_type const _2 = {{{}}};
596         placeholder3_type const _3 = {{{}}};
597 
598         placeholder1_type const free1 = {{{}}};
599         placeholder2_type const free2 = {{{}}};
600         placeholder3_type const free3 = {{{}}};
601 
602         typedef llexpr<proto::terminal<exception_placeholder>::type> placeholderE_type;
603         placeholderE_type const _e = {{{}}};
604 
605         struct byref
606         {
607             template<typename Sig>
608             struct result;
609 
610             template<typename This, typename T>
611             struct result<This(T &)>
612             {
613                 typedef llexpr<typename proto::terminal<T &>::type> type;
614             };
615 
616             template<typename This, typename T>
617             struct result<This(llexpr<T> &)>
618             {
619                 typedef boost::reference_wrapper<llexpr<T> > type;
620             };
621 
622             template<typename This, typename T>
623             struct result<This(llexpr<T> const &)>
624             {
625                 typedef boost::reference_wrapper<llexpr<T> const> type;
626             };
627 
628             template<typename T>
operator ()boost::lambda::byref629             typename result<byref(T &)>::type operator()(T &t) const
630             {
631                 typename result<byref(T &)>::type that = {{t}};
632                 return that;
633             }
634 
635             template<typename T>
operator ()boost::lambda::byref636             typename result<byref(T const &)>::type operator()(T const &t) const
637             {
638                 typename result<byref(T const &)>::type that = {{t}};
639                 return that;
640             }
641 
642             template<typename T>
operator ()boost::lambda::byref643             boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const
644             {
645                 return boost::ref(t);
646             }
647 
648             template<typename T>
operator ()boost::lambda::byref649             boost::reference_wrapper<llexpr<T> const> operator()(llexpr<T> const &t) const
650             {
651                 return boost::ref(t);
652             }
653         };
654 
655         namespace exprns_
656         {
657             // Ugh, the assign operators (and only the assign operators) store
658             // their left terminals by reference. That requires this special handling.
659             #define BOOST_LAMBDA_DEFINE_ASSIGN_OP(OP, TAG)                                          \
660             template<typename T, typename U>                                                        \
661             typename proto::result_of::make_expr<                                                   \
662                 TAG                                                                                 \
663               , lldomain                                                                            \
664               , typename boost::result_of<byref(T &)>::type                                         \
665               , U &                                                                                 \
666             >::type const                                                                           \
667             operator OP(T &t, U &u)                                                                 \
668             {                                                                                       \
669                 return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u));                  \
670             }                                                                                       \
671             template<typename T, typename U>                                                        \
672             typename proto::result_of::make_expr<                                                   \
673                 TAG                                                                                 \
674               , lldomain                                                                            \
675               , typename boost::result_of<byref(T &)>::type                                         \
676               , U const &                                                                           \
677             >::type const                                                                           \
678             operator OP(T &t, U const &u)                                                           \
679             {                                                                                       \
680                 return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u));                  \
681             }                                                                                       \
682             /**/
683 
684             BOOST_LAMBDA_DEFINE_ASSIGN_OP(<<=, boost::proto::tag::shift_left_assign)
685             BOOST_LAMBDA_DEFINE_ASSIGN_OP(>>=, boost::proto::tag::shift_right_assign)
686             BOOST_LAMBDA_DEFINE_ASSIGN_OP(*= , boost::proto::tag::multiplies_assign)
687             BOOST_LAMBDA_DEFINE_ASSIGN_OP(/= , boost::proto::tag::divides_assign)
688             BOOST_LAMBDA_DEFINE_ASSIGN_OP(%= , boost::proto::tag::modulus_assign)
689             BOOST_LAMBDA_DEFINE_ASSIGN_OP(+= , boost::proto::tag::plus_assign)
690             BOOST_LAMBDA_DEFINE_ASSIGN_OP(-= , boost::proto::tag::minus_assign)
691             BOOST_LAMBDA_DEFINE_ASSIGN_OP(&= , boost::proto::tag::bitwise_and_assign)
692             BOOST_LAMBDA_DEFINE_ASSIGN_OP(|= , boost::proto::tag::bitwise_or_assign)
693             BOOST_LAMBDA_DEFINE_ASSIGN_OP(^= , boost::proto::tag::bitwise_xor_assign)
694         }
695 
696         template<typename T>
697         struct var_type
698         {
699             typedef llexpr<typename proto::terminal<T &>::type> type;
700         };
701 
702         template<typename T>
703         llexpr<typename proto::terminal<T &>::type> const
var(T & t)704         var(T &t)
705         {
706             llexpr<typename proto::terminal<T &>::type> that = {{t}};
707             return that;
708         }
709 
710         template<typename T>
711         struct constant_type
712           : proto::result_of::make_expr<
713                 proto::tag::terminal
714               , lldomain
715               , T const &
716             >
717         {};
718 
719         template<typename T>
720         typename constant_type<T>::type const
constant(T const & t)721         constant(T const &t)
722         {
723             typename constant_type<T>::type that = {{t}};
724             return that;
725         }
726 
727         template<typename T>
728         struct constant_ref_type
729         {
730             typedef llexpr<typename proto::terminal<T const &>::type> type;
731         };
732 
733         template<typename T>
734         llexpr<typename proto::terminal<T const &>::type> const
constant_ref(T const & t)735         constant_ref(T const &t)
736         {
737             llexpr<typename proto::terminal<T const &>::type> that = {{t}};
738             return that;
739         }
740 
741         template<typename Cond>
742         struct while_generator
743         {
while_generatorboost::lambda::while_generator744             explicit while_generator(Cond const &c)
745               : cond(c)
746             {}
747 
748             template<typename Body>
749             typename proto::result_of::make_expr<
750                 tag::while_
751               , lldomain
752               , Cond const &
753               , Body const &
754             >::type const
operator []boost::lambda::while_generator755             operator[](Body const &body) const
756             {
757                 return proto::make_expr<tag::while_, lldomain>(
758                     boost::ref(this->cond)
759                   , boost::ref(body)
760                 );
761             }
762 
763         private:
764             Cond const &cond;
765         };
766 
767         template<typename Expr>
while_(Expr const & expr)768         while_generator<Expr> while_(Expr const &expr)
769         {
770             return while_generator<Expr>(expr);
771         }
772 
773         template<typename Expr>
774         struct else_generator
775         {
776             typedef typename proto::result_of::left<Expr const &>::type condition_type;
777             typedef typename proto::result_of::right<Expr const &>::type body1_type;
778 
else_generatorboost::lambda::else_generator779             explicit else_generator(Expr const &expr)
780               : if_(expr)
781             {}
782 
783             template<typename Body2>
784             typename proto::result_of::make_expr<
785                 tag::if_else_
786               , lldomain
787               , condition_type
788               , body1_type
789               , Body2 const &
790             >::type const
operator []boost::lambda::else_generator791             operator[](Body2 const &body2) const
792             {
793                 return proto::make_expr<tag::if_else_, lldomain>(
794                     boost::ref(proto::left(this->if_))
795                   , boost::ref(proto::right(this->if_))
796                   , boost::ref(body2)
797                 );
798             }
799 
800         private:
801             Expr const &if_;
802         };
803 
804         template<typename Expr>
805         struct with_else : Expr
806         {
807             template<typename T>
with_elseboost::lambda::with_else808             with_else(T const &expr)
809               : Expr(expr)
810               , else_(*this)
811             {}
812 
813             else_generator<Expr> else_;
814         };
815 
816         template<typename Cond>
817         struct if_generator
818         {
if_generatorboost::lambda::if_generator819             explicit if_generator(Cond const &c)
820               : cond(c)
821             {}
822 
823             template<typename Body>
824             with_else<
825                 typename proto::result_of::make_expr<
826                     tag::if_
827                   , lldomain
828                   , Cond const &
829                   , Body const &
830                 >::type
831             > const
operator []boost::lambda::if_generator832             operator[](Body const &body) const
833             {
834                 return proto::make_expr<tag::if_, lldomain>(
835                     boost::ref(this->cond)
836                   , boost::ref(body)
837                 );
838             }
839 
840         private:
841             Cond const &cond;
842         };
843 
844         template<typename Expr>
if_(Expr const & expr)845         if_generator<Expr> if_(Expr const &expr)
846         {
847             return if_generator<Expr>(expr);
848         }
849 
850         template<typename Init, typename Cond, typename Oper>
851         struct for_generator
852         {
for_generatorboost::lambda::for_generator853             explicit for_generator(Init const &i, Cond const &c, Oper const &o)
854               : init(i)
855               , cond(c)
856               , oper(o)
857             {}
858 
859             template<typename Body>
860             typename proto::result_of::make_expr<
861                 tag::for_
862               , lldomain
863               , Init const &
864               , Cond const &
865               , Oper const &
866               , Body const &
867             >::type const
operator []boost::lambda::for_generator868             operator[](Body const &body) const
869             {
870                 return proto::make_expr<tag::for_, lldomain>(
871                     boost::ref(this->init)
872                   , boost::ref(this->cond)
873                   , boost::ref(this->oper)
874                   , boost::ref(body)
875                 );
876             }
877 
878         private:
879             Init const &init;
880             Cond const &cond;
881             Oper const &oper;
882         };
883 
884         template<typename Init, typename Cond, typename Oper>
for_(Init const & i,Cond const & c,Oper const & o)885         for_generator<Init, Cond, Oper> for_(Init const &i, Cond const &c, Oper const &o)
886         {
887             return for_generator<Init, Cond, Oper>(i, c, o);
888         }
889 
890         template<typename Body>
891         struct do_while_generator
892         {
do_while_generatorboost::lambda::do_while_generator893             explicit do_while_generator(Body const &b)
894               : body(b)
895             {}
896 
897             template<typename Cond>
898             typename proto::result_of::make_expr<
899                 tag::do_while_
900               , lldomain
901               , Body const &
902               , Cond const &
903             >::type const
operator ()boost::lambda::do_while_generator904             operator()(Cond const &cond) const
905             {
906                 return proto::make_expr<tag::do_while_, lldomain>(
907                     boost::ref(this->body)
908                   , boost::ref(cond)
909                 );
910             }
911 
912         private:
913             Body const &body;
914         };
915 
916         template<typename Body>
917         struct do_body
918         {
do_bodyboost::lambda::do_body919             explicit do_body(Body const &body)
920               : while_(body)
921             {}
922 
923             do_while_generator<Body> while_;
924         };
925 
926         struct do_generator
927         {
928             template<typename Body>
operator []boost::lambda::do_generator929             do_body<Body> operator[](Body const &body) const
930             {
931                 return do_body<Body>(body);
932             }
933         };
934 
935         do_generator const do_ = {};
936 
937         struct noop_fun
938         {
939             typedef void result_type;
operator ()boost::lambda::noop_fun940             void operator()() const {}
941         };
942 
943         typedef llexpr<proto::function<llexpr<proto::terminal<noop_fun>::type> >::type> noop_type;
944         noop_type const noop = {{{{{}}}}};
945 
946         template<typename Init, typename Cond, typename Oper>
947         typename proto::result_of::make_expr<
948             tag::for_
949           , lldomain
950           , Init const &
951           , Cond const &
952           , Oper const &
953           , noop_type const &
954         >::type const
for_loop(Init const & init,Cond const & cond,Oper const & oper)955         for_loop(Init const &init, Cond const &cond, Oper const &oper)
956         {
957             return proto::make_expr<tag::for_, lldomain>(
958                 boost::ref(init)
959               , boost::ref(cond)
960               , boost::ref(oper)
961               , boost::ref(noop)
962             );
963         }
964 
965         template<typename Init, typename Cond, typename Oper, typename Body>
966         typename proto::result_of::make_expr<
967             tag::for_
968           , lldomain
969           , Init const &
970           , Cond const &
971           , Oper const &
972           , Body const &
973         >::type const
for_loop(Init const & init,Cond const & cond,Oper const & oper,Body const & body)974         for_loop(Init const &init, Cond const &cond, Oper const &oper, Body const &body)
975         {
976             return proto::make_expr<tag::for_>(
977                 boost::ref(init)
978               , boost::ref(cond)
979               , boost::ref(oper)
980               , boost::ref(body)
981             );
982         }
983 
984         template<typename Cond, typename Body>
985         typename proto::result_of::make_expr<
986             tag::while_
987           , lldomain
988           , Cond const &
989           , Body const &
990         >::type const
while_loop(Cond const & cond,Body const & body)991         while_loop(Cond const &cond, Body const &body)
992         {
993             return proto::make_expr<tag::while_, lldomain>(
994                 boost::ref(cond)
995               , boost::ref(body)
996             );
997         }
998 
999         template<typename Cond>
1000         typename proto::result_of::make_expr<
1001             tag::while_
1002           , lldomain
1003           , Cond const &
1004           , noop_type const &
1005         >::type const
while_loop(Cond const & cond)1006         while_loop(Cond const &cond)
1007         {
1008             return proto::make_expr<tag::while_, lldomain>(
1009                 boost::ref(cond)
1010               , boost::ref(noop)
1011             );
1012         }
1013 
1014         template<typename Cond, typename Body>
1015         typename proto::result_of::make_expr<
1016             tag::do_while_
1017           , lldomain
1018           , Body const &
1019           , Cond const &
1020         >::type const
do_while_loop(Cond const & cond,Body const & body)1021         do_while_loop(Cond const &cond, Body const &body)
1022         {
1023             return proto::make_expr<tag::do_while_, lldomain>(
1024                 boost::ref(body)
1025               , boost::ref(cond)
1026             );
1027         }
1028 
1029         template<typename Cond>
1030         typename proto::result_of::make_expr<
1031             tag::do_while_
1032           , lldomain
1033           , noop_type const &
1034           , Cond const &
1035         >::type const
do_while_loop(Cond const & cond)1036         do_while_loop(Cond const &cond)
1037         {
1038             return proto::make_expr<tag::do_while_, lldomain>(
1039                 boost::ref(noop)
1040               , boost::ref(cond)
1041             );
1042         }
1043 
1044         template<typename Cond, typename Body1>
1045         typename proto::result_of::make_expr<
1046             tag::if_
1047           , lldomain
1048           , Cond const &
1049           , Body1 const &
1050         >::type const
if_then(Cond const & cond,Body1 const & body1)1051         if_then(Cond const &cond, Body1 const &body1)
1052         {
1053             return proto::make_expr<tag::if_, lldomain>(
1054                 boost::ref(cond)
1055               , boost::ref(body1)
1056             );
1057         }
1058 
1059         template<typename Cond, typename Body1, typename Body2>
1060         typename proto::result_of::make_expr<
1061             tag::if_else_
1062           , lldomain
1063           , Cond const &
1064           , Body1 const &
1065           , Body2 const &
1066         >::type const
if_then_else(Cond const & cond,Body1 const & body1,Body2 const & body2)1067         if_then_else(Cond const &cond, Body1 const &body1, Body2 const &body2)
1068         {
1069             return proto::make_expr<tag::if_else_, lldomain>(
1070                 boost::ref(cond)
1071               , boost::ref(body1)
1072               , boost::ref(body2)
1073             );
1074         }
1075 
1076         template<typename Cond, typename Body1, typename Body2>
1077         typename proto::result_of::make_expr<
1078             proto::tag::if_else_
1079           , lldomain
1080           , Cond const &
1081           , Body1 const &
1082           , Body2 const &
1083         >::type const
if_then_else_return(Cond const & cond,Body1 const & body1,Body2 const & body2)1084         if_then_else_return(Cond const &cond, Body1 const &body1, Body2 const &body2)
1085         {
1086             return proto::make_expr<proto::tag::if_else_, lldomain>(
1087                 boost::ref(cond)
1088               , boost::ref(body1)
1089               , boost::ref(body2)
1090             );
1091         }
1092 
1093         template<typename T>
make_const(T const & t)1094         T const &make_const(T const &t)
1095         {
1096             return t;
1097         }
1098 
1099         #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a)                                \
1100         template<typename_A(N)>                                                                     \
1101         typename proto::result_of::make_expr<                                                       \
1102             proto::tag::function                                                                    \
1103           , lldomain                                                                                \
1104           , A_const_ref(N)                                                                          \
1105         >::type const                                                                               \
1106         bind(A_const_ref_a(N))                                                                      \
1107         {                                                                                           \
1108             return proto::make_expr<proto::tag::function, lldomain>(ref_a(N));                      \
1109         }                                                                                           \
1110                                                                                                     \
1111         template<typename Ret, typename_A(N)>                                                       \
1112         typename proto::result_of::make_expr<                                                       \
1113             proto::tag::function                                                                    \
1114           , lldomain                                                                                \
1115           , A_const_ref(N)                                                                          \
1116         >::type const                                                                               \
1117         bind(A_const_ref_a(N))                                                                      \
1118         {                                                                                           \
1119             return proto::make_expr<proto::tag::function, lldomain>(ref_a(N));                      \
1120         }                                                                                           \
1121         /**/
BOOST_PP_INC(BOOST_PROTO_MAX_ARITY)1122         BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
1123         #undef M1
1124 
1125         template<typename Ret, typename Expr>
1126         Expr const &ret(Expr const &expr)
1127         {
1128             return expr;
1129         }
1130 
1131         template<typename Expr>
const_parameters(Expr const & expr)1132         Expr const &const_parameters(Expr const &expr)
1133         {
1134             return expr;
1135         }
1136 
1137         template<typename Expr>
break_const(Expr const & expr)1138         Expr const &break_const(Expr const &expr)
1139         {
1140             return expr;
1141         }
1142 
1143         template<typename Lambda>
1144         proto::unexpr<Lambda> const
unlambda(Lambda const & lambda)1145         unlambda(Lambda const &lambda)
1146         {
1147             return proto::unexpr<Lambda>(lambda);
1148         }
1149 
1150         template<typename Lambda>
1151         typename proto::result_of::make_expr<
1152             tag::protect
1153           , lldomain
1154           , Lambda const &
1155         >::type const
protect(Lambda const & lambda)1156         protect(Lambda const &lambda)
1157         {
1158             return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda));
1159         }
1160 
1161         template<typename T>
std_functor(T const & t)1162         T const std_functor(T const &t)
1163         {
1164             return t;
1165         }
1166 
1167         template<typename T>
1168         struct ll_static_cast_fun
1169         {
1170             typedef T result_type;
1171 
1172             template<typename U>
operator ()boost::lambda::ll_static_cast_fun1173             T operator()(U &u) const
1174             {
1175                 return static_cast<T>(u);
1176             }
1177 
1178             template<typename U>
operator ()boost::lambda::ll_static_cast_fun1179             T operator()(U const &u) const
1180             {
1181                 return static_cast<T>(u);
1182             }
1183         };
1184 
1185         template<typename T, typename U>
1186         typename proto::result_of::make_expr<
1187             proto::tag::function
1188           , lldomain
1189           , ll_static_cast_fun<T>
1190           , U const &
1191         >::type
ll_static_cast(U const & u)1192         ll_static_cast(U const &u)
1193         {
1194             ll_static_cast_fun<T> fun;
1195             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
1196         }
1197 
1198         template<typename T>
1199         struct ll_const_cast_fun
1200         {
1201             typedef T result_type;
1202 
1203             template<typename U>
operator ()boost::lambda::ll_const_cast_fun1204             T operator()(U &u) const
1205             {
1206                 return const_cast<T>(u);
1207             }
1208 
1209             template<typename U>
operator ()boost::lambda::ll_const_cast_fun1210             T operator()(U const &u) const
1211             {
1212                 return const_cast<T>(u);
1213             }
1214         };
1215 
1216         template<typename T, typename U>
1217         typename proto::result_of::make_expr<
1218             proto::tag::function
1219           , lldomain
1220           , ll_const_cast_fun<T>
1221           , U const &
1222         >::type
ll_const_cast(U const & u)1223         ll_const_cast(U const &u)
1224         {
1225             ll_const_cast_fun<T> fun;
1226             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
1227         }
1228 
1229         template<typename T>
1230         struct ll_dynamic_cast_fun
1231         {
1232             typedef T result_type;
1233 
1234             template<typename U>
operator ()boost::lambda::ll_dynamic_cast_fun1235             T operator()(U &u) const
1236             {
1237                 return dynamic_cast<T>(u);
1238             }
1239 
1240             template<typename U>
operator ()boost::lambda::ll_dynamic_cast_fun1241             T operator()(U const &u) const
1242             {
1243                 return dynamic_cast<T>(u);
1244             }
1245         };
1246 
1247         template<typename T, typename U>
1248         typename proto::result_of::make_expr<
1249             proto::tag::function
1250           , lldomain
1251           , ll_dynamic_cast_fun<T>
1252           , U const &
1253         >::type
ll_dynamic_cast(U const & u)1254         ll_dynamic_cast(U const &u)
1255         {
1256             ll_dynamic_cast_fun<T> fun;
1257             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
1258         }
1259 
1260         template<typename T>
1261         struct ll_reinterpret_cast_fun
1262         {
1263             typedef T result_type;
1264 
1265             template<typename U>
operator ()boost::lambda::ll_reinterpret_cast_fun1266             T operator()(U &u) const
1267             {
1268                 return reinterpret_cast<T>(u);
1269             }
1270 
1271             template<typename U>
operator ()boost::lambda::ll_reinterpret_cast_fun1272             T operator()(U const &u) const
1273             {
1274                 return reinterpret_cast<T>(u);
1275             }
1276         };
1277 
1278         template<typename T, typename U>
1279         typename proto::result_of::make_expr<
1280             proto::tag::function
1281           , lldomain
1282           , ll_reinterpret_cast_fun<T>
1283           , U const &
1284         >::type
ll_reinterpret_cast(U const & u)1285         ll_reinterpret_cast(U const &u)
1286         {
1287             ll_reinterpret_cast_fun<T> fun;
1288             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
1289         }
1290 
1291         struct ll_sizeof_fun
1292         {
1293             typedef std::size_t result_type;
1294 
1295             template<typename U>
operator ()boost::lambda::ll_sizeof_fun1296             std::size_t operator()(U const &) const
1297             {
1298                 return sizeof(U);
1299             }
1300         };
1301 
1302         template<typename U>
1303         typename proto::result_of::make_expr<
1304             proto::tag::function
1305           , lldomain
1306           , ll_sizeof_fun
1307           , U const &
1308         >::type
ll_sizeof(U const & u)1309         ll_sizeof(U const &u)
1310         {
1311             ll_sizeof_fun fun;
1312             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
1313         }
1314 
1315         struct ll_typeid_fun
1316         {
1317             typedef std::type_info const &result_type;
1318 
1319             template<typename U>
operator ()boost::lambda::ll_typeid_fun1320             std::type_info const &operator()(U const &) const
1321             {
1322                 return typeid(U);
1323             }
1324         };
1325 
1326         template<typename U>
1327         typename proto::result_of::make_expr<
1328             proto::tag::function
1329           , lldomain
1330           , ll_typeid_fun
1331           , U const &
1332         >::type
ll_typeid(U const & u)1333         ll_typeid(U const &u)
1334         {
1335             ll_typeid_fun fun;
1336             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
1337         }
1338 
1339         template<typename T>
1340         struct constructor
1341         {
1342             typedef T result_type;
1343 
operator ()boost::lambda::constructor1344             T operator()() const
1345             {
1346                 return T();
1347             }
1348 
1349             #define M0(Z, N, DATA)                                                                  \
1350             template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>                                      \
1351             T operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const                    \
1352             {                                                                                       \
1353                 return T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a));                                          \
1354             }                                                                                       \
1355             /**/
1356             BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
1357             #undef M0
1358         };
1359 
1360         template<typename T>
1361         struct new_ptr
1362         {
1363             typedef T *result_type;
1364 
operator ()boost::lambda::new_ptr1365             T *operator()() const
1366             {
1367                 return new T();
1368             }
1369 
1370             #define M0(Z, N, DATA)                                                                  \
1371             template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>                                      \
1372             T *operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const                   \
1373             {                                                                                       \
1374                 return new T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a));                                      \
1375             }                                                                                       \
1376             /**/
1377             BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
1378             #undef M0
1379         };
1380 
1381         struct destructor
1382         {
1383             typedef void result_type;
1384 
1385             template<typename T>
operator ()boost::lambda::destructor1386             void operator()(T const &t) const
1387             {
1388                 t.~T();
1389             }
1390 
1391             template<typename T>
operator ()boost::lambda::destructor1392             void operator()(T *const &t) const
1393             {
1394                 (*t).~T();
1395             }
1396         };
1397 
1398         struct delete_ptr
1399         {
1400             typedef void result_type;
1401             template<typename T>
operator ()boost::lambda::delete_ptr1402             void operator()(T *t) const
1403             {
1404                 delete t;
1405             }
1406         };
1407 
1408         template<typename T>
1409         struct new_array
1410         {
1411             typedef T *result_type;
operator ()boost::lambda::new_array1412             T *operator()(std::size_t n) const
1413             {
1414                 return new T[n];
1415             }
1416         };
1417 
1418         struct delete_array
1419         {
1420             typedef void result_type;
1421             template<typename T>
operator ()boost::lambda::delete_array1422             void operator()(T *t) const
1423             {
1424                 delete[] t;
1425             }
1426         };
1427 
1428         template<typename T>
1429         struct type2type {};
1430 
1431         struct try_catch_nil {};
1432 
1433         template<typename Head, typename Tail>
1434         struct try_catch_cons : Tail
1435         {
1436             typedef typename Head::proto_tag::exception_type exception_type;
1437 
try_catch_consboost::lambda::try_catch_cons1438             try_catch_cons(Head const &head, Tail const &tail)
1439               : Tail(tail)
1440               , head(head)
1441             {}
1442 
1443             template<typename State, typename Data>
1444             typename result_of<Tail const(State const &, Data &)>::type
operator ()boost::lambda::try_catch_cons1445             operator()(State const &state, Data &data) const
1446             {
1447                 return this->invoke(state, data, type2type<exception_type>());
1448             }
1449 
1450         private:
1451             // catch(Exception const &)
1452             template<typename State, typename Data, typename Exception>
1453             typename result_of<Tail const(State const &, Data &)>::type
invokeboost::lambda::try_catch_cons1454             invoke(State const &state, Data &data, type2type<Exception>) const
1455             {
1456                 typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
1457                 try
1458                 {
1459                     return static_cast<result_type>(this->Tail::operator()(state, data));
1460                 }
1461                 catch(Exception const &e)
1462                 {
1463                     return static_cast<result_type>(Eval()(this->head, e, data));
1464                 }
1465             }
1466 
1467             // catch(...)
1468             template<typename State, typename Data>
1469             typename result_of<Tail const(State const &, Data &)>::type
invokeboost::lambda::try_catch_cons1470             invoke(State const &state, Data &data, type2type<tag::catch_all_>) const
1471             {
1472                 typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
1473                 try
1474                 {
1475                     return static_cast<result_type>(this->Tail::operator()(state, data));
1476                 }
1477                 catch(...)
1478                 {
1479                     return static_cast<result_type>(Eval()(this->head, tag::catch_all_(), data));
1480                 }
1481             }
1482 
1483             Head const &head;
1484         };
1485 
1486         template<typename Head>
1487         struct try_catch_cons<Head, try_catch_nil> : proto::callable
1488         {
try_catch_consboost::lambda::try_catch_cons1489             try_catch_cons(Head const &head, try_catch_nil const &)
1490               : head(head)
1491             {}
1492 
1493             template<typename Sig>
1494             struct result;
1495 
1496             template<typename This, typename State, typename Data>
1497             struct result<This(State, Data)>
1498               : result_of<Eval(Head const &, State, Data)>
1499             {};
1500 
1501             template<typename State, typename Data>
1502             typename result_of<Eval(Head const &, State, Data)>::type
operator ()boost::lambda::try_catch_cons1503             operator()(State const &state, Data &data) const
1504             {
1505                 return Eval()(this->head, state, data);
1506             }
1507 
1508         private:
1509             Head const &head;
1510         };
1511 
1512         struct try_catch_fun : proto::callable
1513         {
1514             template<typename Sig>
1515             struct result;
1516 
1517             template<typename This, typename Fun, typename State, typename Data>
1518             struct result<This(Fun, State, Data)>
1519               : result_of<Fun(State, Data)>
1520             {};
1521 
1522             template<typename Fun, typename State, typename Data>
1523             typename result_of<Fun(State const &, Data &)>::type
operator ()boost::lambda::try_catch_fun1524             operator()(Fun const &fun, State const &state, Data &data) const
1525             {
1526                 return fun(state, data);
1527             }
1528         };
1529 
1530         template<>
1531         struct Cases::case_<tag::try_>
1532           : proto::otherwise<
1533                 try_catch_fun(
1534                     proto::fold<
1535                         proto::_
1536                       , try_catch_nil()
1537                       , try_catch_cons<proto::_, proto::_state>(proto::_, proto::_state)
1538                     >
1539                   , proto::_state
1540                   , proto::_data
1541                 )
1542             >
1543         {};
1544 
1545         template<typename E, typename Expr>
1546         typename proto::result_of::make_expr<tag::catch_<E>, lldomain, Expr const &>::type const
catch_exception(Expr const & expr)1547         catch_exception(Expr const &expr)
1548         {
1549             return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(expr));
1550         }
1551 
1552         template<typename E>
1553         typename proto::result_of::make_expr<tag::catch_<E>, lldomain, noop_type const &>::type const
catch_exception()1554         catch_exception()
1555         {
1556             return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(noop));
1557         }
1558 
1559         template<typename Expr>
1560         typename proto::result_of::make_expr<
1561             tag::catch_all_
1562           , lldomain
1563           , Expr const &
1564         >::type const
catch_all(Expr const & expr)1565         catch_all(Expr const &expr)
1566         {
1567             return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(expr));
1568         }
1569 
1570         inline
1571         proto::result_of::make_expr<tag::catch_all_, lldomain, noop_type const &>::type const
catch_all()1572         catch_all()
1573         {
1574             return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(noop));
1575         }
1576 
1577         #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a)                                \
1578         template<typename_A(N)>                                                                     \
1579         typename proto::result_of::make_expr<                                                       \
1580             tag::try_                                                                               \
1581           , lldomain                                                                                \
1582           , A_const_ref(N)                                                                          \
1583         >::type const                                                                               \
1584         try_catch(A_const_ref_a(N))                                                                 \
1585         {                                                                                           \
1586             return proto::make_expr<tag::try_, lldomain>(ref_a(N));                                 \
1587         }                                                                                           \
1588         /**/
BOOST_PP_INC(BOOST_PROTO_MAX_ARITY)1589         BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
1590         #undef M1
1591 
1592         template<typename Expr>
1593         typename proto::result_of::make_expr<
1594             proto::tag::function
1595           , lldomain
1596           , throw_fun
1597           , Expr const &
1598         >::type const
1599         throw_exception(Expr const &expr)
1600         {
1601             throw_fun fun;
1602             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
1603         }
1604 
1605         inline
1606         proto::result_of::make_expr<proto::tag::function, lldomain, rethrow_fun>::type const
rethrow()1607         rethrow()
1608         {
1609             return proto::make_expr<proto::tag::function, lldomain>(rethrow_fun());
1610         }
1611 
1612         struct make_void_fun
1613         {
1614             typedef void result_type;
1615             template<typename T>
operator ()boost::lambda::make_void_fun1616             void operator()(T const &) const
1617             {}
1618         };
1619 
1620         template<typename Expr>
1621         typename proto::result_of::make_expr<
1622             proto::tag::function
1623           , lldomain
1624           , make_void_fun
1625           , Expr const &
1626         >::type const
make_void(Expr const & expr)1627         make_void(Expr const &expr)
1628         {
1629             make_void_fun fun;
1630             return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
1631         }
1632 
1633         #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a)                                \
1634         template<typename_A(N)>                                                                     \
1635         typename proto::result_of::make_expr<                                                       \
1636             tag::switch_                                                                            \
1637           , lldomain                                                                                \
1638           , A_const_ref(N)                                                                          \
1639         >::type const                                                                               \
1640         switch_statement(A_const_ref_a(N))                                                          \
1641         {                                                                                           \
1642             return proto::make_expr<tag::switch_, lldomain>(ref_a(N));                              \
1643         }                                                                                           \
1644         /**/
BOOST_PP_INC(BOOST_PROTO_MAX_ARITY)1645         BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
1646         #undef M1
1647 
1648         template<int I, typename Expr>
1649         typename proto::result_of::make_expr<tag::case_<I>, lldomain, Expr const &>::type const
1650         case_statement(Expr const &expr)
1651         {
1652             return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(expr));
1653         }
1654 
1655         template<int I>
1656         typename proto::result_of::make_expr<tag::case_<I>, lldomain, noop_type const &>::type const
case_statement()1657         case_statement()
1658         {
1659             return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(noop));
1660         }
1661 
1662         template<typename Expr>
1663         typename proto::result_of::make_expr<tag::default_, lldomain, Expr const &>::type const
default_statement(Expr const & expr)1664         default_statement(Expr const &expr)
1665         {
1666             return proto::make_expr<tag::default_, lldomain>(boost::ref(expr));
1667         }
1668 
1669         inline
1670         proto::result_of::make_expr<tag::default_, lldomain, noop_type const &>::type const
default_statement()1671         default_statement()
1672         {
1673             return proto::make_expr<tag::default_, lldomain>(boost::ref(noop));
1674         }
1675 
1676         namespace ll
1677         {
1678             struct for_each
1679             {
1680                 template<typename Sig>
1681                 struct result;
1682 
1683                 template<typename This, typename Begin, typename End, typename Fun>
1684                 struct result<This(Begin, End, Fun)>
1685                   : remove_const<typename remove_reference<Fun>::type>
1686                 {};
1687 
1688                 template<typename InIter, typename Fun>
operator ()boost::lambda::ll::for_each1689                 Fun operator()(InIter begin, InIter end, Fun fun) const
1690                 {
1691                     return std::for_each(begin, end, fun);
1692                 }
1693             };
1694         }
1695 
1696     }}
1697 
1698     namespace boost
1699     {
1700         template<typename Expr>
1701         struct result_of<lambda::llexpr<Expr>()>
1702           : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr>()>
1703         {};
1704 
1705         template<typename Expr>
1706         struct result_of<lambda::llexpr<Expr> const()>
1707           : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr> const()>
1708         {};
1709     }
1710 
1711     #ifdef _MSC_VER
1712     # pragma warning(pop)
1713     #endif
1714 
1715     #endif
1716 
1717 #else
1718 
1719     BOOST_PP_SEQ_FOR_EACH_PRODUCT(
1720         M2,
1721         BOOST_PP_REPEAT(BOOST_PP_ITERATION(), M1, ~)
1722     )
1723 
1724 #endif
1725