loops.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. // Boost Lambda Library -- loops.hpp ----------------------------------------
  2. // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
  3. // Copyright (C) 2000 Gary Powell (powellg@amazon.com)
  4. // Copyright (c) 2001-2002 Joel de Guzman
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // For more information, see www.boost.org
  11. // --------------------------------------------------------------------------
  12. #if !defined(BOOST_LAMBDA_LOOPS_HPP)
  13. #define BOOST_LAMBDA_LOOPS_HPP
  14. #include "boost/lambda/core.hpp"
  15. namespace boost {
  16. namespace lambda {
  17. // -- loop control structure actions ----------------------
  18. class forloop_action {};
  19. class forloop_no_body_action {};
  20. class whileloop_action {};
  21. class whileloop_no_body_action {};
  22. class dowhileloop_action {};
  23. class dowhileloop_no_body_action {};
  24. // For loop
  25. template <class Arg1, class Arg2, class Arg3, class Arg4>
  26. inline const
  27. lambda_functor<
  28. lambda_functor_base<
  29. forloop_action,
  30. tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
  31. lambda_functor<Arg3>, lambda_functor<Arg4> >
  32. >
  33. >
  34. for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
  35. const lambda_functor<Arg3>& a3, const lambda_functor<Arg4>& a4) {
  36. return
  37. lambda_functor_base<
  38. forloop_action,
  39. tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
  40. lambda_functor<Arg3>, lambda_functor<Arg4> >
  41. >
  42. ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
  43. lambda_functor<Arg3>, lambda_functor<Arg4> >(a1, a2, a3, a4)
  44. );
  45. }
  46. // No body case.
  47. template <class Arg1, class Arg2, class Arg3>
  48. inline const
  49. lambda_functor<
  50. lambda_functor_base<
  51. forloop_no_body_action,
  52. tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
  53. >
  54. >
  55. for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
  56. const lambda_functor<Arg3>& a3) {
  57. return
  58. lambda_functor_base<
  59. forloop_no_body_action,
  60. tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
  61. lambda_functor<Arg3> >
  62. >
  63. ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
  64. lambda_functor<Arg3> >(a1, a2, a3) );
  65. }
  66. // While loop
  67. template <class Arg1, class Arg2>
  68. inline const
  69. lambda_functor<
  70. lambda_functor_base<
  71. whileloop_action,
  72. tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
  73. >
  74. >
  75. while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
  76. return
  77. lambda_functor_base<
  78. whileloop_action,
  79. tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
  80. >
  81. ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
  82. }
  83. // No body case.
  84. template <class Arg1>
  85. inline const
  86. lambda_functor<
  87. lambda_functor_base<
  88. whileloop_no_body_action,
  89. tuple<lambda_functor<Arg1> >
  90. >
  91. >
  92. while_loop(const lambda_functor<Arg1>& a1) {
  93. return
  94. lambda_functor_base<
  95. whileloop_no_body_action,
  96. tuple<lambda_functor<Arg1> >
  97. >
  98. ( tuple<lambda_functor<Arg1> >(a1) );
  99. }
  100. // Do While loop
  101. template <class Arg1, class Arg2>
  102. inline const
  103. lambda_functor<
  104. lambda_functor_base<
  105. dowhileloop_action,
  106. tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
  107. >
  108. >
  109. do_while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
  110. return
  111. lambda_functor_base<
  112. dowhileloop_action,
  113. tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
  114. >
  115. ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
  116. }
  117. // No body case.
  118. template <class Arg1>
  119. inline const
  120. lambda_functor<
  121. lambda_functor_base<
  122. dowhileloop_no_body_action,
  123. tuple<lambda_functor<Arg1> >
  124. >
  125. >
  126. do_while_loop(const lambda_functor<Arg1>& a1) {
  127. return
  128. lambda_functor_base<
  129. dowhileloop_no_body_action,
  130. tuple<lambda_functor<Arg1> >
  131. >
  132. ( tuple<lambda_functor<Arg1> >(a1));
  133. }
  134. // Control loop lambda_functor_base specializations.
  135. // Specialization for for_loop.
  136. template<class Args>
  137. class
  138. lambda_functor_base<forloop_action, Args> {
  139. public:
  140. Args args;
  141. template <class T> struct sig { typedef void type; };
  142. public:
  143. explicit lambda_functor_base(const Args& a) : args(a) {}
  144. template<class RET, CALL_TEMPLATE_ARGS>
  145. RET call(CALL_FORMAL_ARGS) const {
  146. for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
  147. detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
  148. detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS))
  149. detail::select(boost::tuples::get<3>(args), CALL_ACTUAL_ARGS);
  150. }
  151. };
  152. // No body case
  153. template<class Args>
  154. class
  155. lambda_functor_base<forloop_no_body_action, Args> {
  156. public:
  157. Args args;
  158. template <class T> struct sig { typedef void type; };
  159. public:
  160. explicit lambda_functor_base(const Args& a) : args(a) {}
  161. template<class RET, CALL_TEMPLATE_ARGS>
  162. RET call(CALL_FORMAL_ARGS) const {
  163. for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
  164. detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
  165. detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) {}
  166. }
  167. };
  168. // Specialization for while_loop.
  169. template<class Args>
  170. class
  171. lambda_functor_base<whileloop_action, Args> {
  172. public:
  173. Args args;
  174. template <class T> struct sig { typedef void type; };
  175. public:
  176. explicit lambda_functor_base(const Args& a) : args(a) {}
  177. template<class RET, CALL_TEMPLATE_ARGS>
  178. RET call(CALL_FORMAL_ARGS) const {
  179. while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
  180. detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
  181. }
  182. };
  183. // No body case
  184. template<class Args>
  185. class
  186. lambda_functor_base<whileloop_no_body_action, Args> {
  187. public:
  188. Args args;
  189. template <class T> struct sig { typedef void type; };
  190. public:
  191. explicit lambda_functor_base(const Args& a) : args(a) {}
  192. template<class RET, CALL_TEMPLATE_ARGS>
  193. RET call(CALL_FORMAL_ARGS) const {
  194. while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) {}
  195. }
  196. };
  197. // Specialization for do_while_loop.
  198. // Note that the first argument is the condition.
  199. template<class Args>
  200. class
  201. lambda_functor_base<dowhileloop_action, Args> {
  202. public:
  203. Args args;
  204. template <class T> struct sig { typedef void type; };
  205. public:
  206. explicit lambda_functor_base(const Args& a) : args(a) {}
  207. template<class RET, CALL_TEMPLATE_ARGS>
  208. RET call(CALL_FORMAL_ARGS) const {
  209. do {
  210. detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
  211. } while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
  212. }
  213. };
  214. // No body case
  215. template<class Args>
  216. class
  217. lambda_functor_base<dowhileloop_no_body_action, Args> {
  218. public:
  219. Args args;
  220. template <class T> struct sig { typedef void type; };
  221. public:
  222. explicit lambda_functor_base(const Args& a) : args(a) {}
  223. template<class RET, CALL_TEMPLATE_ARGS>
  224. RET call(CALL_FORMAL_ARGS) const {
  225. do {} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
  226. }
  227. };
  228. // The code below is from Joel de Guzman, some name changes etc.
  229. // has been made.
  230. ///////////////////////////////////////////////////////////////////////////////
  231. //
  232. // while_composite
  233. //
  234. // This composite has the form:
  235. //
  236. // while_(condition)
  237. // [
  238. // statement
  239. // ]
  240. //
  241. // While the condition (an lambda_functor) evaluates to true, statement
  242. // (another lambda_functor) is executed. The result type of this is void.
  243. // Note the trailing underscore after while_.
  244. //
  245. ///////////////////////////////////////////////////////////////////////////////
  246. template <typename CondT, typename DoT>
  247. struct while_composite {
  248. typedef while_composite<CondT, DoT> self_t;
  249. template <class SigArgs>
  250. struct sig { typedef void type; };
  251. while_composite(CondT const& cond_, DoT const& do__)
  252. : cond(cond_), do_(do__) {}
  253. template <class Ret, CALL_TEMPLATE_ARGS>
  254. Ret call(CALL_FORMAL_ARGS) const
  255. {
  256. while (cond.internal_call(CALL_ACTUAL_ARGS))
  257. do_.internal_call(CALL_ACTUAL_ARGS);
  258. }
  259. CondT cond;
  260. DoT do_;
  261. };
  262. //////////////////////////////////
  263. template <typename CondT>
  264. struct while_gen {
  265. while_gen(CondT const& cond_)
  266. : cond(cond_) {}
  267. template <typename DoT>
  268. lambda_functor<while_composite<
  269. typename as_lambda_functor<CondT>::type,
  270. typename as_lambda_functor<DoT>::type> >
  271. operator[](DoT const& do_) const
  272. {
  273. typedef while_composite<
  274. typename as_lambda_functor<CondT>::type,
  275. typename as_lambda_functor<DoT>::type>
  276. result;
  277. return result(
  278. to_lambda_functor(cond),
  279. to_lambda_functor(do_));
  280. }
  281. CondT cond;
  282. };
  283. //////////////////////////////////
  284. template <typename CondT>
  285. inline while_gen<CondT>
  286. while_(CondT const& cond)
  287. {
  288. return while_gen<CondT>(cond);
  289. }
  290. ///////////////////////////////////////////////////////////////////////////////
  291. //
  292. // do_composite
  293. //
  294. // This composite has the form:
  295. //
  296. // do_
  297. // [
  298. // statement
  299. // ]
  300. // .while_(condition)
  301. //
  302. // While the condition (an lambda_functor) evaluates to true, statement
  303. // (another lambda_functor) is executed. The statement is executed at least
  304. // once. The result type of this is void. Note the trailing
  305. // underscore after do_ and the leading dot and the trailing
  306. // underscore before and after .while_.
  307. //
  308. ///////////////////////////////////////////////////////////////////////////////
  309. template <typename DoT, typename CondT>
  310. struct do_composite {
  311. typedef do_composite<DoT, CondT> self_t;
  312. template <class SigArgs>
  313. struct sig { typedef void type; };
  314. do_composite(DoT const& do__, CondT const& cond_)
  315. : do_(do__), cond(cond_) {}
  316. template <class Ret, CALL_TEMPLATE_ARGS>
  317. Ret call(CALL_FORMAL_ARGS) const
  318. {
  319. do
  320. do_.internal_call(CALL_ACTUAL_ARGS);
  321. while (cond.internal_call(CALL_ACTUAL_ARGS));
  322. }
  323. DoT do_;
  324. CondT cond;
  325. };
  326. ////////////////////////////////////
  327. template <typename DoT>
  328. struct do_gen2 {
  329. do_gen2(DoT const& do__)
  330. : do_(do__) {}
  331. template <typename CondT>
  332. lambda_functor<do_composite<
  333. typename as_lambda_functor<DoT>::type,
  334. typename as_lambda_functor<CondT>::type> >
  335. while_(CondT const& cond) const
  336. {
  337. typedef do_composite<
  338. typename as_lambda_functor<DoT>::type,
  339. typename as_lambda_functor<CondT>::type>
  340. result;
  341. return result(
  342. to_lambda_functor(do_),
  343. to_lambda_functor(cond));
  344. }
  345. DoT do_;
  346. };
  347. ////////////////////////////////////
  348. struct do_gen {
  349. template <typename DoT>
  350. do_gen2<DoT>
  351. operator[](DoT const& do_) const
  352. {
  353. return do_gen2<DoT>(do_);
  354. }
  355. };
  356. do_gen const do_ = do_gen();
  357. ///////////////////////////////////////////////////////////////////////////////
  358. //
  359. // for_composite
  360. //
  361. // This statement has the form:
  362. //
  363. // for_(init, condition, step)
  364. // [
  365. // statement
  366. // ]
  367. //
  368. // Where init, condition, step and statement are all lambda_functors. init
  369. // is executed once before entering the for-loop. The for-loop
  370. // exits once condition evaluates to false. At each loop iteration,
  371. // step and statement is called. The result of this statement is
  372. // void. Note the trailing underscore after for_.
  373. //
  374. ///////////////////////////////////////////////////////////////////////////////
  375. template <typename InitT, typename CondT, typename StepT, typename DoT>
  376. struct for_composite {
  377. template <class SigArgs>
  378. struct sig { typedef void type; };
  379. for_composite(
  380. InitT const& init_,
  381. CondT const& cond_,
  382. StepT const& step_,
  383. DoT const& do__)
  384. : init(init_), cond(cond_), step(step_), do_(do__) {}
  385. template <class Ret, CALL_TEMPLATE_ARGS>
  386. Ret
  387. call(CALL_FORMAL_ARGS) const
  388. {
  389. for (init.internal_call(CALL_ACTUAL_ARGS); cond.internal_call(CALL_ACTUAL_ARGS); step.internal_call(CALL_ACTUAL_ARGS))
  390. do_.internal_call(CALL_ACTUAL_ARGS);
  391. }
  392. InitT init; CondT cond; StepT step; DoT do_; // lambda_functors
  393. };
  394. //////////////////////////////////
  395. template <typename InitT, typename CondT, typename StepT>
  396. struct for_gen {
  397. for_gen(
  398. InitT const& init_,
  399. CondT const& cond_,
  400. StepT const& step_)
  401. : init(init_), cond(cond_), step(step_) {}
  402. template <typename DoT>
  403. lambda_functor<for_composite<
  404. typename as_lambda_functor<InitT>::type,
  405. typename as_lambda_functor<CondT>::type,
  406. typename as_lambda_functor<StepT>::type,
  407. typename as_lambda_functor<DoT>::type> >
  408. operator[](DoT const& do_) const
  409. {
  410. typedef for_composite<
  411. typename as_lambda_functor<InitT>::type,
  412. typename as_lambda_functor<CondT>::type,
  413. typename as_lambda_functor<StepT>::type,
  414. typename as_lambda_functor<DoT>::type>
  415. result;
  416. return result(
  417. to_lambda_functor(init),
  418. to_lambda_functor(cond),
  419. to_lambda_functor(step),
  420. to_lambda_functor(do_));
  421. }
  422. InitT init; CondT cond; StepT step;
  423. };
  424. //////////////////////////////////
  425. template <typename InitT, typename CondT, typename StepT>
  426. inline for_gen<InitT, CondT, StepT>
  427. for_(InitT const& init, CondT const& cond, StepT const& step)
  428. {
  429. return for_gen<InitT, CondT, StepT>(init, cond, step);
  430. }
  431. } // lambda
  432. } // boost
  433. #endif // BOOST_LAMBDA_LOOPS_HPP