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

http://hadesmem.googlecode.com/ · C++ Header · 627 lines · 444 code · 61 blank · 122 comment · 1 complexity · d6c78481a090dc9667d9e9d9903d9e48 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /// \file extends.hpp
  3. /// Macros and a base class for defining end-user expression types
  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_EXTENDS_HPP_EAN_11_1_2006
  9. #define BOOST_PROTO_EXTENDS_HPP_EAN_11_1_2006
  10. #include <cstddef> // for offsetof
  11. #include <boost/config.hpp>
  12. #include <boost/detail/workaround.hpp>
  13. #include <boost/preprocessor/facilities/empty.hpp>
  14. #include <boost/preprocessor/tuple/elem.hpp>
  15. #include <boost/preprocessor/control/if.hpp>
  16. #include <boost/preprocessor/arithmetic/inc.hpp>
  17. #include <boost/preprocessor/arithmetic/dec.hpp>
  18. #include <boost/preprocessor/iteration/local.hpp>
  19. #include <boost/preprocessor/repetition/enum_params.hpp>
  20. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  21. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  22. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  23. #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  24. #include <boost/preprocessor/seq/for_each.hpp>
  25. #include <boost/utility/addressof.hpp>
  26. #include <boost/utility/result_of.hpp>
  27. #include <boost/proto/proto_fwd.hpp>
  28. #include <boost/proto/traits.hpp>
  29. #include <boost/proto/expr.hpp>
  30. #include <boost/proto/args.hpp>
  31. #include <boost/proto/traits.hpp>
  32. #include <boost/proto/generate.hpp>
  33. #ifdef _MSC_VER
  34. #define BOOST_PROTO_DISABLE_MSVC_C4522 __pragma(warning(disable: 4522))
  35. #else
  36. #define BOOST_PROTO_DISABLE_MSVC_C4522
  37. #endif
  38. namespace boost { namespace proto
  39. {
  40. #ifdef __GNUC__
  41. /// INTERNAL ONLY
  42. ///
  43. # define BOOST_PROTO_ADDROF(x) ((char const volatile*)boost::addressof(x))
  44. /// INTERNAL ONLY
  45. ///
  46. # define BOOST_PROTO_OFFSETOF(s,m) (BOOST_PROTO_ADDROF((((s *)this)->m)) - BOOST_PROTO_ADDROF(*((s *)this)))
  47. #else
  48. /// INTERNAL ONLY
  49. ///
  50. # define BOOST_PROTO_OFFSETOF offsetof
  51. #endif
  52. /// INTERNAL ONLY
  53. ///
  54. #define BOOST_PROTO_CONST() const
  55. /// INTERNAL ONLY
  56. ///
  57. #define BOOST_PROTO_TYPENAME() typename
  58. /// INTERNAL ONLY
  59. ///
  60. #define BOOST_PROTO_TEMPLATE_YES_(Z, N) template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>
  61. /// INTERNAL ONLY
  62. ///
  63. #define BOOST_PROTO_TEMPLATE_NO_(Z, N)
  64. /// INTERNAL ONLY
  65. ///
  66. #define BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, Const) \
  67. BOOST_PP_IF(N, BOOST_PROTO_TEMPLATE_YES_, BOOST_PROTO_TEMPLATE_NO_)(Z, N) \
  68. typename BOOST_PROTO_RESULT_OF< \
  69. proto_generator( \
  70. typename boost::proto::result_of::BOOST_PP_CAT(funop, N)< \
  71. proto_derived_expr Const() \
  72. , proto_domain \
  73. BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, const A) \
  74. >::type \
  75. ) \
  76. >::type const \
  77. operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) Const() \
  78. { \
  79. typedef boost::proto::result_of::BOOST_PP_CAT(funop, N)< \
  80. proto_derived_expr Const() \
  81. , proto_domain \
  82. BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, const A) \
  83. > funop; \
  84. return proto_generator()( \
  85. funop::call( \
  86. *static_cast<proto_derived_expr Const() *>(this) \
  87. BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, a) \
  88. ) \
  89. ); \
  90. } \
  91. /**/
  92. /// INTERNAL ONLY
  93. ///
  94. #define BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(Const) \
  95. template<typename... A> \
  96. typename BOOST_PROTO_RESULT_OF< \
  97. proto_generator( \
  98. typename boost::proto::result_of::funop< \
  99. proto_derived_expr Const()(A const &...) \
  100. , proto_derived_expr \
  101. , proto_domain \
  102. >::type \
  103. ) \
  104. >::type const \
  105. operator ()(A const &...a) Const() \
  106. { \
  107. typedef boost::proto::result_of::funop< \
  108. proto_derived_expr Const()(A const &...) \
  109. , proto_derived_expr \
  110. , proto_domain \
  111. > funop; \
  112. return proto_generator()( \
  113. funop::call( \
  114. *static_cast<proto_derived_expr Const() *>(this) \
  115. , a... \
  116. ) \
  117. ); \
  118. } \
  119. /**/
  120. /// INTERNAL ONLY
  121. ///
  122. #define BOOST_PROTO_DEFINE_FUN_OP_CONST(Z, N, DATA) \
  123. BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, BOOST_PROTO_CONST) \
  124. /**/
  125. /// INTERNAL ONLY
  126. ///
  127. #define BOOST_PROTO_DEFINE_FUN_OP_NON_CONST(Z, N, DATA) \
  128. BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, BOOST_PP_EMPTY) \
  129. /**/
  130. /// INTERNAL ONLY
  131. ///
  132. #define BOOST_PROTO_DEFINE_FUN_OP(Z, N, DATA) \
  133. BOOST_PROTO_DEFINE_FUN_OP_CONST(Z, N, DATA) \
  134. BOOST_PROTO_DEFINE_FUN_OP_NON_CONST(Z, N, DATA) \
  135. /**/
  136. /// INTERNAL ONLY
  137. ///
  138. #define BOOST_PROTO_EXTENDS_CHILD(Z, N, DATA) \
  139. typedef \
  140. typename proto_base_expr::BOOST_PP_CAT(proto_child, N) \
  141. BOOST_PP_CAT(proto_child, N); \
  142. /**/
  143. #define BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain) \
  144. Expr proto_expr_; \
  145. \
  146. typedef Expr proto_base_expr_; /**< INTERNAL ONLY */ \
  147. typedef typename proto_base_expr_::proto_base_expr proto_base_expr; \
  148. typedef Domain proto_domain; \
  149. typedef Derived proto_derived_expr; \
  150. typedef typename proto_base_expr::proto_tag proto_tag; \
  151. typedef typename proto_base_expr::proto_args proto_args; \
  152. typedef typename proto_base_expr::proto_arity proto_arity; \
  153. typedef typename proto_base_expr::proto_grammar proto_grammar; \
  154. typedef typename proto_base_expr::address_of_hack_type_ proto_address_of_hack_type_; \
  155. typedef void proto_is_expr_; /**< INTERNAL ONLY */ \
  156. static const long proto_arity_c = proto_base_expr::proto_arity_c; \
  157. typedef boost::proto::tag::proto_expr fusion_tag; \
  158. BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, BOOST_PROTO_EXTENDS_CHILD, ~) \
  159. \
  160. static proto_derived_expr const make(Expr const &e) \
  161. { \
  162. proto_derived_expr that = {e}; \
  163. return that; \
  164. } \
  165. \
  166. proto_base_expr &proto_base() \
  167. { \
  168. return this->proto_expr_.proto_base(); \
  169. } \
  170. \
  171. proto_base_expr const &proto_base() const \
  172. { \
  173. return this->proto_expr_.proto_base(); \
  174. } \
  175. \
  176. operator proto_address_of_hack_type_() const \
  177. { \
  178. return boost::addressof(this->proto_base().child0); \
  179. } \
  180. /**/
  181. #define BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, Domain) \
  182. BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain) \
  183. typedef void proto_is_aggregate_; \
  184. typedef Domain::proto_generator proto_generator; \
  185. /**< INTERNAL ONLY */
  186. #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, Const, Typename) \
  187. BOOST_PROTO_DISABLE_MSVC_C4522 \
  188. Typename() BOOST_PROTO_RESULT_OF< \
  189. Typename() This::proto_generator( \
  190. Typename() boost::proto::base_expr< \
  191. Typename() This::proto_domain \
  192. , boost::proto::tag::assign \
  193. , boost::proto::list2< \
  194. This & \
  195. , This Const() & \
  196. > \
  197. >::type \
  198. ) \
  199. >::type const \
  200. operator =(This Const() &a) \
  201. { \
  202. typedef \
  203. Typename() boost::proto::base_expr< \
  204. Typename() This::proto_domain \
  205. , boost::proto::tag::assign \
  206. , boost::proto::list2< \
  207. This & \
  208. , This Const() & \
  209. > \
  210. >::type \
  211. that_type; \
  212. that_type const that = { \
  213. *this \
  214. , a \
  215. }; \
  216. return Typename() This::proto_generator()(that); \
  217. } \
  218. /**/
  219. // MSVC 8.0 and higher seem to need copy-assignment operator to be overloaded on *both*
  220. // const and non-const rhs arguments.
  221. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) && (BOOST_MSVC > 1310)
  222. #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_(This, Typename) \
  223. BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PP_EMPTY, Typename) \
  224. BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PROTO_CONST, Typename) \
  225. /**/
  226. #else
  227. #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_(This, Typename) \
  228. BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PROTO_CONST, Typename) \
  229. /**/
  230. #endif
  231. /// INTERNAL ONLY
  232. ///
  233. #define BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(ThisConst, ThatConst) \
  234. template<typename A> \
  235. typename BOOST_PROTO_RESULT_OF< \
  236. proto_generator( \
  237. typename boost::proto::base_expr< \
  238. proto_domain \
  239. , boost::proto::tag::assign \
  240. , boost::proto::list2< \
  241. proto_derived_expr ThisConst() & \
  242. , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
  243. > \
  244. >::type \
  245. ) \
  246. >::type const \
  247. operator =(A ThatConst() &a) ThisConst() \
  248. { \
  249. typedef \
  250. typename boost::proto::base_expr< \
  251. proto_domain \
  252. , boost::proto::tag::assign \
  253. , boost::proto::list2< \
  254. proto_derived_expr ThisConst() & \
  255. , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
  256. > \
  257. >::type \
  258. that_type; \
  259. that_type const that = { \
  260. *static_cast<proto_derived_expr ThisConst() *>(this) \
  261. , boost::proto::as_child<proto_domain>(a) \
  262. }; \
  263. return proto_generator()(that); \
  264. } \
  265. /**/
  266. #define BOOST_PROTO_EXTENDS_ASSIGN_CONST_() \
  267. BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PROTO_CONST, BOOST_PP_EMPTY) \
  268. BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PROTO_CONST, BOOST_PROTO_CONST) \
  269. /**/
  270. #define BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_() \
  271. BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PP_EMPTY, BOOST_PP_EMPTY) \
  272. BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PP_EMPTY, BOOST_PROTO_CONST) \
  273. /**/
  274. #define BOOST_PROTO_EXTENDS_ASSIGN_() \
  275. BOOST_PROTO_EXTENDS_ASSIGN_CONST_() \
  276. BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_() \
  277. /**/
  278. #define BOOST_PROTO_EXTENDS_ASSIGN_CONST() \
  279. BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME) \
  280. BOOST_PROTO_EXTENDS_ASSIGN_CONST_() \
  281. /**/
  282. #define BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST() \
  283. BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME) \
  284. BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_() \
  285. /**/
  286. #define BOOST_PROTO_EXTENDS_ASSIGN() \
  287. BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME) \
  288. BOOST_PROTO_EXTENDS_ASSIGN_() \
  289. /**/
  290. /// INTERNAL ONLY
  291. ///
  292. #define BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(ThisConst, ThatConst) \
  293. template<typename A> \
  294. typename BOOST_PROTO_RESULT_OF< \
  295. proto_generator( \
  296. typename boost::proto::base_expr< \
  297. proto_domain \
  298. , boost::proto::tag::subscript \
  299. , boost::proto::list2< \
  300. proto_derived_expr ThisConst() & \
  301. , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
  302. > \
  303. >::type \
  304. ) \
  305. >::type const \
  306. operator [](A ThatConst() &a) ThisConst() \
  307. { \
  308. typedef \
  309. typename boost::proto::base_expr< \
  310. proto_domain \
  311. , boost::proto::tag::subscript \
  312. , boost::proto::list2< \
  313. proto_derived_expr ThisConst() & \
  314. , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
  315. > \
  316. >::type \
  317. that_type; \
  318. that_type const that = { \
  319. *static_cast<proto_derived_expr ThisConst() *>(this) \
  320. , boost::proto::as_child<proto_domain>(a) \
  321. }; \
  322. return proto_generator()(that); \
  323. } \
  324. /**/
  325. #define BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST() \
  326. BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PROTO_CONST, BOOST_PP_EMPTY) \
  327. BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PROTO_CONST, BOOST_PROTO_CONST) \
  328. /**/
  329. #define BOOST_PROTO_EXTENDS_SUBSCRIPT_NON_CONST() \
  330. BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PP_EMPTY, BOOST_PP_EMPTY) \
  331. BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PP_EMPTY, BOOST_PROTO_CONST) \
  332. /**/
  333. #define BOOST_PROTO_EXTENDS_SUBSCRIPT() \
  334. BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST() \
  335. BOOST_PROTO_EXTENDS_SUBSCRIPT_NON_CONST() \
  336. /**/
  337. /// INTERNAL ONLY
  338. ///
  339. #define BOOST_PROTO_EXTENDS_FUNCTION_() \
  340. template<typename Sig> \
  341. struct result \
  342. { \
  343. typedef \
  344. typename BOOST_PROTO_RESULT_OF< \
  345. proto_generator( \
  346. typename boost::proto::result_of::funop< \
  347. Sig \
  348. , proto_derived_expr \
  349. , proto_domain \
  350. >::type \
  351. ) \
  352. >::type const \
  353. type; \
  354. }; \
  355. /**/
  356. #ifndef BOOST_NO_VARIADIC_TEMPLATES
  357. #define BOOST_PROTO_EXTENDS_FUNCTION_CONST() \
  358. BOOST_PROTO_EXTENDS_FUNCTION_() \
  359. BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PROTO_CONST) \
  360. /**/
  361. #define BOOST_PROTO_EXTENDS_FUNCTION_NON_CONST() \
  362. BOOST_PROTO_EXTENDS_FUNCTION_() \
  363. BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PP_EMPTY) \
  364. /**/
  365. #define BOOST_PROTO_EXTENDS_FUNCTION() \
  366. BOOST_PROTO_EXTENDS_FUNCTION_() \
  367. BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PP_EMPTY) \
  368. BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PROTO_CONST) \
  369. /**/
  370. #else
  371. #define BOOST_PROTO_EXTENDS_FUNCTION_CONST() \
  372. BOOST_PROTO_EXTENDS_FUNCTION_() \
  373. BOOST_PP_REPEAT_FROM_TO( \
  374. 0 \
  375. , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY \
  376. , BOOST_PROTO_DEFINE_FUN_OP_CONST \
  377. , ~ \
  378. ) \
  379. /**/
  380. #define BOOST_PROTO_EXTENDS_FUNCTION_NON_CONST() \
  381. BOOST_PROTO_EXTENDS_FUNCTION_() \
  382. BOOST_PP_REPEAT_FROM_TO( \
  383. 0 \
  384. , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY \
  385. , BOOST_PROTO_DEFINE_FUN_OP_NON_CONST \
  386. , ~ \
  387. ) \
  388. /**/
  389. #define BOOST_PROTO_EXTENDS_FUNCTION() \
  390. BOOST_PROTO_EXTENDS_FUNCTION_() \
  391. BOOST_PP_REPEAT_FROM_TO( \
  392. 0 \
  393. , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY \
  394. , BOOST_PROTO_DEFINE_FUN_OP \
  395. , ~ \
  396. ) \
  397. /**/
  398. #endif
  399. #define BOOST_PROTO_EXTENDS(Expr, Derived, Domain) \
  400. BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, Domain) \
  401. BOOST_PROTO_EXTENDS_ASSIGN() \
  402. BOOST_PROTO_EXTENDS_SUBSCRIPT() \
  403. BOOST_PROTO_EXTENDS_FUNCTION() \
  404. /**/
  405. #define BOOST_PROTO_EXTENDS_USING_ASSIGN(Derived) \
  406. typedef typename Derived::proto_extends proto_extends; \
  407. using proto_extends::operator =; \
  408. BOOST_PROTO_EXTENDS_COPY_ASSIGN_(Derived, BOOST_PROTO_TYPENAME) \
  409. /**/
  410. #define BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT(Derived) \
  411. typedef Derived::proto_extends proto_extends; \
  412. using proto_extends::operator =; \
  413. BOOST_PROTO_EXTENDS_COPY_ASSIGN_(Derived, BOOST_PP_EMPTY) \
  414. /**/
  415. namespace exprns_
  416. {
  417. /// \brief Empty type to be used as a dummy template parameter of
  418. /// POD expression wrappers. It allows argument-dependent lookup
  419. /// to find Proto's operator overloads.
  420. ///
  421. /// \c proto::is_proto_expr allows argument-dependent lookup
  422. /// to find Proto's operator overloads. For example:
  423. ///
  424. /// \code
  425. /// template<typename T, typename Dummy = proto::is_proto_expr>
  426. /// struct my_terminal
  427. /// {
  428. /// BOOST_PROTO_BASIC_EXTENDS(
  429. /// typename proto::terminal<T>::type
  430. /// , my_terminal<T>
  431. /// , default_domain
  432. /// )
  433. /// };
  434. ///
  435. /// // ...
  436. /// my_terminal<int> _1, _2;
  437. /// _1 + _2; // OK, uses proto::operator+
  438. /// \endcode
  439. ///
  440. /// Without the second \c Dummy template parameter, Proto's operator
  441. /// overloads would not be considered by name lookup.
  442. struct is_proto_expr
  443. {};
  444. /// \brief extends\<\> class template for adding behaviors to a Proto expression template
  445. ///
  446. template<
  447. typename Expr
  448. , typename Derived
  449. , typename Domain // = proto::default_domain
  450. , long Arity // = Expr::proto_arity_c
  451. >
  452. struct extends
  453. {
  454. extends()
  455. : proto_expr_()
  456. {}
  457. extends(extends const &that)
  458. : proto_expr_(that.proto_expr_)
  459. {}
  460. extends(Expr const &expr_)
  461. : proto_expr_(expr_)
  462. {}
  463. typedef extends proto_extends;
  464. BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain)
  465. typedef typename Domain::proto_generator proto_generator;
  466. BOOST_PROTO_EXTENDS_ASSIGN_CONST_()
  467. BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST()
  468. // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
  469. // nested preprocessor loops, use file iteration here to generate
  470. // the operator() overloads, which is more efficient.
  471. #include <boost/proto/detail/extends_funop_const.hpp>
  472. };
  473. /// \brief extends\<\> class template for adding behaviors to a Proto expression template
  474. ///
  475. template<typename Expr, typename Derived, typename Domain>
  476. struct extends<Expr, Derived, Domain, 0>
  477. {
  478. extends()
  479. : proto_expr_()
  480. {}
  481. extends(extends const &that)
  482. : proto_expr_(that.proto_expr_)
  483. {}
  484. extends(Expr const &expr_)
  485. : proto_expr_(expr_)
  486. {}
  487. typedef extends proto_extends;
  488. BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain)
  489. typedef typename Domain::proto_generator proto_generator;
  490. BOOST_PROTO_EXTENDS_ASSIGN_()
  491. BOOST_PROTO_EXTENDS_SUBSCRIPT()
  492. // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
  493. // nested preprocessor loops, use file iteration here to generate
  494. // the operator() overloads, which is more efficient.
  495. #include <boost/proto/detail/extends_funop.hpp>
  496. };
  497. /// INTERNAL ONLY
  498. ///
  499. template<typename This, typename Fun, typename Domain>
  500. struct virtual_member
  501. {
  502. typedef Domain proto_domain;
  503. typedef typename Domain::proto_generator proto_generator;
  504. typedef virtual_member<This, Fun, Domain> proto_derived_expr;
  505. typedef tag::member proto_tag;
  506. typedef list2<This &, expr<tag::terminal, term<Fun> > const &> proto_args;
  507. typedef mpl::long_<2> proto_arity;
  508. typedef detail::not_a_valid_type proto_address_of_hack_type_;
  509. typedef void proto_is_expr_; /**< INTERNAL ONLY */
  510. static const long proto_arity_c = 2;
  511. typedef boost::proto::tag::proto_expr fusion_tag;
  512. typedef This &proto_child0;
  513. typedef expr<tag::terminal, term<Fun> > const &proto_child1;
  514. typedef expr<proto_tag, proto_args, proto_arity_c> proto_base_expr;
  515. typedef basic_expr<proto_tag, proto_args, proto_arity_c> proto_grammar;
  516. typedef void proto_is_aggregate_; /**< INTERNAL ONLY */
  517. BOOST_PROTO_EXTENDS_ASSIGN_()
  518. BOOST_PROTO_EXTENDS_SUBSCRIPT()
  519. // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
  520. // nested preprocessor loops, use file iteration here to generate
  521. // the operator() overloads, which is more efficient.
  522. #define BOOST_PROTO_NO_WAVE_OUTPUT
  523. #include <boost/proto/detail/extends_funop.hpp>
  524. #undef BOOST_PROTO_NO_WAVE_OUTPUT
  525. proto_base_expr const proto_base() const
  526. {
  527. proto_base_expr that = {this->child0(), this->child1()};
  528. return that;
  529. }
  530. proto_child0 child0() const
  531. {
  532. using std::size_t;
  533. return *(This *)((char *)this - BOOST_PROTO_OFFSETOF(This, proto_member_union_start_));
  534. }
  535. proto_child1 child1() const
  536. {
  537. static expr<tag::terminal, term<Fun>, 0> const that = {Fun()};
  538. return that;
  539. }
  540. };
  541. /// INTERNAL ONLY
  542. ///
  543. #define BOOST_PROTO_EXTENDS_MEMBER_(R, DOMAIN, ELEM) \
  544. boost::proto::exprns_::virtual_member< \
  545. proto_derived_expr \
  546. , BOOST_PP_TUPLE_ELEM(2, 0, ELEM) \
  547. , DOMAIN \
  548. > BOOST_PP_TUPLE_ELEM(2, 1, ELEM); \
  549. /**/
  550. /// \brief For declaring virtual data members in an extension class.
  551. ///
  552. #define BOOST_PROTO_EXTENDS_MEMBERS_WITH_DOMAIN(SEQ, DOMAIN) \
  553. union \
  554. { \
  555. char proto_member_union_start_; \
  556. BOOST_PP_SEQ_FOR_EACH(BOOST_PROTO_EXTENDS_MEMBER_, DOMAIN, SEQ) \
  557. }; \
  558. /**/
  559. /// \brief For declaring virtual data members in an extension class.
  560. ///
  561. #define BOOST_PROTO_EXTENDS_MEMBERS(SEQ) \
  562. BOOST_PROTO_EXTENDS_MEMBERS_WITH_DOMAIN(SEQ, proto_domain) \
  563. /**/
  564. }
  565. }}
  566. #endif