extends.hpp 42 KB

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