lambda.hpp 63 KB

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