]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/proto/example/lambda.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / proto / example / lambda.hpp
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
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
118 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
140 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
164 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
188 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
210 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
238 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>
330 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>
353 T &operator()(reference_wrapper<T> const &ref) const
354 {
355 return ref;
356 }
357 };
358
359 struct anytype
360 {
361 template<typename T>
362 anytype(T &) { BOOST_ASSERT(false); }
363 template<typename T>
364 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>
374 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
539 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>
629 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>
636 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>
643 boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const
644 {
645 return boost::ref(t);
646 }
647
648 template<typename T>
649 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
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
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
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 {
744 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
755 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>
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
779 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
791 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>
808 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 {
819 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
832 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>
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 {
853 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
868 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>
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 {
893 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
904 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 {
919 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>
929 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;
940 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
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
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
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
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
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
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
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
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
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>
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 /**/
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>
1132 Expr const &const_parameters(Expr const &expr)
1133 {
1134 return expr;
1135 }
1136
1137 template<typename Expr>
1138 Expr const &break_const(Expr const &expr)
1139 {
1140 return expr;
1141 }
1142
1143 template<typename Lambda>
1144 proto::unexpr<Lambda> const
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
1156 protect(Lambda const &lambda)
1157 {
1158 return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda));
1159 }
1160
1161 template<typename 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>
1173 T operator()(U &u) const
1174 {
1175 return static_cast<T>(u);
1176 }
1177
1178 template<typename U>
1179 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
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>
1204 T operator()(U &u) const
1205 {
1206 return const_cast<T>(u);
1207 }
1208
1209 template<typename U>
1210 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
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>
1235 T operator()(U &u) const
1236 {
1237 return dynamic_cast<T>(u);
1238 }
1239
1240 template<typename U>
1241 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
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>
1266 T operator()(U &u) const
1267 {
1268 return reinterpret_cast<T>(u);
1269 }
1270
1271 template<typename U>
1272 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
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>
1296 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
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>
1320 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
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
1344 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
1365 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>
1386 void operator()(T const &t) const
1387 {
1388 t.~T();
1389 }
1390
1391 template<typename T>
1392 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>
1402 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;
1412 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>
1422 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
1438 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
1445 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
1454 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
1470 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 {
1489 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
1503 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
1524 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
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
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
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
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 /**/
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
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>
1616 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
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 /**/
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
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
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
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>
1689 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