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