arg.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file arg.hpp
  3. /// Contains definition of the argN transforms.
  4. //
  5. // Copyright 2008 Eric Niebler. Distributed under the Boost
  6. // Software License, Version 1.0. (See accompanying file
  7. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_PROTO_TRANSFORM_ARG_HPP_EAN_11_01_2007
  9. #define BOOST_PROTO_TRANSFORM_ARG_HPP_EAN_11_01_2007
  10. #include <boost/mpl/if.hpp>
  11. #include <boost/proto/proto_fwd.hpp>
  12. #include <boost/proto/traits.hpp>
  13. #include <boost/proto/transform/impl.hpp>
  14. #include <boost/type_traits/is_array.hpp>
  15. #include <boost/proto/transform/env.hpp>
  16. namespace boost { namespace proto
  17. {
  18. /// \brief A PrimitiveTransform that returns the current expression
  19. /// unmodified
  20. ///
  21. /// Example:
  22. ///
  23. /// \code
  24. /// proto::terminal<int>::type i = {42};
  25. /// proto::terminal<int>::type & j = proto::_expr()(i);
  26. /// assert( boost::addressof(i) == boost::addressof(j) );
  27. /// \endcode
  28. struct _expr : transform<_expr>
  29. {
  30. template<typename Expr, typename State, typename Data>
  31. struct impl : transform_impl<Expr, State, Data>
  32. {
  33. typedef Expr result_type;
  34. /// Returns the current expression.
  35. /// \param e The current expression.
  36. /// \return \c e
  37. /// \throw nothrow
  38. BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param)
  39. operator()(
  40. typename impl::expr_param e
  41. , typename impl::state_param
  42. , typename impl::data_param
  43. ) const
  44. {
  45. return e;
  46. }
  47. };
  48. };
  49. /// \brief A PrimitiveTransform that returns the current state
  50. /// unmodified
  51. ///
  52. /// Example:
  53. ///
  54. /// \code
  55. /// proto::terminal<int>::type i = {42};
  56. /// char ch = proto::_state()(i, 'a');
  57. /// assert( ch == 'a' );
  58. /// \endcode
  59. struct _state : transform<_state>
  60. {
  61. template<typename Expr, typename State, typename Data>
  62. struct impl : transform_impl<Expr, State, Data>
  63. {
  64. typedef State result_type;
  65. /// Returns the current state.
  66. /// \param s The current state.
  67. /// \return \c s
  68. /// \throw nothrow
  69. BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::state_param)
  70. operator ()(
  71. typename impl::expr_param
  72. , typename impl::state_param s
  73. , typename impl::data_param
  74. ) const
  75. {
  76. return s;
  77. }
  78. };
  79. };
  80. /// \brief A PrimitiveTransform that returns the current data
  81. /// unmodified
  82. ///
  83. /// Example:
  84. ///
  85. /// \code
  86. /// proto::terminal<int>::type i = {42};
  87. /// std::string str("hello");
  88. /// std::string & data = proto::_data()(i, 'a', str);
  89. /// assert( &str == &data );
  90. /// \endcode
  91. struct _data : transform<_data>
  92. {
  93. template<typename Expr, typename State, typename Data>
  94. struct impl
  95. : mpl::if_c<
  96. is_env<Data>::value
  97. , _env_var<data_type>
  98. , _env
  99. >::type::template impl<Expr, State, Data>
  100. {};
  101. };
  102. /// \brief A PrimitiveTransform that returns N-th child of the current
  103. /// expression.
  104. ///
  105. /// Example:
  106. ///
  107. /// \code
  108. /// proto::terminal<int>::type i = {42};
  109. /// proto::terminal<int>::type & j = proto::_child_c<0>()(-i);
  110. /// assert( boost::addressof(i) == boost::addressof(j) );
  111. /// \endcode
  112. template<int N>
  113. struct _child_c : transform<_child_c<N> >
  114. {
  115. template<typename Expr, typename State, typename Data>
  116. struct impl : transform_impl<Expr, State, Data>
  117. {
  118. typedef
  119. typename result_of::child_c<Expr, N>::type
  120. result_type;
  121. /// Returns the N-th child of \c e
  122. /// \pre <tt>arity_of\<Expr\>::value \> N</tt>
  123. /// \param e The current expression.
  124. /// \return <tt>proto::child_c\<N\>(e)</tt>
  125. /// \throw nothrow
  126. #ifdef BOOST_PROTO_STRICT_RESULT_OF
  127. result_type
  128. #else
  129. typename result_of::child_c<typename impl::expr_param, N>::type
  130. #endif
  131. operator ()(
  132. typename impl::expr_param e
  133. , typename impl::state_param
  134. , typename impl::data_param
  135. ) const
  136. {
  137. return proto::child_c<N>(e);
  138. }
  139. };
  140. };
  141. /// \brief A PrimitiveTransform that returns the value of the
  142. /// current terminal expression.
  143. ///
  144. /// Example:
  145. ///
  146. /// \code
  147. /// proto::terminal<int>::type i = {42};
  148. /// int j = proto::_value()(i);
  149. /// assert( 42 == j );
  150. /// \endcode
  151. struct _value : transform<_value>
  152. {
  153. template<typename Expr, typename State, typename Data>
  154. struct impl : transform_impl<Expr, State, Data>
  155. {
  156. typedef
  157. typename result_of::value<Expr>::type
  158. result_type;
  159. /// Returns the value of the specified terminal expression.
  160. /// \pre <tt>arity_of\<Expr\>::value == 0</tt>.
  161. /// \param e The current expression.
  162. /// \return <tt>proto::value(e)</tt>
  163. /// \throw nothrow
  164. #ifdef BOOST_PROTO_STRICT_RESULT_OF
  165. typename mpl::if_c<is_array<result_type>::value, result_type &, result_type>::type
  166. #else
  167. typename result_of::value<typename impl::expr_param>::type
  168. #endif
  169. operator ()(
  170. typename impl::expr_param e
  171. , typename impl::state_param
  172. , typename impl::data_param
  173. ) const
  174. {
  175. return proto::value(e);
  176. }
  177. };
  178. };
  179. /// \brief A PrimitiveTransform that does nothing
  180. /// and returns void.
  181. struct _void : transform<_void>
  182. {
  183. template<typename Expr, typename State, typename Data>
  184. struct impl : transform_impl<Expr, State, Data>
  185. {
  186. typedef void result_type;
  187. /// Does nothing and returns void
  188. void operator ()(
  189. typename impl::expr_param
  190. , typename impl::state_param
  191. , typename impl::data_param
  192. ) const
  193. {}
  194. };
  195. };
  196. /// \brief A unary CallableTransform that wraps its argument
  197. /// in a \c boost::reference_wrapper\<\>.
  198. ///
  199. /// Example:
  200. ///
  201. /// \code
  202. /// proto::terminal<int>::type i = {42};
  203. /// boost::reference_wrapper<proto::terminal<int>::type> j
  204. /// = proto::when<_, proto::_byref(_)>()(i);
  205. /// assert( boost::addressof(i) == boost::addressof(j.get()) );
  206. /// \endcode
  207. struct _byref : callable
  208. {
  209. template<typename Sig>
  210. struct result;
  211. template<typename This, typename T>
  212. struct result<This(T)>
  213. {
  214. typedef boost::reference_wrapper<T const> const type;
  215. };
  216. template<typename This, typename T>
  217. struct result<This(T &)>
  218. {
  219. typedef boost::reference_wrapper<T> const type;
  220. };
  221. /// Wrap the parameter \c t in a \c boost::reference_wrapper\<\>
  222. /// \param t The object to wrap
  223. /// \return <tt>boost::ref(t)</tt>
  224. /// \throw nothrow
  225. template<typename T>
  226. boost::reference_wrapper<T> const operator ()(T &t) const
  227. {
  228. return boost::reference_wrapper<T>(t);
  229. }
  230. /// \overload
  231. ///
  232. template<typename T>
  233. boost::reference_wrapper<T const> const operator ()(T const &t) const
  234. {
  235. return boost::reference_wrapper<T const>(t);
  236. }
  237. };
  238. /// \brief A unary CallableTransform that strips references
  239. /// and \c boost::reference_wrapper\<\> from its argument.
  240. ///
  241. /// Example:
  242. ///
  243. /// \code
  244. /// proto::terminal<int>::type i = {42};
  245. /// int j = 67;
  246. /// int k = proto::when<_, proto::_byval(proto::_state)>()(i, boost::ref(j));
  247. /// assert( 67 == k );
  248. /// \endcode
  249. struct _byval : callable
  250. {
  251. template<typename Sig>
  252. struct result;
  253. template<typename This, typename T>
  254. struct result<This(T)>
  255. {
  256. typedef T type;
  257. };
  258. template<typename This, typename T>
  259. struct result<This(T &)>
  260. : result<This(T)>
  261. {};
  262. template<typename This, typename T>
  263. struct result<This(boost::reference_wrapper<T>)>
  264. : result<This(T)>
  265. {};
  266. /// \param t The object to unref
  267. /// \return <tt>t</tt>
  268. /// \throw nothrow
  269. template<typename T>
  270. T operator ()(T const &t) const
  271. {
  272. return t;
  273. }
  274. /// \overload
  275. ///
  276. template<typename T>
  277. T operator ()(boost::reference_wrapper<T> const &t) const
  278. {
  279. return t;
  280. }
  281. };
  282. /// INTERNAL ONLY
  283. ///
  284. template<>
  285. struct is_callable<_expr>
  286. : mpl::true_
  287. {};
  288. /// INTERNAL ONLY
  289. ///
  290. template<>
  291. struct is_callable<_state>
  292. : mpl::true_
  293. {};
  294. /// INTERNAL ONLY
  295. ///
  296. template<>
  297. struct is_callable<_data>
  298. : mpl::true_
  299. {};
  300. /// INTERNAL ONLY
  301. ///
  302. template<int N>
  303. struct is_callable<_child_c<N> >
  304. : mpl::true_
  305. {};
  306. /// INTERNAL ONLY
  307. ///
  308. template<>
  309. struct is_callable<_value>
  310. : mpl::true_
  311. {};
  312. /// INTERNAL ONLY
  313. ///
  314. template<>
  315. struct is_callable<_byref>
  316. : mpl::true_
  317. {};
  318. /// INTERNAL ONLY
  319. ///
  320. template<>
  321. struct is_callable<_byval>
  322. : mpl::true_
  323. {};
  324. }}
  325. #endif