sample8.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*=============================================================================
  2. Phoenix V1.2.1
  3. Copyright (c) 2001-2003 Joel de Guzman
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. ==============================================================================*/
  8. #include <vector>
  9. #include <algorithm>
  10. #include <iostream>
  11. #define PHOENIX_LIMIT 5
  12. #include <boost/spirit/include/phoenix1_operators.hpp>
  13. #include <boost/spirit/include/phoenix1_primitives.hpp>
  14. #include <boost/spirit/include/phoenix1_composite.hpp>
  15. #include <boost/spirit/include/phoenix1_special_ops.hpp>
  16. #include <boost/spirit/include/phoenix1_statements.hpp>
  17. namespace phoenix {
  18. ///////////////////////////////////////////////////////////////////////////////
  19. //
  20. // local_tuple
  21. //
  22. // This *is a* tuple like the one we see in TupleT in any actor
  23. // base class' eval member function. local_tuple should look and
  24. // feel the same as a tupled-args, that's why it is derived from
  25. // TupleArgsT. It has an added member, locs which is another tuple
  26. // where the local variables will be stored. locs is mutable to
  27. // allow read-write access to our locals regardless of
  28. // local_tuple's constness (The eval member function accepts it as
  29. // a const argument).
  30. //
  31. ///////////////////////////////////////////////////////////////////////////////
  32. template <typename TupleArgsT, typename TupleLocsT>
  33. struct local_tuple : public TupleArgsT {
  34. typedef TupleLocsT local_vars_t;
  35. local_tuple(TupleArgsT const& args, TupleLocsT const& locs_)
  36. : TupleArgsT(args), locs(locs_) {}
  37. mutable TupleLocsT locs;
  38. };
  39. ///////////////////////////////////////////////////////////////////////////////
  40. //
  41. // local_var_result
  42. //
  43. // This is a return type computer. Given a constant integer N and a
  44. // tuple, get the Nth local variable type. If TupleT is not really
  45. // a local_tuple, we just return nil_t. Otherwise we get the Nth
  46. // local variable type.
  47. //
  48. ///////////////////////////////////////////////////////////////////////////////
  49. template <int N, typename TupleT>
  50. struct local_var_result {
  51. typedef nil_t type;
  52. };
  53. //////////////////////////////////
  54. template <int N, typename TupleArgsT, typename TupleLocsT>
  55. struct local_var_result<N, local_tuple<TupleArgsT, TupleLocsT> > {
  56. typedef typename tuple_element<N, TupleLocsT>::type& type;
  57. };
  58. ///////////////////////////////////////////////////////////////////////////////
  59. //
  60. // local_var
  61. //
  62. // This class looks so curiously like the argument class. local_var
  63. // provides access to the Nth local variable packed in the tuple
  64. // duo local_tuple above. Note that the member function eval
  65. // expects a local_tuple argument. Otherwise the expression
  66. // 'tuple.locs' will fail (compile-time error). local_var
  67. // primitives only work within the context of a context_composite
  68. // (see below).
  69. //
  70. // Provided are some predefined local_var actors for 0..N local
  71. // variable access: loc1..locN.
  72. //
  73. ///////////////////////////////////////////////////////////////////////////////
  74. template <int N>
  75. struct local_var {
  76. template <typename TupleT>
  77. struct result {
  78. typedef typename local_var_result<N, TupleT>::type type;
  79. };
  80. template <typename TupleT>
  81. typename local_var_result<N, TupleT>::type
  82. eval(TupleT const& tuple) const
  83. {
  84. return tuple.locs[tuple_index<N>()];
  85. }
  86. };
  87. //////////////////////////////////
  88. namespace locals {
  89. actor<local_var<0> > const result = local_var<0>();
  90. actor<local_var<1> > const loc1 = local_var<1>();
  91. actor<local_var<2> > const loc2 = local_var<2>();
  92. actor<local_var<3> > const loc3 = local_var<3>();
  93. actor<local_var<4> > const loc4 = local_var<4>();
  94. }
  95. ///////////////////////////////////////////////////////////////////////////////
  96. //
  97. // context_composite
  98. //
  99. // This class encapsulates an actor and some local variable
  100. // initializers packed in a tuple.
  101. //
  102. // context_composite is just like a proxy and delegates the actual
  103. // evaluation to the actor. The actor does the actual work. In the
  104. // eval member function, before invoking the embedded actor's eval
  105. // member function, we first stuff an instance of our locals and
  106. // bundle both 'args' and 'locals' in a local_tuple. This
  107. // local_tuple instance is created in the stack initializing it
  108. // with our locals member. We then pass this local_tuple instance
  109. // as an argument to the actor's eval member function.
  110. //
  111. ///////////////////////////////////////////////////////////////////////////////
  112. template <typename ActorT, typename LocsT>
  113. struct context_composite {
  114. typedef context_composite<ActorT, LocsT> self_t;
  115. template <typename TupleT>
  116. struct result { typedef typename tuple_element<0, LocsT>::type type; };
  117. context_composite(ActorT const& actor_, LocsT const& locals_)
  118. : actor(actor_), locals(locals_) {}
  119. template <typename TupleT>
  120. typename tuple_element<0, LocsT>::type
  121. eval(TupleT const& args) const
  122. {
  123. local_tuple<TupleT, LocsT> local_context(args, locals);
  124. actor.eval(local_context);
  125. return local_context.locs[tuple_index<0>()];
  126. }
  127. ActorT actor;
  128. LocsT locals;
  129. };
  130. ///////////////////////////////////////////////////////////////////////////////
  131. //
  132. // context_gen
  133. //
  134. // At construction time, this class is given some local var-
  135. // initializers packed in a tuple. We just store this for later.
  136. // The operator[] of this class creates the actual context_composite
  137. // given an actor. This is responsible for the construct
  138. // context<types>[actor].
  139. //
  140. ///////////////////////////////////////////////////////////////////////////////
  141. template <typename LocsT>
  142. struct context_gen {
  143. context_gen(LocsT const& locals_)
  144. : locals(locals_) {}
  145. template <typename ActorT>
  146. actor<context_composite<typename as_actor<ActorT>::type, LocsT> >
  147. operator[](ActorT const& actor)
  148. {
  149. return context_composite<typename as_actor<ActorT>::type, LocsT>
  150. (as_actor<ActorT>::convert(actor), locals);
  151. }
  152. LocsT locals;
  153. };
  154. ///////////////////////////////////////////////////////////////////////////////
  155. //
  156. // Front end generator functions. These generators are overloaded for
  157. // 1..N local variables. context<T0,... TN>(i0,...iN) generate context_gen
  158. // objects (see above).
  159. //
  160. ///////////////////////////////////////////////////////////////////////////////
  161. template <typename T0>
  162. inline context_gen<tuple<T0> >
  163. context()
  164. {
  165. typedef tuple<T0> tuple_t;
  166. return context_gen<tuple_t>(tuple_t(T0()));
  167. }
  168. //////////////////////////////////
  169. template <typename T0, typename T1>
  170. inline context_gen<tuple<T0, T1> >
  171. context(
  172. T1 const& _1 = T1()
  173. )
  174. {
  175. typedef tuple<T0, T1> tuple_t;
  176. return context_gen<tuple_t>(tuple_t(T0(), _1));
  177. }
  178. //////////////////////////////////
  179. template <typename T0, typename T1, typename T2>
  180. inline context_gen<tuple<T0, T1, T2> >
  181. context(
  182. T1 const& _1 = T1(),
  183. T2 const& _2 = T2()
  184. )
  185. {
  186. typedef tuple<T0, T1, T2> tuple_t;
  187. return context_gen<tuple_t>(tuple_t(T0(), _1, _2));
  188. }
  189. //////////////////////////////////
  190. template <typename T0, typename T1, typename T2, typename T3>
  191. inline context_gen<tuple<T0, T1, T2, T3> >
  192. context(
  193. T1 const& _1 = T1(),
  194. T2 const& _2 = T2(),
  195. T3 const& _3 = T3()
  196. )
  197. {
  198. typedef tuple<T0, T1, T2, T3> tuple_t;
  199. return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3));
  200. }
  201. //////////////////////////////////
  202. template <typename T0, typename T1, typename T2, typename T3, typename T4>
  203. inline context_gen<tuple<T0, T1, T2, T3, T4> >
  204. context(
  205. T1 const& _1 = T1(),
  206. T2 const& _2 = T2(),
  207. T3 const& _3 = T3(),
  208. T4 const& _4 = T4()
  209. )
  210. {
  211. typedef tuple<T0, T1, T2, T3> tuple_t;
  212. return context_gen<tuple_t>(tuple_t(T0(), _1, _2, _3, _4));
  213. }
  214. ///////////////////////////////////////////////////////////////////////////////
  215. }
  216. //////////////////////////////////
  217. using namespace std;
  218. using namespace phoenix;
  219. using namespace phoenix::locals;
  220. //////////////////////////////////
  221. int
  222. main()
  223. {
  224. int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  225. vector<int> c(init, init + 10);
  226. typedef vector<int>::iterator iterator;
  227. // find the first element > 5, print each element
  228. // as we traverse the container c. Print the result
  229. // if one is found.
  230. find_if(c.begin(), c.end(),
  231. context<bool>()
  232. [
  233. cout << arg1,
  234. result = arg1 > 5,
  235. if_(!result)
  236. [
  237. cout << val(", ")
  238. ]
  239. .else_
  240. [
  241. cout << val(" found result == ") << arg1
  242. ]
  243. ]
  244. );
  245. return 0;
  246. }