/Src/Dependencies/Boost/boost/proto/make_expr.hpp

http://hadesmem.googlecode.com/ · C++ Header · 501 lines · 288 code · 36 blank · 177 comment · 0 complexity · 35ec970221c6bdc2423412b0a3064326 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file make_expr.hpp
  3. /// Definition of the \c make_expr() and \c unpack_expr() utilities for
  4. /// building Proto expression nodes from child nodes or from a Fusion
  5. /// sequence of child nodes, respectively.
  6. //
  7. // Copyright 2008 Eric Niebler. Distributed under the Boost
  8. // Software License, Version 1.0. (See accompanying file
  9. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005
  11. #define BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005
  12. #include <boost/preprocessor/cat.hpp>
  13. #include <boost/preprocessor/arithmetic/inc.hpp>
  14. #include <boost/preprocessor/arithmetic/dec.hpp>
  15. #include <boost/preprocessor/arithmetic/sub.hpp>
  16. #include <boost/preprocessor/punctuation/comma_if.hpp>
  17. #include <boost/preprocessor/iteration/iterate.hpp>
  18. #include <boost/preprocessor/facilities/intercept.hpp>
  19. #include <boost/preprocessor/repetition/enum.hpp>
  20. #include <boost/preprocessor/repetition/enum_params.hpp>
  21. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  22. #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
  23. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  24. #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  25. #include <boost/preprocessor/repetition/repeat.hpp>
  26. #include <boost/ref.hpp>
  27. #include <boost/mpl/if.hpp>
  28. #include <boost/mpl/assert.hpp>
  29. #include <boost/mpl/eval_if.hpp>
  30. #include <boost/utility/enable_if.hpp>
  31. #include <boost/type_traits/add_const.hpp>
  32. #include <boost/type_traits/add_reference.hpp>
  33. #include <boost/type_traits/remove_cv.hpp>
  34. #include <boost/proto/proto_fwd.hpp>
  35. #include <boost/proto/traits.hpp>
  36. #include <boost/proto/domain.hpp>
  37. #include <boost/proto/generate.hpp>
  38. #include <boost/fusion/include/begin.hpp>
  39. #include <boost/fusion/include/next.hpp>
  40. #include <boost/fusion/include/value_of.hpp>
  41. #include <boost/fusion/include/size.hpp>
  42. #include <boost/proto/detail/poly_function.hpp>
  43. #include <boost/proto/detail/deprecated.hpp>
  44. #ifdef _MSC_VER
  45. # pragma warning(push)
  46. # pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored
  47. #endif
  48. namespace boost { namespace proto
  49. {
  50. /// INTERNAL ONLY
  51. ///
  52. #define BOOST_PROTO_AS_CHILD_TYPE(Z, N, DATA) \
  53. typename boost::proto::detail::protoify< \
  54. BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N) \
  55. , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \
  56. >::result_type \
  57. /**/
  58. /// INTERNAL ONLY
  59. ///
  60. #define BOOST_PROTO_AS_CHILD(Z, N, DATA) \
  61. boost::proto::detail::protoify< \
  62. BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N) \
  63. , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \
  64. >()(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, DATA), N)) \
  65. /**/
  66. namespace detail
  67. {
  68. template<typename T, typename Domain>
  69. struct protoify
  70. : Domain::template as_expr<T>
  71. {};
  72. template<typename T, typename Domain>
  73. struct protoify<T &, Domain>
  74. : Domain::template as_child<T>
  75. {};
  76. template<typename T, typename Domain>
  77. struct protoify<boost::reference_wrapper<T>, Domain>
  78. : Domain::template as_child<T>
  79. {};
  80. template<typename T, typename Domain>
  81. struct protoify<boost::reference_wrapper<T> const, Domain>
  82. : Domain::template as_child<T>
  83. {};
  84. // Definition of detail::unpack_expr_
  85. #include <boost/proto/detail/unpack_expr_.hpp>
  86. // Definition of detail::make_expr_
  87. #include <boost/proto/detail/make_expr_.hpp>
  88. }
  89. namespace result_of
  90. {
  91. /// \brief Metafunction that computes the return type of the
  92. /// \c make_expr() function, with a domain deduced from the
  93. /// domains of the children.
  94. ///
  95. /// Use the <tt>result_of::make_expr\<\></tt> metafunction to
  96. /// compute the return type of the \c make_expr() function.
  97. ///
  98. /// In this specialization, the domain is deduced from the
  99. /// domains of the child types. (If
  100. /// <tt>is_domain\<A0\>::value</tt> is \c true, then another
  101. /// specialization is selected.)
  102. template<
  103. typename Tag
  104. , BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, typename A)
  105. , typename Void1 // = void
  106. , typename Void2 // = void
  107. >
  108. struct make_expr
  109. {
  110. /// Same as <tt>result_of::make_expr\<Tag, D, A0, ... AN\>::type</tt>
  111. /// where \c D is the deduced domain, which is calculated as follows:
  112. ///
  113. /// For each \c x in <tt>[0,N)</tt> (proceeding in order beginning with
  114. /// <tt>x=0</tt>), if <tt>domain_of\<Ax\>::type</tt> is not
  115. /// \c default_domain, then \c D is <tt>domain_of\<Ax\>::type</tt>.
  116. /// Otherwise, \c D is \c default_domain.
  117. typedef
  118. typename detail::make_expr_<
  119. Tag
  120. , deduce_domain
  121. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
  122. >::result_type
  123. type;
  124. };
  125. /// \brief Metafunction that computes the return type of the
  126. /// \c make_expr() function, within the specified domain.
  127. ///
  128. /// Use the <tt>result_of::make_expr\<\></tt> metafunction to compute
  129. /// the return type of the \c make_expr() function.
  130. template<
  131. typename Tag
  132. , typename Domain
  133. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, typename A)
  134. >
  135. struct make_expr<
  136. Tag
  137. , Domain
  138. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
  139. , typename Domain::proto_is_domain_
  140. >
  141. {
  142. /// If \c Tag is <tt>tag::terminal</tt>, then \c type is a
  143. /// typedef for <tt>boost::result_of\<Domain(expr\<tag::terminal,
  144. /// term\<A0\> \>)\>::type</tt>.
  145. ///
  146. /// Otherwise, \c type is a typedef for <tt>boost::result_of\<Domain(expr\<Tag,
  147. /// listN\< as_child\<A0\>::type, ... as_child\<AN\>::type\>)
  148. /// \>::type</tt>, where \c N is the number of non-void template
  149. /// arguments, and <tt>as_child\<A\>::type</tt> is evaluated as
  150. /// follows:
  151. ///
  152. /// \li If <tt>is_expr\<A\>::value</tt> is \c true, then the
  153. /// child type is \c A.
  154. /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
  155. /// and <tt>is_expr\<B\>::value</tt> is \c true, then the
  156. /// child type is <tt>B &</tt>.
  157. /// \li If <tt>is_expr\<A\>::value</tt> is \c false, then the
  158. /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<A\> \>
  159. /// )\>::type</tt>.
  160. /// \li If \c A is <tt>B &</tt> or <tt>cv boost::reference_wrapper\<B\></tt>,
  161. /// and <tt>is_expr\<B\>::value</tt> is \c false, then the
  162. /// child type is <tt>boost::result_of\<Domain(expr\<tag::terminal, term\<B &\> \>
  163. /// )\>::type</tt>.
  164. typedef
  165. typename detail::make_expr_<
  166. Tag
  167. , Domain
  168. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
  169. >::result_type
  170. type;
  171. };
  172. /// \brief Metafunction that computes the return type of the
  173. /// \c unpack_expr() function, with a domain deduced from the
  174. /// domains of the children.
  175. ///
  176. /// Use the <tt>result_of::unpack_expr\<\></tt> metafunction to
  177. /// compute the return type of the \c unpack_expr() function.
  178. ///
  179. /// \c Sequence is a Fusion Forward Sequence.
  180. ///
  181. /// In this specialization, the domain is deduced from the
  182. /// domains of the child types. (If
  183. /// <tt>is_domain\<Sequence>::value</tt> is \c true, then another
  184. /// specialization is selected.)
  185. template<
  186. typename Tag
  187. , typename Sequence
  188. , typename Void1 // = void
  189. , typename Void2 // = void
  190. >
  191. struct unpack_expr
  192. {
  193. /// Let \c S be the type of a Fusion Random Access Sequence
  194. /// equivalent to \c Sequence. Then \c type is the
  195. /// same as <tt>result_of::make_expr\<Tag,
  196. /// fusion::result_of::value_at_c\<S, 0\>::type, ...
  197. /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
  198. /// where \c N is the size of \c S.
  199. typedef
  200. typename detail::unpack_expr_<
  201. Tag
  202. , deduce_domain
  203. , Sequence
  204. , fusion::result_of::size<Sequence>::type::value
  205. >::type
  206. type;
  207. };
  208. /// \brief Metafunction that computes the return type of the
  209. /// \c unpack_expr() function, within the specified domain.
  210. ///
  211. /// Use the <tt>result_of::make_expr\<\></tt> metafunction to compute
  212. /// the return type of the \c make_expr() function.
  213. template<typename Tag, typename Domain, typename Sequence>
  214. struct unpack_expr<Tag, Domain, Sequence, typename Domain::proto_is_domain_>
  215. {
  216. /// Let \c S be the type of a Fusion Random Access Sequence
  217. /// equivalent to \c Sequence. Then \c type is the
  218. /// same as <tt>result_of::make_expr\<Tag, Domain,
  219. /// fusion::result_of::value_at_c\<S, 0\>::type, ...
  220. /// fusion::result_of::value_at_c\<S, N-1\>::type\>::type</tt>,
  221. /// where \c N is the size of \c S.
  222. typedef
  223. typename detail::unpack_expr_<
  224. Tag
  225. , Domain
  226. , Sequence
  227. , fusion::result_of::size<Sequence>::type::value
  228. >::type
  229. type;
  230. };
  231. }
  232. namespace functional
  233. {
  234. /// \brief A callable function object equivalent to the
  235. /// \c proto::make_expr() function.
  236. ///
  237. /// In all cases, <tt>functional::make_expr\<Tag, Domain\>()(a0, ... aN)</tt>
  238. /// is equivalent to <tt>proto::make_expr\<Tag, Domain\>(a0, ... aN)</tt>.
  239. ///
  240. /// <tt>functional::make_expr\<Tag\>()(a0, ... aN)</tt>
  241. /// is equivalent to <tt>proto::make_expr\<Tag\>(a0, ... aN)</tt>.
  242. template<typename Tag, typename Domain /* = deduce_domain*/>
  243. struct make_expr
  244. {
  245. BOOST_PROTO_CALLABLE()
  246. BOOST_PROTO_POLY_FUNCTION()
  247. template<typename Sig>
  248. struct result;
  249. template<typename This, typename A0>
  250. struct result<This(A0)>
  251. {
  252. typedef
  253. typename result_of::make_expr<
  254. Tag
  255. , Domain
  256. , A0
  257. >::type
  258. type;
  259. };
  260. /// Construct an expression node with tag type \c Tag
  261. /// and in the domain \c Domain.
  262. ///
  263. /// \return <tt>proto::make_expr\<Tag, Domain\>(a0,...aN)</tt>
  264. template<typename A0>
  265. typename result_of::make_expr<
  266. Tag
  267. , Domain
  268. , A0 const
  269. >::type const
  270. operator ()(A0 const &a0) const
  271. {
  272. return proto::detail::make_expr_<
  273. Tag
  274. , Domain
  275. , A0 const
  276. >()(a0);
  277. }
  278. // Additional overloads generated by the preprocessor ...
  279. #include <boost/proto/detail/make_expr_funop.hpp>
  280. /// INTERNAL ONLY
  281. ///
  282. template<
  283. BOOST_PP_ENUM_BINARY_PARAMS(
  284. BOOST_PROTO_MAX_ARITY
  285. , typename A
  286. , = void BOOST_PP_INTERCEPT
  287. )
  288. >
  289. struct impl
  290. : detail::make_expr_<
  291. Tag
  292. , Domain
  293. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A)
  294. >
  295. {};
  296. };
  297. /// \brief A callable function object equivalent to the
  298. /// \c proto::unpack_expr() function.
  299. ///
  300. /// In all cases, <tt>functional::unpack_expr\<Tag, Domain\>()(seq)</tt>
  301. /// is equivalent to <tt>proto::unpack_expr\<Tag, Domain\>(seq)</tt>.
  302. ///
  303. /// <tt>functional::unpack_expr\<Tag\>()(seq)</tt>
  304. /// is equivalent to <tt>proto::unpack_expr\<Tag\>(seq)</tt>.
  305. template<typename Tag, typename Domain /* = deduce_domain*/>
  306. struct unpack_expr
  307. {
  308. BOOST_PROTO_CALLABLE()
  309. template<typename Sig>
  310. struct result;
  311. template<typename This, typename Sequence>
  312. struct result<This(Sequence)>
  313. {
  314. typedef
  315. typename result_of::unpack_expr<
  316. Tag
  317. , Domain
  318. , typename remove_reference<Sequence>::type
  319. >::type
  320. type;
  321. };
  322. /// Construct an expression node with tag type \c Tag
  323. /// and in the domain \c Domain.
  324. ///
  325. /// \param sequence A Fusion Forward Sequence
  326. /// \return <tt>proto::unpack_expr\<Tag, Domain\>(sequence)</tt>
  327. template<typename Sequence>
  328. typename result_of::unpack_expr<Tag, Domain, Sequence const>::type const
  329. operator ()(Sequence const &sequence) const
  330. {
  331. return proto::detail::unpack_expr_<
  332. Tag
  333. , Domain
  334. , Sequence const
  335. , fusion::result_of::size<Sequence>::type::value
  336. >::call(sequence);
  337. }
  338. };
  339. } // namespace functional
  340. /// \brief Construct an expression of the requested tag type
  341. /// with a domain and with the specified arguments as children.
  342. ///
  343. /// This function template may be invoked either with or without
  344. /// specifying a \c Domain argument. If no domain is specified,
  345. /// the domain is deduced by examining in order the domains of
  346. /// the given arguments and taking the first that is not
  347. /// \c default_domain, if any such domain exists, or
  348. /// \c default_domain otherwise.
  349. ///
  350. /// Let \c wrap_(x) be defined such that:
  351. /// \li If \c x is a <tt>boost::reference_wrapper\<\></tt>,
  352. /// \c wrap_(x) is equivalent to <tt>as_child\<Domain\>(x.get())</tt>.
  353. /// \li Otherwise, \c wrap_(x) is equivalent to
  354. /// <tt>as_expr\<Domain\>(x)</tt>.
  355. ///
  356. /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
  357. /// <tt>expr\<Tag, listN\<C0,...CN\> \>::make(c0,...cN)</tt>
  358. /// where \c Bx is the type of \c bx.
  359. ///
  360. /// \return <tt>Domain()(make_\<Tag\>(wrap_(a0),...wrap_(aN)))</tt>.
  361. template<typename Tag, typename A0>
  362. typename lazy_disable_if<
  363. is_domain<A0>
  364. , result_of::make_expr<
  365. Tag
  366. , A0 const
  367. >
  368. >::type const
  369. make_expr(A0 const &a0)
  370. {
  371. return proto::detail::make_expr_<
  372. Tag
  373. , deduce_domain
  374. , A0 const
  375. >()(a0);
  376. }
  377. /// \overload
  378. ///
  379. template<typename Tag, typename Domain, typename C0>
  380. typename result_of::make_expr<
  381. Tag
  382. , Domain
  383. , C0 const
  384. >::type const
  385. make_expr(C0 const &c0)
  386. {
  387. return proto::detail::make_expr_<
  388. Tag
  389. , Domain
  390. , C0 const
  391. >()(c0);
  392. }
  393. // Additional overloads generated by the preprocessor...
  394. #include <boost/proto/detail/make_expr.hpp>
  395. /// \brief Construct an expression of the requested tag type
  396. /// with a domain and with childres from the specified Fusion
  397. /// Forward Sequence.
  398. ///
  399. /// This function template may be invoked either with or without
  400. /// specifying a \c Domain argument. If no domain is specified,
  401. /// the domain is deduced by examining in order the domains of the
  402. /// elements of \c sequence and taking the first that is not
  403. /// \c default_domain, if any such domain exists, or
  404. /// \c default_domain otherwise.
  405. ///
  406. /// Let \c s be a Fusion Random Access Sequence equivalent to \c sequence.
  407. /// Let <tt>wrap_\<N\>(s)</tt>, where \c s has type \c S, be defined
  408. /// such that:
  409. /// \li If <tt>fusion::result_of::value_at_c\<S,N\>::type</tt> is a reference,
  410. /// <tt>wrap_\<N\>(s)</tt> is equivalent to
  411. /// <tt>as_child\<Domain\>(fusion::at_c\<N\>(s))</tt>.
  412. /// \li Otherwise, <tt>wrap_\<N\>(s)</tt> is equivalent to
  413. /// <tt>as_expr\<Domain\>(fusion::at_c\<N\>(s))</tt>.
  414. ///
  415. /// Let <tt>make_\<Tag\>(b0,...bN)</tt> be defined as
  416. /// <tt>expr\<Tag, listN\<B0,...BN\> \>::make(b0,...bN)</tt>
  417. /// where \c Bx is the type of \c bx.
  418. ///
  419. /// \param sequence a Fusion Forward Sequence.
  420. /// \return <tt>Domain()(make_\<Tag\>(wrap_\<0\>(s),...wrap_\<N-1\>(s)))</tt>,
  421. /// where N is the size of \c Sequence.
  422. template<typename Tag, typename Sequence>
  423. typename lazy_disable_if<
  424. is_domain<Sequence>
  425. , result_of::unpack_expr<Tag, Sequence const>
  426. >::type const
  427. unpack_expr(Sequence const &sequence)
  428. {
  429. return proto::detail::unpack_expr_<
  430. Tag
  431. , deduce_domain
  432. , Sequence const
  433. , fusion::result_of::size<Sequence>::type::value
  434. >::call(sequence);
  435. }
  436. /// \overload
  437. ///
  438. template<typename Tag, typename Domain, typename Sequence2>
  439. typename result_of::unpack_expr<Tag, Domain, Sequence2 const>::type const
  440. unpack_expr(Sequence2 const &sequence2)
  441. {
  442. return proto::detail::unpack_expr_<
  443. Tag
  444. , Domain
  445. , Sequence2 const
  446. , fusion::result_of::size<Sequence2>::type::value
  447. >::call(sequence2);
  448. }
  449. /// INTERNAL ONLY
  450. ///
  451. template<typename Tag, typename Domain>
  452. struct is_callable<functional::make_expr<Tag, Domain> >
  453. : mpl::true_
  454. {};
  455. /// INTERNAL ONLY
  456. ///
  457. template<typename Tag, typename Domain>
  458. struct is_callable<functional::unpack_expr<Tag, Domain> >
  459. : mpl::true_
  460. {};
  461. }}
  462. #ifdef _MSC_VER
  463. # pragma warning(pop)
  464. #endif
  465. #endif // BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005