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