9
3

extends.hpp 41 KB

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