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

http://hadesmem.googlecode.com/ · C++ Header · 1212 lines · 684 code · 133 blank · 395 comment · 9 complexity · b7fda702f0cc8a9f311637e8e20309ea MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file traits.hpp
  3. /// Contains definitions for child\<\>, child_c\<\>, left\<\>,
  4. /// right\<\>, tag_of\<\>, and the helper functions child(), child_c(),
  5. /// value(), left() and right().
  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_ARG_TRAITS_HPP_EAN_04_01_2005
  11. #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005
  12. #include <boost/config.hpp>
  13. #include <boost/detail/workaround.hpp>
  14. #include <boost/preprocessor/iteration/iterate.hpp>
  15. #include <boost/preprocessor/repetition/enum.hpp>
  16. #include <boost/preprocessor/repetition/enum_params.hpp>
  17. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  18. #include <boost/preprocessor/repetition/repeat.hpp>
  19. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  20. #include <boost/preprocessor/facilities/intercept.hpp>
  21. #include <boost/preprocessor/arithmetic/sub.hpp>
  22. #include <boost/static_assert.hpp>
  23. #include <boost/mpl/bool.hpp>
  24. #include <boost/proto/detail/template_arity.hpp>
  25. #include <boost/type_traits/is_pod.hpp>
  26. #include <boost/type_traits/is_same.hpp>
  27. #include <boost/type_traits/add_const.hpp>
  28. #include <boost/proto/proto_fwd.hpp>
  29. #include <boost/proto/args.hpp>
  30. #include <boost/proto/domain.hpp>
  31. #include <boost/proto/transform/pass_through.hpp>
  32. #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 )
  33. #pragma warning(push)
  34. #pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored
  35. #endif
  36. namespace boost { namespace proto
  37. {
  38. namespace detail
  39. {
  40. template<typename T, typename Void = void>
  41. struct if_vararg
  42. {};
  43. template<typename T>
  44. struct if_vararg<T, typename T::proto_is_vararg_>
  45. : T
  46. {};
  47. template<typename T, typename Void = void>
  48. struct is_callable2_
  49. : mpl::false_
  50. {};
  51. template<typename T>
  52. struct is_callable2_<T, typename T::proto_is_callable_>
  53. : mpl::true_
  54. {};
  55. template<typename T BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = boost::proto::detail::template_arity<T>::value)>
  56. struct is_callable_
  57. : is_callable2_<T>
  58. {};
  59. }
  60. /// \brief Boolean metafunction which detects whether a type is
  61. /// a callable function object type or not.
  62. ///
  63. /// <tt>is_callable\<\></tt> is used by the <tt>when\<\></tt> transform
  64. /// to determine whether a function type <tt>R(A1,A2,...AN)</tt> is a
  65. /// callable transform or an object transform. (The former are evaluated
  66. /// using <tt>call\<\></tt> and the later with <tt>make\<\></tt>.) If
  67. /// <tt>is_callable\<R\>::value</tt> is \c true, the function type is
  68. /// a callable transform; otherwise, it is an object transform.
  69. ///
  70. /// Unless specialized for a type \c T, <tt>is_callable\<T\>::value</tt>
  71. /// is computed as follows:
  72. ///
  73. /// \li If \c T is a template type <tt>X\<Y0,Y1,...YN\></tt>, where all \c Yx
  74. /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::value</tt>
  75. /// is <tt>is_same\<YN, proto::callable\>::value</tt>.
  76. /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef
  77. /// for \c void, <tt>is_callable\<T\>::value</tt> is \c true. (Note: this is
  78. /// the case for any type that derives from \c proto::callable.)
  79. /// \li Otherwise, <tt>is_callable\<T\>::value</tt> is \c false.
  80. template<typename T>
  81. struct is_callable
  82. : proto::detail::is_callable_<T>
  83. {};
  84. /// INTERNAL ONLY
  85. ///
  86. template<>
  87. struct is_callable<proto::_>
  88. : mpl::true_
  89. {};
  90. /// INTERNAL ONLY
  91. ///
  92. template<>
  93. struct is_callable<proto::callable>
  94. : mpl::false_
  95. {};
  96. /// INTERNAL ONLY
  97. ///
  98. template<typename PrimitiveTransform, typename X>
  99. struct is_callable<proto::transform<PrimitiveTransform, X> >
  100. : mpl::false_
  101. {};
  102. #if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
  103. // work around GCC bug
  104. template<typename Tag, typename Args, long N>
  105. struct is_callable<proto::expr<Tag, Args, N> >
  106. : mpl::false_
  107. {};
  108. // work around GCC bug
  109. template<typename Tag, typename Args, long N>
  110. struct is_callable<proto::basic_expr<Tag, Args, N> >
  111. : mpl::false_
  112. {};
  113. #endif
  114. /// \brief Boolean metafunction which detects whether a type is
  115. /// a PrimitiveTransform type or not.
  116. ///
  117. /// <tt>is_transform\<\></tt> is used by the <tt>call\<\></tt> transform
  118. /// to determine whether the function types <tt>R()</tt>, <tt>R(A1)</tt>,
  119. /// and <tt>R(A1, A2)</tt> should be passed the expression, state and data
  120. /// parameters (as needed).
  121. ///
  122. /// Unless specialized for a type \c T, <tt>is_transform\<T\>::value</tt>
  123. /// is computed as follows:
  124. ///
  125. /// \li If \c T has a nested type \c proto_is_transform_ that is a typedef
  126. /// for \c void, <tt>is_transform\<T\>::value</tt> is \c true. (Note: this is
  127. /// the case for any type that derives from an instantiation of \c proto::transform.)
  128. /// \li Otherwise, <tt>is_transform\<T\>::value</tt> is \c false.
  129. template<typename T, typename Void /*= void*/>
  130. struct is_transform
  131. : mpl::false_
  132. {};
  133. template<typename T>
  134. struct is_transform<T, typename T::proto_is_transform_>
  135. : mpl::true_
  136. {};
  137. /// \brief A Boolean metafunction that indicates whether a type requires
  138. /// aggregate initialization.
  139. ///
  140. /// <tt>is_aggregate\<\></tt> is used by the <tt>make\<\></tt> transform
  141. /// to determine how to construct an object of some type \c T, given some
  142. /// initialization arguments <tt>a0,a1,...aN</tt>.
  143. /// If <tt>is_aggregate\<T\>::value</tt> is \c true, then an object of
  144. /// type T will be initialized as <tt>T t = {a0,a1,...aN};</tt>. Otherwise,
  145. /// it will be initialized as <tt>T t(a0,a1,...aN)</tt>.
  146. template<typename T, typename Void>
  147. struct is_aggregate
  148. : is_pod<T>
  149. {};
  150. /// \brief Specialization of <tt>is_aggregate\<\></tt> that indicates
  151. /// that objects of <tt>expr\<\></tt> type require aggregate initialization.
  152. template<typename Tag, typename Args, long N>
  153. struct is_aggregate<proto::expr<Tag, Args, N>, void>
  154. : mpl::true_
  155. {};
  156. template<typename Tag, typename Args, long N>
  157. struct is_aggregate<proto::basic_expr<Tag, Args, N>, void>
  158. : mpl::true_
  159. {};
  160. /// INTERNAL ONLY
  161. template<typename T>
  162. struct is_aggregate<T, typename T::proto_is_aggregate_>
  163. : mpl::true_
  164. {};
  165. /// \brief A Boolean metafunction that indicates whether a given
  166. /// type \c T is a Proto expression type.
  167. ///
  168. /// If \c T has a nested type \c proto_is_expr_ that is a typedef
  169. /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
  170. /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
  171. /// from <tt>proto::extends\<\></tt> or that uses the
  172. /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
  173. /// <tt>is_expr\<T\>::value</tt> is \c false.
  174. template<typename T, typename Void /* = void*/>
  175. struct is_expr
  176. : mpl::false_
  177. {};
  178. /// \brief A Boolean metafunction that indicates whether a given
  179. /// type \c T is a Proto expression type.
  180. ///
  181. /// If \c T has a nested type \c proto_is_expr_ that is a typedef
  182. /// for \c void, <tt>is_expr\<T\>::value</tt> is \c true. (Note, this
  183. /// is the case for <tt>proto::expr\<\></tt>, any type that is derived
  184. /// from <tt>proto::extends\<\></tt> or that uses the
  185. /// <tt>BOOST_PROTO_BASIC_EXTENDS()</tt> macro.) Otherwise,
  186. /// <tt>is_expr\<T\>::value</tt> is \c false.
  187. template<typename T>
  188. struct is_expr<T, typename T::proto_is_expr_>
  189. : mpl::true_
  190. {};
  191. template<typename T>
  192. struct is_expr<T &, void>
  193. : is_expr<T>
  194. {};
  195. /// \brief A metafunction that returns the tag type of a
  196. /// Proto expression.
  197. template<typename Expr>
  198. struct tag_of
  199. {
  200. typedef typename Expr::proto_tag type;
  201. };
  202. template<typename Expr>
  203. struct tag_of<Expr &>
  204. {
  205. typedef typename Expr::proto_tag type;
  206. };
  207. /// \brief A metafunction that returns the arity of a
  208. /// Proto expression.
  209. template<typename Expr>
  210. struct arity_of
  211. : Expr::proto_arity
  212. {};
  213. template<typename Expr>
  214. struct arity_of<Expr &>
  215. : Expr::proto_arity
  216. {};
  217. namespace result_of
  218. {
  219. /// \brief A metafunction that computes the return type of the \c as_expr()
  220. /// function.
  221. template<typename T, typename Domain /*= default_domain*/>
  222. struct as_expr
  223. {
  224. typedef typename Domain::template as_expr<T>::result_type type;
  225. };
  226. /// \brief A metafunction that computes the return type of the \c as_child()
  227. /// function.
  228. template<typename T, typename Domain /*= default_domain*/>
  229. struct as_child
  230. {
  231. typedef typename Domain::template as_child<T>::result_type type;
  232. };
  233. /// \brief A metafunction that returns the type of the Nth child
  234. /// of a Proto expression, where N is an MPL Integral Constant.
  235. ///
  236. /// <tt>result_of::child\<Expr, N\></tt> is equivalent to
  237. /// <tt>result_of::child_c\<Expr, N::value\></tt>.
  238. template<typename Expr, typename N /* = mpl::long_<0>*/>
  239. struct child
  240. : child_c<Expr, N::value>
  241. {};
  242. /// \brief A metafunction that returns the type of the value
  243. /// of a terminal Proto expression.
  244. ///
  245. template<typename Expr>
  246. struct value
  247. {
  248. /// Verify that we are actually operating on a terminal
  249. BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
  250. /// The raw type of the Nth child as it is stored within
  251. /// \c Expr. This may be a value or a reference
  252. typedef typename Expr::proto_child0 value_type;
  253. /// The "value" type of the child, suitable for storage by value,
  254. /// computed as follows:
  255. /// \li <tt>T const(&)[N]</tt> becomes <tt>T[N]</tt>
  256. /// \li <tt>T[N]</tt> becomes <tt>T[N]</tt>
  257. /// \li <tt>T(&)[N]</tt> becomes <tt>T[N]</tt>
  258. /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
  259. /// \li <tt>T const &</tt> becomes <tt>T</tt>
  260. /// \li <tt>T &</tt> becomes <tt>T</tt>
  261. /// \li <tt>T</tt> becomes <tt>T</tt>
  262. typedef typename detail::term_traits<typename Expr::proto_child0>::value_type type;
  263. };
  264. template<typename Expr>
  265. struct value<Expr &>
  266. {
  267. /// Verify that we are actually operating on a terminal
  268. BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
  269. /// The raw type of the Nth child as it is stored within
  270. /// \c Expr. This may be a value or a reference
  271. typedef typename Expr::proto_child0 value_type;
  272. /// The "reference" type of the child, suitable for storage by
  273. /// reference, computed as follows:
  274. /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt>
  275. /// \li <tt>T[N]</tt> becomes <tt>T(&)[N]</tt>
  276. /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt>
  277. /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
  278. /// \li <tt>T const &</tt> becomes <tt>T const &</tt>
  279. /// \li <tt>T &</tt> becomes <tt>T &</tt>
  280. /// \li <tt>T</tt> becomes <tt>T &</tt>
  281. typedef typename detail::term_traits<typename Expr::proto_child0>::reference type;
  282. };
  283. template<typename Expr>
  284. struct value<Expr const &>
  285. {
  286. /// Verify that we are actually operating on a terminal
  287. BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c);
  288. /// The raw type of the Nth child as it is stored within
  289. /// \c Expr. This may be a value or a reference
  290. typedef typename Expr::proto_child0 value_type;
  291. /// The "const reference" type of the child, suitable for storage by
  292. /// const reference, computed as follows:
  293. /// \li <tt>T const(&)[N]</tt> becomes <tt>T const(&)[N]</tt>
  294. /// \li <tt>T[N]</tt> becomes <tt>T const(&)[N]</tt>
  295. /// \li <tt>T(&)[N]</tt> becomes <tt>T(&)[N]</tt>
  296. /// \li <tt>R(&)(A0,...)</tt> becomes <tt>R(&)(A0,...)</tt>
  297. /// \li <tt>T const &</tt> becomes <tt>T const &</tt>
  298. /// \li <tt>T &</tt> becomes <tt>T &</tt>
  299. /// \li <tt>T</tt> becomes <tt>T const &</tt>
  300. typedef typename detail::term_traits<typename Expr::proto_child0>::const_reference type;
  301. };
  302. /// \brief A metafunction that returns the type of the left child
  303. /// of a binary Proto expression.
  304. ///
  305. /// <tt>result_of::left\<Expr\></tt> is equivalent to
  306. /// <tt>result_of::child_c\<Expr, 0\></tt>.
  307. template<typename Expr>
  308. struct left
  309. : child_c<Expr, 0>
  310. {};
  311. /// \brief A metafunction that returns the type of the right child
  312. /// of a binary Proto expression.
  313. ///
  314. /// <tt>result_of::right\<Expr\></tt> is equivalent to
  315. /// <tt>result_of::child_c\<Expr, 1\></tt>.
  316. template<typename Expr>
  317. struct right
  318. : child_c<Expr, 1>
  319. {};
  320. } // namespace result_of
  321. /// \brief A metafunction for generating terminal expression types,
  322. /// a grammar element for matching terminal expressions, and a
  323. /// PrimitiveTransform that returns the current expression unchanged.
  324. template<typename T>
  325. struct terminal
  326. : proto::transform<terminal<T>, int>
  327. {
  328. typedef proto::expr<proto::tag::terminal, term<T>, 0> type;
  329. typedef proto::basic_expr<proto::tag::terminal, term<T>, 0> proto_grammar;
  330. template<typename Expr, typename State, typename Data>
  331. struct impl : transform_impl<Expr, State, Data>
  332. {
  333. typedef Expr result_type;
  334. /// \param e The current expression
  335. /// \pre <tt>matches\<Expr, terminal\<T\> \>::value</tt> is \c true.
  336. /// \return \c e
  337. /// \throw nothrow
  338. #ifdef BOOST_PROTO_STRICT_RESULT_OF
  339. result_type
  340. #else
  341. typename impl::expr_param
  342. #endif
  343. operator ()(
  344. typename impl::expr_param e
  345. , typename impl::state_param
  346. , typename impl::data_param
  347. ) const
  348. {
  349. return e;
  350. }
  351. };
  352. /// INTERNAL ONLY
  353. typedef proto::tag::terminal proto_tag;
  354. /// INTERNAL ONLY
  355. typedef T proto_child0;
  356. };
  357. /// \brief A metafunction for generating ternary conditional expression types,
  358. /// a grammar element for matching ternary conditional expressions, and a
  359. /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
  360. /// transform.
  361. template<typename T, typename U, typename V>
  362. struct if_else_
  363. : proto::transform<if_else_<T, U, V>, int>
  364. {
  365. typedef proto::expr<proto::tag::if_else_, list3<T, U, V>, 3> type;
  366. typedef proto::basic_expr<proto::tag::if_else_, list3<T, U, V>, 3> proto_grammar;
  367. template<typename Expr, typename State, typename Data>
  368. struct impl
  369. : detail::pass_through_impl<if_else_, Expr, State, Data>
  370. {};
  371. /// INTERNAL ONLY
  372. typedef proto::tag::if_else_ proto_tag;
  373. /// INTERNAL ONLY
  374. typedef T proto_child0;
  375. /// INTERNAL ONLY
  376. typedef U proto_child1;
  377. /// INTERNAL ONLY
  378. typedef V proto_child2;
  379. };
  380. /// \brief A metafunction for generating nullary expression types with a
  381. /// specified tag type,
  382. /// a grammar element for matching nullary expressions, and a
  383. /// PrimitiveTransform that returns the current expression unchanged.
  384. ///
  385. /// Use <tt>nullary_expr\<_, _\></tt> as a grammar element to match any
  386. /// nullary expression.
  387. template<typename Tag, typename T>
  388. struct nullary_expr
  389. : proto::transform<nullary_expr<Tag, T>, int>
  390. {
  391. typedef proto::expr<Tag, term<T>, 0> type;
  392. typedef proto::basic_expr<Tag, term<T>, 0> proto_grammar;
  393. template<typename Expr, typename State, typename Data>
  394. struct impl : transform_impl<Expr, State, Data>
  395. {
  396. typedef Expr result_type;
  397. /// \param e The current expression
  398. /// \pre <tt>matches\<Expr, nullary_expr\<Tag, T\> \>::value</tt> is \c true.
  399. /// \return \c e
  400. /// \throw nothrow
  401. #ifdef BOOST_PROTO_STRICT_RESULT_OF
  402. result_type
  403. #else
  404. typename impl::expr_param
  405. #endif
  406. operator ()(
  407. typename impl::expr_param e
  408. , typename impl::state_param
  409. , typename impl::data_param
  410. ) const
  411. {
  412. return e;
  413. }
  414. };
  415. /// INTERNAL ONLY
  416. typedef Tag proto_tag;
  417. /// INTERNAL ONLY
  418. typedef T proto_child0;
  419. };
  420. /// \brief A metafunction for generating unary expression types with a
  421. /// specified tag type,
  422. /// a grammar element for matching unary expressions, and a
  423. /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
  424. /// transform.
  425. ///
  426. /// Use <tt>unary_expr\<_, _\></tt> as a grammar element to match any
  427. /// unary expression.
  428. template<typename Tag, typename T>
  429. struct unary_expr
  430. : proto::transform<unary_expr<Tag, T>, int>
  431. {
  432. typedef proto::expr<Tag, list1<T>, 1> type;
  433. typedef proto::basic_expr<Tag, list1<T>, 1> proto_grammar;
  434. template<typename Expr, typename State, typename Data>
  435. struct impl
  436. : detail::pass_through_impl<unary_expr, Expr, State, Data>
  437. {};
  438. /// INTERNAL ONLY
  439. typedef Tag proto_tag;
  440. /// INTERNAL ONLY
  441. typedef T proto_child0;
  442. };
  443. /// \brief A metafunction for generating binary expression types with a
  444. /// specified tag type,
  445. /// a grammar element for matching binary expressions, and a
  446. /// PrimitiveTransform that dispatches to the <tt>pass_through\<\></tt>
  447. /// transform.
  448. ///
  449. /// Use <tt>binary_expr\<_, _, _\></tt> as a grammar element to match any
  450. /// binary expression.
  451. template<typename Tag, typename T, typename U>
  452. struct binary_expr
  453. : proto::transform<binary_expr<Tag, T, U>, int>
  454. {
  455. typedef proto::expr<Tag, list2<T, U>, 2> type;
  456. typedef proto::basic_expr<Tag, list2<T, U>, 2> proto_grammar;
  457. template<typename Expr, typename State, typename Data>
  458. struct impl
  459. : detail::pass_through_impl<binary_expr, Expr, State, Data>
  460. {};
  461. /// INTERNAL ONLY
  462. typedef Tag proto_tag;
  463. /// INTERNAL ONLY
  464. typedef T proto_child0;
  465. /// INTERNAL ONLY
  466. typedef U proto_child1;
  467. };
  468. #define BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(Op) \
  469. template<typename T> \
  470. struct Op \
  471. : proto::transform<Op<T>, int> \
  472. { \
  473. typedef proto::expr<proto::tag::Op, list1<T>, 1> type; \
  474. typedef proto::basic_expr<proto::tag::Op, list1<T>, 1> proto_grammar; \
  475. \
  476. template<typename Expr, typename State, typename Data> \
  477. struct impl \
  478. : detail::pass_through_impl<Op, Expr, State, Data> \
  479. {}; \
  480. \
  481. typedef proto::tag::Op proto_tag; \
  482. typedef T proto_child0; \
  483. }; \
  484. /**/
  485. #define BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(Op) \
  486. template<typename T, typename U> \
  487. struct Op \
  488. : proto::transform<Op<T, U>, int> \
  489. { \
  490. typedef proto::expr<proto::tag::Op, list2<T, U>, 2> type; \
  491. typedef proto::basic_expr<proto::tag::Op, list2<T, U>, 2> proto_grammar; \
  492. \
  493. template<typename Expr, typename State, typename Data> \
  494. struct impl \
  495. : detail::pass_through_impl<Op, Expr, State, Data> \
  496. {}; \
  497. \
  498. typedef proto::tag::Op proto_tag; \
  499. typedef T proto_child0; \
  500. typedef U proto_child1; \
  501. }; \
  502. /**/
  503. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(unary_plus)
  504. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(negate)
  505. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(dereference)
  506. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(complement)
  507. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(address_of)
  508. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(logical_not)
  509. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_inc)
  510. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_dec)
  511. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_inc)
  512. BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_dec)
  513. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left)
  514. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right)
  515. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies)
  516. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides)
  517. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus)
  518. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus)
  519. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus)
  520. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less)
  521. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater)
  522. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less_equal)
  523. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater_equal)
  524. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(equal_to)
  525. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(not_equal_to)
  526. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_or)
  527. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_and)
  528. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or)
  529. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and)
  530. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor)
  531. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(comma)
  532. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(mem_ptr)
  533. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(assign)
  534. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left_assign)
  535. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right_assign)
  536. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies_assign)
  537. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides_assign)
  538. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus_assign)
  539. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus_assign)
  540. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus_assign)
  541. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign)
  542. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign)
  543. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign)
  544. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(subscript)
  545. BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(member)
  546. #undef BOOST_PROTO_DEFINE_UNARY_METAFUNCTION
  547. #undef BOOST_PROTO_DEFINE_BINARY_METAFUNCTION
  548. #include <boost/proto/detail/traits.hpp>
  549. namespace functional
  550. {
  551. /// \brief A callable PolymorphicFunctionObject that is
  552. /// equivalent to the \c as_expr() function.
  553. template<typename Domain /* = default_domain*/>
  554. struct as_expr
  555. {
  556. BOOST_PROTO_CALLABLE()
  557. template<typename Sig>
  558. struct result;
  559. template<typename This, typename T>
  560. struct result<This(T)>
  561. {
  562. typedef typename Domain::template as_expr<T>::result_type type;
  563. };
  564. template<typename This, typename T>
  565. struct result<This(T &)>
  566. {
  567. typedef typename Domain::template as_expr<T>::result_type type;
  568. };
  569. /// \brief Wrap an object in a Proto terminal if it isn't a
  570. /// Proto expression already.
  571. /// \param t The object to wrap.
  572. /// \return <tt>proto::as_expr\<Domain\>(t)</tt>
  573. template<typename T>
  574. typename add_const<typename result<as_expr(T &)>::type>::type
  575. operator ()(T &t) const
  576. {
  577. return typename Domain::template as_expr<T>()(t);
  578. }
  579. /// \overload
  580. ///
  581. template<typename T>
  582. typename add_const<typename result<as_expr(T const &)>::type>::type
  583. operator ()(T const &t) const
  584. {
  585. return typename Domain::template as_expr<T const>()(t);
  586. }
  587. #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  588. template<typename T, std::size_t N_>
  589. typename add_const<typename result<as_expr(T (&)[N_])>::type>::type
  590. operator ()(T (&t)[N_]) const
  591. {
  592. return typename Domain::template as_expr<T[N_]>()(t);
  593. }
  594. template<typename T, std::size_t N_>
  595. typename add_const<typename result<as_expr(T const (&)[N_])>::type>::type
  596. operator ()(T const (&t)[N_]) const
  597. {
  598. return typename Domain::template as_expr<T const[N_]>()(t);
  599. }
  600. #endif
  601. };
  602. /// \brief A callable PolymorphicFunctionObject that is
  603. /// equivalent to the \c as_child() function.
  604. template<typename Domain /* = default_domain*/>
  605. struct as_child
  606. {
  607. BOOST_PROTO_CALLABLE()
  608. template<typename Sig>
  609. struct result;
  610. template<typename This, typename T>
  611. struct result<This(T)>
  612. {
  613. typedef typename Domain::template as_child<T>::result_type type;
  614. };
  615. template<typename This, typename T>
  616. struct result<This(T &)>
  617. {
  618. typedef typename Domain::template as_child<T>::result_type type;
  619. };
  620. /// \brief Wrap an object in a Proto terminal if it isn't a
  621. /// Proto expression already.
  622. /// \param t The object to wrap.
  623. /// \return <tt>proto::as_child\<Domain\>(t)</tt>
  624. template<typename T>
  625. typename add_const<typename result<as_child(T &)>::type>::type
  626. operator ()(T &t) const
  627. {
  628. return typename Domain::template as_child<T>()(t);
  629. }
  630. /// \overload
  631. ///
  632. template<typename T>
  633. typename add_const<typename result<as_child(T const &)>::type>::type
  634. operator ()(T const &t) const
  635. {
  636. return typename Domain::template as_child<T const>()(t);
  637. }
  638. };
  639. /// \brief A callable PolymorphicFunctionObject that is
  640. /// equivalent to the \c child_c() function.
  641. template<long N>
  642. struct child_c
  643. {
  644. BOOST_PROTO_CALLABLE()
  645. template<typename Sig>
  646. struct result;
  647. template<typename This, typename Expr>
  648. struct result<This(Expr)>
  649. {
  650. typedef typename result_of::child_c<Expr, N>::type type;
  651. };
  652. /// \brief Return the Nth child of the given expression.
  653. /// \param expr The expression node.
  654. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
  655. /// \pre <tt>N \< Expr::proto_arity::value</tt>
  656. /// \return <tt>proto::child_c\<N\>(expr)</tt>
  657. /// \throw nothrow
  658. template<typename Expr>
  659. typename result_of::child_c<Expr &, N>::type
  660. operator ()(Expr &e) const
  661. {
  662. return result_of::child_c<Expr &, N>::call(e);
  663. }
  664. /// \overload
  665. ///
  666. template<typename Expr>
  667. typename result_of::child_c<Expr const &, N>::type
  668. operator ()(Expr const &e) const
  669. {
  670. return result_of::child_c<Expr const &, N>::call(e);
  671. }
  672. };
  673. /// \brief A callable PolymorphicFunctionObject that is
  674. /// equivalent to the \c child() function.
  675. ///
  676. /// A callable PolymorphicFunctionObject that is
  677. /// equivalent to the \c child() function. \c N is required
  678. /// to be an MPL Integral Constant.
  679. template<typename N /* = mpl::long_<0>*/>
  680. struct child
  681. {
  682. BOOST_PROTO_CALLABLE()
  683. template<typename Sig>
  684. struct result;
  685. template<typename This, typename Expr>
  686. struct result<This(Expr)>
  687. {
  688. typedef typename result_of::child<Expr, N>::type type;
  689. };
  690. /// \brief Return the Nth child of the given expression.
  691. /// \param expr The expression node.
  692. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
  693. /// \pre <tt>N::value \< Expr::proto_arity::value</tt>
  694. /// \return <tt>proto::child\<N\>(expr)</tt>
  695. /// \throw nothrow
  696. template<typename Expr>
  697. typename result_of::child<Expr &, N>::type
  698. operator ()(Expr &e) const
  699. {
  700. return result_of::child<Expr &, N>::call(e);
  701. }
  702. /// \overload
  703. ///
  704. template<typename Expr>
  705. typename result_of::child<Expr const &, N>::type
  706. operator ()(Expr const &e) const
  707. {
  708. return result_of::child<Expr const &, N>::call(e);
  709. }
  710. };
  711. /// \brief A callable PolymorphicFunctionObject that is
  712. /// equivalent to the \c value() function.
  713. struct value
  714. {
  715. BOOST_PROTO_CALLABLE()
  716. template<typename Sig>
  717. struct result;
  718. template<typename This, typename Expr>
  719. struct result<This(Expr)>
  720. {
  721. typedef typename result_of::value<Expr>::type type;
  722. };
  723. /// \brief Return the value of the given terminal expression.
  724. /// \param expr The terminal expression node.
  725. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
  726. /// \pre <tt>0 == Expr::proto_arity::value</tt>
  727. /// \return <tt>proto::value(expr)</tt>
  728. /// \throw nothrow
  729. template<typename Expr>
  730. typename result_of::value<Expr &>::type
  731. operator ()(Expr &e) const
  732. {
  733. return e.proto_base().child0;
  734. }
  735. /// \overload
  736. ///
  737. template<typename Expr>
  738. typename result_of::value<Expr const &>::type
  739. operator ()(Expr const &e) const
  740. {
  741. return e.proto_base().child0;
  742. }
  743. };
  744. /// \brief A callable PolymorphicFunctionObject that is
  745. /// equivalent to the \c left() function.
  746. struct left
  747. {
  748. BOOST_PROTO_CALLABLE()
  749. template<typename Sig>
  750. struct result;
  751. template<typename This, typename Expr>
  752. struct result<This(Expr)>
  753. {
  754. typedef typename result_of::left<Expr>::type type;
  755. };
  756. /// \brief Return the left child of the given binary expression.
  757. /// \param expr The expression node.
  758. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
  759. /// \pre <tt>2 == Expr::proto_arity::value</tt>
  760. /// \return <tt>proto::left(expr)</tt>
  761. /// \throw nothrow
  762. template<typename Expr>
  763. typename result_of::left<Expr &>::type
  764. operator ()(Expr &e) const
  765. {
  766. return e.proto_base().child0;
  767. }
  768. /// \overload
  769. ///
  770. template<typename Expr>
  771. typename result_of::left<Expr const &>::type
  772. operator ()(Expr const &e) const
  773. {
  774. return e.proto_base().child0;
  775. }
  776. };
  777. /// \brief A callable PolymorphicFunctionObject that is
  778. /// equivalent to the \c right() function.
  779. struct right
  780. {
  781. BOOST_PROTO_CALLABLE()
  782. template<typename Sig>
  783. struct result;
  784. template<typename This, typename Expr>
  785. struct result<This(Expr)>
  786. {
  787. typedef typename result_of::right<Expr>::type type;
  788. };
  789. /// \brief Return the right child of the given binary expression.
  790. /// \param expr The expression node.
  791. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true
  792. /// \pre <tt>2 == Expr::proto_arity::value</tt>
  793. /// \return <tt>proto::right(expr)</tt>
  794. /// \throw nothrow
  795. template<typename Expr>
  796. typename result_of::right<Expr &>::type
  797. operator ()(Expr &e) const
  798. {
  799. return e.proto_base().child1;
  800. }
  801. template<typename Expr>
  802. typename result_of::right<Expr const &>::type
  803. operator ()(Expr const &e) const
  804. {
  805. return e.proto_base().child1;
  806. }
  807. };
  808. }
  809. /// \brief A function that wraps non-Proto expression types in Proto
  810. /// terminals and leaves Proto expression types alone.
  811. ///
  812. /// The <tt>as_expr()</tt> function turns objects into Proto terminals if
  813. /// they are not Proto expression types already. Non-Proto types are
  814. /// held by value, if possible. Types which are already Proto types are
  815. /// left alone and returned by reference.
  816. ///
  817. /// This function can be called either with an explicitly specified
  818. /// \c Domain parameter (i.e., <tt>as_expr\<Domain\>(t)</tt>), or
  819. /// without (i.e., <tt>as_expr(t)</tt>). If no domain is
  820. /// specified, \c default_domain is assumed.
  821. ///
  822. /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is
  823. /// returned unmodified, by reference. Otherwise, the argument is wrapped
  824. /// in a Proto terminal expression node according to the following rules.
  825. /// If \c T is a function type, let \c A be <tt>T &</tt>. Otherwise, let
  826. /// \c A be the type \c T stripped of cv-qualifiers. Then, \c as_expr()
  827. /// returns <tt>Domain()(terminal\<A\>::type::make(t))</tt>.
  828. ///
  829. /// \param t The object to wrap.
  830. template<typename T>
  831. typename add_const<typename result_of::as_expr<T, default_domain>::type>::type
  832. as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
  833. {
  834. return default_domain::as_expr<T>()(t);
  835. }
  836. /// \overload
  837. ///
  838. template<typename T>
  839. typename add_const<typename result_of::as_expr<T const, default_domain>::type>::type
  840. as_expr(T const &t)
  841. {
  842. return default_domain::as_expr<T const>()(t);
  843. }
  844. /// \overload
  845. ///
  846. template<typename Domain, typename T>
  847. typename add_const<typename result_of::as_expr<T, Domain>::type>::type
  848. as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
  849. {
  850. return typename Domain::template as_expr<T>()(t);
  851. }
  852. /// \overload
  853. ///
  854. template<typename Domain, typename T>
  855. typename add_const<typename result_of::as_expr<T const, Domain>::type>::type
  856. as_expr(T const &t)
  857. {
  858. return typename Domain::template as_expr<T const>()(t);
  859. }
  860. /// \brief A function that wraps non-Proto expression types in Proto
  861. /// terminals (by reference) and returns Proto expression types by
  862. /// reference
  863. ///
  864. /// The <tt>as_child()</tt> function turns objects into Proto terminals if
  865. /// they are not Proto expression types already. Non-Proto types are
  866. /// held by reference. Types which are already Proto types are simply
  867. /// returned as-is.
  868. ///
  869. /// This function can be called either with an explicitly specified
  870. /// \c Domain parameter (i.e., <tt>as_child\<Domain\>(t)</tt>), or
  871. /// without (i.e., <tt>as_child(t)</tt>). If no domain is
  872. /// specified, \c default_domain is assumed.
  873. ///
  874. /// If <tt>is_expr\<T\>::value</tt> is \c true, then the argument is
  875. /// returned as-is. Otherwise, \c as_child() returns
  876. /// <tt>Domain()(terminal\<T &\>::type::make(t))</tt>.
  877. ///
  878. /// \param t The object to wrap.
  879. template<typename T>
  880. typename add_const<typename result_of::as_child<T, default_domain>::type>::type
  881. as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
  882. {
  883. return default_domain::as_child<T>()(t);
  884. }
  885. /// \overload
  886. ///
  887. template<typename T>
  888. typename add_const<typename result_of::as_child<T const, default_domain>::type>::type
  889. as_child(T const &t)
  890. {
  891. return default_domain::as_child<T const>()(t);
  892. }
  893. /// \overload
  894. ///
  895. template<typename Domain, typename T>
  896. typename add_const<typename result_of::as_child<T, Domain>::type>::type
  897. as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T))
  898. {
  899. return typename Domain::template as_child<T>()(t);
  900. }
  901. /// \overload
  902. ///
  903. template<typename Domain, typename T>
  904. typename add_const<typename result_of::as_child<T const, Domain>::type>::type
  905. as_child(T const &t)
  906. {
  907. return typename Domain::template as_child<T const>()(t);
  908. }
  909. /// \brief Return the Nth child of the specified Proto expression.
  910. ///
  911. /// Return the Nth child of the specified Proto expression. If
  912. /// \c N is not specified, as in \c child(expr), then \c N is assumed
  913. /// to be <tt>mpl::long_\<0\></tt>. The child is returned by
  914. /// reference.
  915. ///
  916. /// \param expr The Proto expression.
  917. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
  918. /// \pre \c N is an MPL Integral Constant.
  919. /// \pre <tt>N::value \< Expr::proto_arity::value</tt>
  920. /// \throw nothrow
  921. /// \return A reference to the Nth child
  922. template<typename N, typename Expr>
  923. typename result_of::child<Expr &, N>::type
  924. child(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
  925. {
  926. return result_of::child<Expr &, N>::call(e);
  927. }
  928. /// \overload
  929. ///
  930. template<typename N, typename Expr>
  931. typename result_of::child<Expr const &, N>::type
  932. child(Expr const &e)
  933. {
  934. return result_of::child<Expr const &, N>::call(e);
  935. }
  936. /// \overload
  937. ///
  938. template<typename Expr2>
  939. typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::reference
  940. child(Expr2 &expr2 BOOST_PROTO_DISABLE_IF_IS_CONST(Expr2))
  941. {
  942. return expr2.proto_base().child0;
  943. }
  944. /// \overload
  945. ///
  946. template<typename Expr2>
  947. typename detail::expr_traits<typename Expr2::proto_base_expr::proto_child0>::const_reference
  948. child(Expr2 const &expr2)
  949. {
  950. return expr2.proto_base().child0;
  951. }
  952. /// \brief Return the Nth child of the specified Proto expression.
  953. ///
  954. /// Return the Nth child of the specified Proto expression. The child
  955. /// is returned by reference.
  956. ///
  957. /// \param expr The Proto expression.
  958. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
  959. /// \pre <tt>N \< Expr::proto_arity::value</tt>
  960. /// \throw nothrow
  961. /// \return A reference to the Nth child
  962. template<long N, typename Expr>
  963. typename result_of::child_c<Expr &, N>::type
  964. child_c(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
  965. {
  966. return result_of::child_c<Expr &, N>::call(e);
  967. }
  968. /// \overload
  969. ///
  970. template<long N, typename Expr>
  971. typename result_of::child_c<Expr const &, N>::type
  972. child_c(Expr const &e)
  973. {
  974. return result_of::child_c<Expr const &, N>::call(e);
  975. }
  976. /// \brief Return the value stored within the specified Proto
  977. /// terminal expression.
  978. ///
  979. /// Return the the value stored within the specified Proto
  980. /// terminal expression. The value is returned by
  981. /// reference.
  982. ///
  983. /// \param expr The Proto terminal expression.
  984. /// \pre <tt>N::value == 0</tt>
  985. /// \throw nothrow
  986. /// \return A reference to the terminal's value
  987. template<typename Expr>
  988. typename result_of::value<Expr &>::type
  989. value(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
  990. {
  991. return e.proto_base().child0;
  992. }
  993. /// \overload
  994. ///
  995. template<typename Expr>
  996. typename result_of::value<Expr const &>::type
  997. value(Expr const &e)
  998. {
  999. return e.proto_base().child0;
  1000. }
  1001. /// \brief Return the left child of the specified binary Proto
  1002. /// expression.
  1003. ///
  1004. /// Return the left child of the specified binary Proto expression. The
  1005. /// child is returned by reference.
  1006. ///
  1007. /// \param expr The Proto expression.
  1008. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
  1009. /// \pre <tt>2 == Expr::proto_arity::value</tt>
  1010. /// \throw nothrow
  1011. /// \return A reference to the left child
  1012. template<typename Expr>
  1013. typename result_of::left<Expr &>::type
  1014. left(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
  1015. {
  1016. return e.proto_base().child0;
  1017. }
  1018. /// \overload
  1019. ///
  1020. template<typename Expr>
  1021. typename result_of::left<Expr const &>::type
  1022. left(Expr const &e)
  1023. {
  1024. return e.proto_base().child0;
  1025. }
  1026. /// \brief Return the right child of the specified binary Proto
  1027. /// expression.
  1028. ///
  1029. /// Return the right child of the specified binary Proto expression. The
  1030. /// child is returned by reference.
  1031. ///
  1032. /// \param expr The Proto expression.
  1033. /// \pre <tt>is_expr\<Expr\>::value</tt> is \c true.
  1034. /// \pre <tt>2 == Expr::proto_arity::value</tt>
  1035. /// \throw nothrow
  1036. /// \return A reference to the right child
  1037. template<typename Expr>
  1038. typename result_of::right<Expr &>::type
  1039. right(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr))
  1040. {
  1041. return e.proto_base().child1;
  1042. }
  1043. /// \overload
  1044. ///
  1045. template<typename Expr>
  1046. typename result_of::right<Expr const &>::type
  1047. right(Expr const &e)
  1048. {
  1049. return e.proto_base().child1;
  1050. }
  1051. /// INTERNAL ONLY
  1052. ///
  1053. template<typename Domain>
  1054. struct is_callable<functional::as_expr<Domain> >
  1055. : mpl::true_
  1056. {};
  1057. /// INTERNAL ONLY
  1058. ///
  1059. template<typename Domain>
  1060. struct is_callable<functional::as_child<Domain> >
  1061. : mpl::true_
  1062. {};
  1063. /// INTERNAL ONLY
  1064. ///
  1065. template<long N>
  1066. struct is_callable<functional::child_c<N> >
  1067. : mpl::true_
  1068. {};
  1069. /// INTERNAL ONLY
  1070. ///
  1071. template<typename N>
  1072. struct is_callable<functional::child<N> >
  1073. : mpl::true_
  1074. {};
  1075. }}
  1076. #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 )
  1077. #pragma warning(pop)
  1078. #endif
  1079. #endif