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