lazy_operator.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. ////////////////////////////////////////////////////////////////////////////
  2. // lazy operator.hpp
  3. //
  4. // Build lazy operations for Phoenix equivalents for FC++
  5. //
  6. // These are equivalents of the Boost FC++ functoids in operator.hpp
  7. //
  8. // Implemented so far:
  9. //
  10. // make_pair
  11. // plus minus multiplies divides modulus
  12. // negate equal not_equal greater less
  13. // greater_equal less_equal positive
  14. // logical_and logical_or
  15. // logical_not min max inc dec
  16. //
  17. // These are not from the FC++ operator.hpp but were made for testing purposes.
  18. //
  19. // identity (renamed id)
  20. // sin
  21. //
  22. // These are now being modified to use boost::phoenix::function
  23. // so that they are available for use as arguments.
  24. // Types are being defined in capitals e.g. Id id;
  25. ////////////////////////////////////////////////////////////////////////////
  26. /*=============================================================================
  27. Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
  28. Copyright (c) 2001-2007 Joel de Guzman
  29. Copyright (c) 2015 John Fletcher
  30. Distributed under the Boost Software License, Version 1.0. (See accompanying
  31. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  32. ==============================================================================*/
  33. #ifndef BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR
  34. #define BOOST_PHOENIX_FUNCTION_LAZY_OPERATOR
  35. #include <cmath>
  36. #include <cstdlib>
  37. #include <boost/phoenix/core.hpp>
  38. #include <boost/phoenix/function.hpp>
  39. #include <boost/function.hpp>
  40. namespace boost {
  41. namespace phoenix {
  42. //////////////////////////////////////////////////////////////////////
  43. // a_unique_type_for_nil
  44. //////////////////////////////////////////////////////////////////////
  45. // This may need to be moved elsewhere to define reuser.
  46. struct a_unique_type_for_nil {
  47. bool operator==( a_unique_type_for_nil ) const { return true; }
  48. bool operator< ( a_unique_type_for_nil ) const { return false; }
  49. typedef a_unique_type_for_nil value_type;
  50. };
  51. // This maybe put into a namespace.
  52. a_unique_type_for_nil NIL;
  53. //////////////////////////////////////////////////////////////////////
  54. // lazy_exception - renamed from fcpp_exception.
  55. //////////////////////////////////////////////////////////////////////
  56. #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
  57. struct lazy_exception : public std::exception {
  58. const char* s;
  59. lazy_exception( const char* ss ) : s(ss) {}
  60. const char* what() const throw() { return s; }
  61. };
  62. #endif
  63. //////////////////////////////////////////////////////////////////////
  64. // in ref_count.hpp in BoostFC++
  65. typedef unsigned int RefCountType;
  66. namespace impl {
  67. // Implemented early, moved from lazy_signature.hpp
  68. template <class T>
  69. struct remove_RC
  70. {
  71. typedef typename boost::remove_reference<T>::type TT;
  72. typedef typename boost::remove_const<TT>::type type;
  73. };
  74. struct XId
  75. {
  76. template <typename Sig>
  77. struct result;
  78. template <typename This, typename A0>
  79. struct result<This(A0)>
  80. : boost::remove_reference<A0>
  81. {};
  82. template <typename A0>
  83. A0 operator()(A0 const & a0) const
  84. {
  85. return a0;
  86. }
  87. };
  88. }
  89. typedef boost::phoenix::function<impl::XId> Id;
  90. Id id;
  91. #ifdef BOOST_RESULT_OF_USE_TR1
  92. // Experiment following examples in
  93. // phoenix/stl/container/container.hpp
  94. namespace result_of {
  95. template <
  96. typename Arg1
  97. , typename Arg2
  98. >
  99. class make_pair
  100. {
  101. public:
  102. typedef typename impl::remove_RC<Arg1>::type Arg1Type;
  103. typedef typename impl::remove_RC<Arg2>::type Arg2Type;
  104. typedef std::pair<Arg1Type,Arg2Type> type;
  105. typedef std::pair<Arg1Type,Arg2Type> result_type;
  106. };
  107. }
  108. #endif
  109. namespace impl
  110. {
  111. struct XMake_pair {
  112. #ifdef BOOST_RESULT_OF_USE_TR1
  113. template <typename Sig>
  114. struct result;
  115. // This fails with -O2 unless refs are removed from A1 and A2.
  116. template <typename This, typename A0, typename A1>
  117. struct result<This(A0, A1)>
  118. {
  119. typedef typename result_of::make_pair<A0,A1>::type type;
  120. };
  121. #else
  122. template <typename Sig>
  123. struct result;
  124. template <typename This, typename A0, typename A1>
  125. struct result<This(A0, A1)>
  126. : boost::remove_reference<std::pair<A0, A1> >
  127. {};
  128. #endif
  129. template <typename A0, typename A1>
  130. #ifdef BOOST_RESULT_OF_USE_TR1
  131. typename result<XMake_pair(A0,A1)>::type
  132. #else
  133. std::pair<A0, A1>
  134. #endif
  135. operator()(A0 const & a0, A1 const & a1) const
  136. {
  137. return std::make_pair(a0,a1);
  138. }
  139. };
  140. }
  141. typedef boost::phoenix::function<impl::XMake_pair> Make_pair;
  142. Make_pair make_pair;
  143. namespace impl
  144. {
  145. // For now I will leave the return type deduction as it is.
  146. // I want to look at bringing in the sort of type deduction for
  147. // mixed types which I have in FC++.
  148. // Also I could look at the case where one of the arguments is
  149. // another functor or a Phoenix placeholder.
  150. struct XPlus
  151. {
  152. template <typename Sig>
  153. struct result;
  154. template <typename This, typename A0, typename A1>
  155. struct result<This(A0, A1)>
  156. : boost::remove_reference<A0>
  157. {};
  158. template <typename This, typename A0, typename A1, typename A2>
  159. struct result<This(A0, A1, A2)>
  160. : boost::remove_reference<A0>
  161. {};
  162. template <typename A0, typename A1>
  163. A0 operator()(A0 const & a0, A1 const & a1) const
  164. {
  165. //A0 res = a0 + a1;
  166. //return res;
  167. return a0 + a1;
  168. }
  169. template <typename A0, typename A1, typename A2>
  170. A0 operator()(A0 const & a0, A1 const & a1, A2 const & a2) const
  171. {
  172. return a0 + a1 + a2;
  173. }
  174. };
  175. struct XMinus
  176. {
  177. template <typename Sig>
  178. struct result;
  179. template <typename This, typename A0, typename A1>
  180. struct result<This(A0, A1)>
  181. : boost::remove_reference<A0>
  182. {};
  183. template <typename A0, typename A1>
  184. A0 operator()(A0 const & a0, A1 const & a1) const
  185. {
  186. return a0 - a1;
  187. }
  188. };
  189. struct XMultiplies
  190. {
  191. template <typename Sig>
  192. struct result;
  193. template <typename This, typename A0, typename A1>
  194. struct result<This(A0, A1)>
  195. : boost::remove_reference<A0>
  196. {};
  197. template <typename A0, typename A1>
  198. A0 operator()(A0 const & a0, A1 const & a1) const
  199. {
  200. return a0 * a1;
  201. }
  202. };
  203. struct XDivides
  204. {
  205. template <typename Sig>
  206. struct result;
  207. template <typename This, typename A0, typename A1>
  208. struct result<This(A0, A1)>
  209. : boost::remove_reference<A0>
  210. {};
  211. template <typename A0, typename A1>
  212. A0 operator()(A0 const & a0, A1 const & a1) const
  213. {
  214. return a0 / a1;
  215. }
  216. };
  217. struct XModulus
  218. {
  219. template <typename Sig>
  220. struct result;
  221. template <typename This, typename A0, typename A1>
  222. struct result<This(A0, A1)>
  223. : boost::remove_reference<A0>
  224. {};
  225. template <typename A0, typename A1>
  226. A0 operator()(A0 const & a0, A1 const & a1) const
  227. {
  228. return a0 % a1;
  229. }
  230. };
  231. struct XNegate
  232. {
  233. template <typename Sig>
  234. struct result;
  235. template <typename This, typename A0>
  236. struct result<This(A0)>
  237. : boost::remove_reference<A0>
  238. {};
  239. template <typename A0>
  240. A0 operator()(A0 const & a0) const
  241. {
  242. return -a0;
  243. }
  244. };
  245. struct XEqual
  246. {
  247. template <typename Sig>
  248. struct result;
  249. template <typename This, typename A0, typename A1>
  250. struct result<This(A0,A1)>
  251. {
  252. typedef bool type;
  253. };
  254. template <typename A0, typename A1>
  255. bool operator()(A0 const & a0, A1 const & a1) const
  256. {
  257. return a0 == a1;
  258. }
  259. };
  260. struct XNot_equal
  261. {
  262. template <typename Sig>
  263. struct result;
  264. template <typename This, typename A0, typename A1>
  265. struct result<This(A0,A1)>
  266. {
  267. typedef bool type;
  268. };
  269. template <typename A0, typename A1>
  270. bool operator()(A0 const & a0, A1 const & a1) const
  271. {
  272. return a0 != a1;
  273. }
  274. };
  275. struct XGreater
  276. {
  277. template <typename Sig>
  278. struct result;
  279. template <typename This, typename A0, typename A1>
  280. struct result<This(A0,A1)>
  281. {
  282. typedef bool type;
  283. };
  284. template <typename A0, typename A1>
  285. bool operator()(A0 const & a0, A1 const & a1) const
  286. {
  287. return a0 > a1;
  288. }
  289. };
  290. struct XLess
  291. {
  292. template <typename Sig>
  293. struct result;
  294. template <typename This, typename A0, typename A1>
  295. struct result<This(A0,A1)>
  296. {
  297. typedef bool type;
  298. };
  299. template <typename A0, typename A1>
  300. bool operator()(A0 const & a0, A1 const & a1) const
  301. {
  302. return a0 < a1;
  303. }
  304. };
  305. struct XGreater_equal
  306. {
  307. template <typename Sig>
  308. struct result;
  309. template <typename This, typename A0, typename A1>
  310. struct result<This(A0,A1)>
  311. {
  312. typedef bool type;
  313. };
  314. template <typename A0, typename A1>
  315. bool operator()(A0 const & a0, A1 const & a1) const
  316. {
  317. return a0 >= a1;
  318. }
  319. };
  320. struct XLess_equal
  321. {
  322. template <typename Sig>
  323. struct result;
  324. template <typename This, typename A0, typename A1>
  325. struct result<This(A0,A1)>
  326. {
  327. typedef bool type;
  328. };
  329. template <typename A0, typename A1>
  330. bool operator()(A0 const & a0, A1 const & a1) const
  331. {
  332. return a0 <= a1;
  333. }
  334. };
  335. struct XPositive
  336. {
  337. template <typename Sig>
  338. struct result;
  339. template <typename This, typename A0>
  340. struct result<This(A0)>
  341. {
  342. typedef bool type;
  343. };
  344. template <typename A0>
  345. bool operator()(A0 const & a0) const
  346. {
  347. return a0 >= A0(0);
  348. }
  349. };
  350. struct XLogical_and
  351. {
  352. template <typename Sig>
  353. struct result;
  354. template <typename This, typename A0, typename A1>
  355. struct result<This(A0,A1)>
  356. {
  357. typedef bool type;
  358. };
  359. template <typename A0, typename A1>
  360. bool operator()(A0 const & a0, A1 const & a1) const
  361. {
  362. return a0 && a1;
  363. }
  364. };
  365. struct XLogical_or
  366. {
  367. template <typename Sig>
  368. struct result;
  369. template <typename This, typename A0, typename A1>
  370. struct result<This(A0,A1)>
  371. {
  372. typedef bool type;
  373. };
  374. template <typename A0, typename A1>
  375. bool operator()(A0 const & a0, A1 const & a1) const
  376. {
  377. return a0 || a1;
  378. }
  379. };
  380. struct XLogical_not
  381. {
  382. template <typename Sig>
  383. struct result;
  384. template <typename This, typename A0>
  385. struct result<This(A0)>
  386. {
  387. typedef bool type;
  388. };
  389. template <typename A0>
  390. bool operator()(A0 const & a0) const
  391. {
  392. return !a0;
  393. }
  394. };
  395. struct XMin
  396. {
  397. template <typename Sig>
  398. struct result;
  399. template <typename This, typename A0, typename A1>
  400. struct result<This(A0, A1)>
  401. : boost::remove_reference<A0>
  402. {};
  403. template <typename A0, typename A1>
  404. A0 operator()(A0 const & a0, A1 const & a1) const
  405. {
  406. if ( a0 < a1 ) return a0; else return a1;
  407. }
  408. };
  409. struct XMax
  410. {
  411. template <typename Sig>
  412. struct result;
  413. template <typename This, typename A0, typename A1>
  414. struct result<This(A0, A1)>
  415. : boost::remove_reference<A0>
  416. {};
  417. template <typename A0, typename A1>
  418. A0 operator()(A0 const & a0, A1 const & a1) const
  419. {
  420. if ( a0 < a1 ) return a1; else return a0;
  421. }
  422. };
  423. struct XInc
  424. {
  425. template <typename Sig>
  426. struct result;
  427. template <typename This, typename A0>
  428. struct result<This(A0)>
  429. : boost::remove_reference<A0>
  430. {};
  431. template <typename A0>
  432. A0 operator()(A0 const & a0) const
  433. {
  434. return a0 + 1;
  435. }
  436. };
  437. struct XDec
  438. {
  439. template <typename Sig>
  440. struct result;
  441. template <typename This, typename A0>
  442. struct result<This(A0)>
  443. : boost::remove_reference<A0>
  444. {};
  445. template <typename A0>
  446. A0 operator()(A0 const & a0) const
  447. {
  448. return a0 - 1;
  449. }
  450. };
  451. struct XSin
  452. {
  453. template <typename Sig>
  454. struct result;
  455. template <typename This, typename A0>
  456. struct result<This(A0)>
  457. : boost::remove_reference<A0>
  458. {};
  459. template <typename A0>
  460. A0 operator()(A0 const & a0) const
  461. {
  462. return std::sin(a0);
  463. }
  464. };
  465. // Example of templated struct.
  466. // How do I make it callable?
  467. template <typename Result>
  468. struct what {
  469. typedef Result result_type;
  470. Result operator()(Result const & r) const
  471. {
  472. return r;
  473. }
  474. // what is not complete - error.
  475. //static boost::function1<Result,Result> res = what<Result>();
  476. };
  477. template <typename Result>
  478. struct what0 {
  479. typedef Result result_type;
  480. Result operator()() const
  481. {
  482. return Result(100);
  483. }
  484. };
  485. template <class Result, class F>
  486. class MonomorphicWrapper0 /* : public c_fun_type<Res> */
  487. {
  488. F f;
  489. public:
  490. typedef Result result_type;
  491. MonomorphicWrapper0( const F& g ) : f(g) {}
  492. Result operator()() const {
  493. return f();
  494. }
  495. };
  496. }
  497. /////////////////////////////////////////////////////////
  498. // Look at this. How to use Phoenix with a templated
  499. // struct. First adapt with boost::function and then
  500. // convert that to Phoenix!!
  501. // I have not found out how to do it directly.
  502. /////////////////////////////////////////////////////////
  503. boost::function1<int, int > what_int = impl::what<int>();
  504. typedef boost::function1<int,int> fun1_int_int;
  505. typedef boost::function0<int> fun0_int;
  506. boost::function0<int> what0_int = impl::what0<int>();
  507. BOOST_PHOENIX_ADAPT_FUNCTION(int,what,what_int,1)
  508. BOOST_PHOENIX_ADAPT_FUNCTION_NULLARY(int,what0,what0_int)
  509. // And this shows how to make them into argument callable functions.
  510. typedef boost::phoenix::function<fun1_int_int> What_arg;
  511. typedef boost::phoenix::function<fun0_int> What0_arg;
  512. What_arg what_arg(what_int);
  513. What0_arg what0_arg(what0_int);
  514. // To use these as arguments they have to be defined like this.
  515. typedef boost::phoenix::function<impl::XPlus> Plus;
  516. typedef boost::phoenix::function<impl::XMinus> Minus;
  517. typedef boost::phoenix::function<impl::XMultiplies> Multiplies;
  518. typedef boost::phoenix::function<impl::XDivides> Divides;
  519. typedef boost::phoenix::function<impl::XModulus> Modulus;
  520. typedef boost::phoenix::function<impl::XNegate> Negate;
  521. typedef boost::phoenix::function<impl::XEqual> Equal;
  522. typedef boost::phoenix::function<impl::XNot_equal> Not_equal;
  523. typedef boost::phoenix::function<impl::XGreater> Greater;
  524. typedef boost::phoenix::function<impl::XLess> Less;
  525. typedef boost::phoenix::function<impl::XGreater_equal> Greater_equal;
  526. typedef boost::phoenix::function<impl::XLess_equal> Less_equal;
  527. typedef boost::phoenix::function<impl::XPositive> Positive;
  528. typedef boost::phoenix::function<impl::XLogical_and> Logical_and;
  529. typedef boost::phoenix::function<impl::XLogical_or> Logical_or;
  530. typedef boost::phoenix::function<impl::XLogical_not> Logical_not;
  531. typedef boost::phoenix::function<impl::XMax> Max;
  532. typedef boost::phoenix::function<impl::XMin> Min;
  533. typedef boost::phoenix::function<impl::XInc> Inc;
  534. typedef boost::phoenix::function<impl::XDec> Dec;
  535. typedef boost::phoenix::function<impl::XSin> Sin;
  536. Plus plus;
  537. Minus minus;
  538. Multiplies multiplies;
  539. Divides divides;
  540. Modulus modulus;
  541. Negate negate;
  542. Equal equal;
  543. Not_equal not_equal;
  544. Greater greater;
  545. Less less;
  546. Greater_equal greater_equal;
  547. Less_equal less_equal;
  548. Positive positive;
  549. Logical_and logical_and;
  550. Logical_or logical_or;
  551. Logical_not logical_not;
  552. Max max;
  553. Min min;
  554. Inc inc;
  555. Dec dec;
  556. Sin sin;
  557. }
  558. }
  559. #endif