1 // Copyright Daniel Wallin, David Abrahams 2005. 2 // Copyright Cromwell D. Enage 2017. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef BOOST_PARAMETER_AUX_ARG_LIST_HPP 8 #define BOOST_PARAMETER_AUX_ARG_LIST_HPP 9 10 namespace boost { namespace parameter { namespace aux { 11 12 // 13 // Structures used to build the tuple of actual arguments. The tuple is a 14 // nested cons-style list of arg_list specializations terminated by an 15 // empty_arg_list. 16 // 17 // Each specialization of arg_list is derived from its successor in the 18 // list type. This feature is used along with using declarations to build 19 // member function overload sets that can match against keywords. 20 // 21 22 // MPL sequence support 23 struct arg_list_tag; 24 25 template <typename T> 26 struct get_reference 27 { 28 typedef typename T::reference type; 29 }; 30 }}} // namespace boost::parameter::aux 31 32 #include <boost/parameter/config.hpp> 33 34 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) 35 36 namespace boost { namespace parameter { namespace aux { 37 38 struct value_type_is_void 39 { 40 }; 41 42 struct value_type_is_not_void 43 { 44 }; 45 }}} // namespace boost::parameter::aux 46 47 #endif 48 49 #include <boost/parameter/aux_/void.hpp> 50 #include <boost/parameter/aux_/yesno.hpp> 51 #include <boost/parameter/aux_/result_of0.hpp> 52 #include <boost/parameter/aux_/default.hpp> 53 54 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) 55 #include <utility> 56 57 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 58 #include <boost/mp11/integral.hpp> 59 #include <boost/mp11/list.hpp> 60 #include <boost/mp11/utility.hpp> 61 #include <type_traits> 62 #endif 63 64 namespace boost { namespace parameter { namespace aux { 65 66 // Terminates arg_list<> and represents an empty list. Since this is just 67 // the terminating case, you might want to look at arg_list first to get a 68 // feel for what's really happening here. 69 struct empty_arg_list 70 { 71 struct tagged_arg 72 { 73 typedef ::boost::parameter::void_ value_type; 74 }; 75 76 // Variadic constructor also serves as default constructor. 77 template <typename ...Args> empty_arg_listboost::parameter::aux::empty_arg_list78 inline BOOST_CONSTEXPR empty_arg_list(Args&&...) 79 { 80 } 81 82 // A metafunction class that, given a keyword and a default type, 83 // returns the appropriate result type for a keyword lookup given 84 // that default. 85 struct binding 86 { 87 template <typename KW, typename Default, typename Reference> 88 struct apply 89 { 90 typedef Default type; 91 }; 92 93 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 94 template <typename KW, typename Default, typename Reference> 95 using fn = Default; 96 #endif 97 }; 98 99 // Terminator for has_key, indicating that the keyword is unique. 100 template <typename KW> 101 static ::boost::parameter::aux::no_tag has_key(KW*); 102 103 // If either of these operators are called, it means there is no 104 // argument in the list that matches the supplied keyword. Just 105 // return the default value. 106 template <typename K, typename Default> 107 inline BOOST_CONSTEXPR Default& operator []boost::parameter::aux::empty_arg_list108 operator[](::boost::parameter::aux::default_<K,Default> x) const 109 { 110 return x.value; 111 } 112 113 template <typename K, typename Default> 114 inline BOOST_CONSTEXPR Default&& operator []boost::parameter::aux::empty_arg_list115 operator[](::boost::parameter::aux::default_r_<K,Default> x) const 116 { 117 return ::std::forward<Default>(x.value); 118 } 119 120 // If this operator is called, it means there is no argument in the 121 // list that matches the supplied keyword. Just evaluate and return 122 // the default value. 123 template <typename K, typename F> 124 inline BOOST_CONSTEXPR 125 typename ::boost::parameter::aux::result_of0<F>::type operator []boost::parameter::aux::empty_arg_list126 operator[](BOOST_PARAMETER_lazy_default_fallback<K,F> x) const 127 { 128 return x.compute_default(); 129 } 130 131 // No argument corresponding to ParameterRequirements::key_type 132 // was found if we match this overload, so unless that parameter 133 // has a default, we indicate that the actual arguments don't 134 // match the function's requirements. 135 template <typename ParameterRequirements, typename ArgPack> 136 static typename ParameterRequirements::has_default 137 satisfies(ParameterRequirements*, ArgPack*); 138 139 // MPL sequence support 140 typedef ::boost::parameter::aux::empty_arg_list type; // convenience 141 // For dispatching to sequence intrinsics 142 typedef ::boost::parameter::aux::arg_list_tag tag; 143 }; 144 }}} // namespace boost::parameter::aux 145 146 #include <boost/parameter/aux_/preprocessor/nullptr.hpp> 147 #include <boost/parameter/aux_/yesno.hpp> 148 #include <boost/parameter/aux_/is_maybe.hpp> 149 #include <boost/parameter/aux_/tagged_argument_fwd.hpp> 150 #include <boost/parameter/aux_/parameter_requirements.hpp> 151 #include <boost/parameter/aux_/augment_predicate.hpp> 152 #include <boost/parameter/keyword_fwd.hpp> 153 #include <boost/mpl/bool.hpp> 154 #include <boost/mpl/if.hpp> 155 #include <boost/mpl/eval_if.hpp> 156 #include <boost/mpl/apply_wrap.hpp> 157 #include <boost/mpl/assert.hpp> 158 #include <boost/type_traits/is_same.hpp> 159 #include <boost/core/enable_if.hpp> 160 161 namespace boost { namespace parameter { namespace aux { 162 163 // A tuple of tagged arguments, terminated with empty_arg_list. Every 164 // TaggedArg is an instance of tagged_argument<> or 165 // tagged_argument_rref<>. 166 template < 167 typename TaggedArg 168 , typename Next = ::boost::parameter::aux::empty_arg_list 169 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 170 , typename EmitsErrors = ::boost::mp11::mp_true 171 #else 172 , typename EmitsErrors = ::boost::mpl::true_ 173 #endif 174 > 175 class arg_list : public Next 176 { 177 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 178 using _holds_maybe = typename ::boost::parameter::aux 179 ::is_maybe<typename TaggedArg::value_type>::type; 180 #else 181 typedef typename ::boost::parameter::aux 182 ::is_maybe<typename TaggedArg::value_type>::type _holds_maybe; 183 #endif 184 185 TaggedArg arg; // Stores the argument 186 187 public: 188 typedef TaggedArg tagged_arg; 189 typedef ::boost::parameter::aux::arg_list<TaggedArg,Next> self; 190 typedef typename TaggedArg::key_type key_type; 191 192 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 193 using reference = typename ::boost::mp11::mp_if< 194 _holds_maybe 195 , ::boost::parameter::aux 196 ::get_reference<typename TaggedArg::value_type> 197 , ::boost::parameter::aux::get_reference<TaggedArg> 198 >::type; 199 200 using value_type = ::boost::mp11 201 ::mp_if<_holds_maybe,reference,typename TaggedArg::value_type>; 202 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) 203 typedef typename ::boost::mpl::eval_if< 204 _holds_maybe 205 , ::boost::parameter::aux 206 ::get_reference<typename TaggedArg::value_type> 207 , ::boost::parameter::aux::get_reference<TaggedArg> 208 >::type reference; 209 210 typedef typename ::boost::mpl::if_< 211 _holds_maybe 212 , reference 213 , typename TaggedArg::value_type 214 >::type value_type; 215 #endif // BOOST_PARAMETER_CAN_USE_MP11 216 217 // Create a new list by prepending arg to a copy of tail. Used when 218 // incrementally building this structure with the comma operator. arg_list(TaggedArg const & head,Next const & tail)219 inline BOOST_CONSTEXPR arg_list( 220 TaggedArg const& head 221 , Next const& tail 222 ) : Next(tail), arg(head) 223 { 224 } 225 226 // Store the arguments in successive nodes of this list. 227 // Use tag dispatching to determine whether to forward all arguments 228 // to the Next constructor, or store the first argument and forward 229 // the rest. -- Cromwell D. Enage 230 template <typename A0> arg_list(::boost::parameter::aux::value_type_is_not_void,A0 && a0)231 inline BOOST_CONSTEXPR arg_list( 232 ::boost::parameter::aux::value_type_is_not_void 233 , A0&& a0 234 ) : Next( 235 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 236 ::boost::mp11::mp_if< 237 ::std::is_same< 238 #else 239 typename ::boost::mpl::if_< 240 ::boost::is_same< 241 #endif 242 typename Next::tagged_arg::value_type 243 , ::boost::parameter::void_ 244 > 245 , ::boost::parameter::aux::value_type_is_void 246 , ::boost::parameter::aux::value_type_is_not_void 247 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 248 >() 249 #else 250 >::type() 251 #endif 252 ) 253 , arg(::std::forward<A0>(a0)) 254 { 255 } 256 257 template <typename ...Args> arg_list(::boost::parameter::aux::value_type_is_void,Args &&...args)258 inline BOOST_CONSTEXPR arg_list( 259 ::boost::parameter::aux::value_type_is_void 260 , Args&&... args 261 ) : Next( 262 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 263 ::boost::mp11::mp_if< 264 ::std::is_same< 265 #else 266 typename ::boost::mpl::if_< 267 ::boost::is_same< 268 #endif 269 typename Next::tagged_arg::value_type 270 , ::boost::parameter::void_ 271 > 272 , ::boost::parameter::aux::value_type_is_void 273 , ::boost::parameter::aux::value_type_is_not_void 274 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 275 >() 276 #else 277 >::type() 278 #endif 279 , ::std::forward<Args>(args)... 280 ) 281 , arg(::boost::parameter::aux::void_reference()) 282 { 283 } 284 285 template <typename A0, typename A1, typename ...Args> arg_list(::boost::parameter::aux::value_type_is_not_void,A0 && a0,A1 && a1,Args &&...args)286 inline BOOST_CONSTEXPR arg_list( 287 ::boost::parameter::aux::value_type_is_not_void 288 , A0&& a0 289 , A1&& a1 290 , Args&&... args 291 ) : Next( 292 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 293 ::boost::mp11::mp_if< 294 ::std::is_same< 295 #else 296 typename ::boost::mpl::if_< 297 ::boost::is_same< 298 #endif 299 typename Next::tagged_arg::value_type 300 , ::boost::parameter::void_ 301 > 302 , ::boost::parameter::aux::value_type_is_void 303 , ::boost::parameter::aux::value_type_is_not_void 304 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 305 >() 306 #else 307 >::type() 308 #endif 309 , ::std::forward<A1>(a1) 310 , ::std::forward<Args>(args)... 311 ) 312 , arg(::std::forward<A0>(a0)) 313 { 314 } 315 316 // A metafunction class that, given a keyword and a default type, 317 // returns the appropriate result type for a keyword lookup given 318 // that default. 319 struct binding 320 { 321 typedef typename Next::binding next_binding; 322 323 template <typename KW, typename Default, typename Reference> 324 struct apply 325 { 326 typedef typename ::boost::mpl::eval_if< 327 ::boost::is_same<KW,key_type> 328 , ::boost::mpl::if_<Reference,reference,value_type> 329 , ::boost::mpl 330 ::apply_wrap3<next_binding,KW,Default,Reference> 331 >::type type; 332 }; 333 334 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 335 template <typename KW, typename Default, typename Reference> 336 using fn = ::boost::mp11::mp_if< 337 ::std::is_same<KW,key_type> 338 , ::boost::mp11::mp_if<Reference,reference,value_type> 339 , ::boost::mp11::mp_apply_q< 340 next_binding 341 , ::boost::mp11::mp_list<KW,Default,Reference> 342 > 343 >; 344 #endif 345 }; 346 347 // Overload for key_type, so the assert below will fire 348 // if the same keyword is used again. 349 static ::boost::parameter::aux::yes_tag has_key(key_type*); 350 using Next::has_key; 351 352 private: 353 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 354 using _has_unique_key = ::boost::mp11::mp_bool< 355 #else 356 typedef ::boost::mpl::bool_< 357 #endif 358 sizeof( 359 Next::has_key( 360 static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR) 361 ) 362 ) == sizeof(::boost::parameter::aux::no_tag) 363 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 364 >; 365 #else 366 > _has_unique_key; 367 #endif 368 369 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 370 static_assert( 371 !(EmitsErrors::value) || (_has_unique_key::value) 372 , "duplicate keyword" 373 ); 374 #else 375 BOOST_MPL_ASSERT_MSG( 376 !(EmitsErrors::value) || (_has_unique_key::value) 377 , duplicate_keyword 378 , (key_type) 379 ); 380 #endif 381 382 // 383 // Begin implementation of indexing operators 384 // for looking up specific arguments by name. 385 // 386 387 // Helpers that handle the case when TaggedArg is empty<T>. 388 template <typename D> 389 inline BOOST_CONSTEXPR reference 390 #if defined(BOOST_PARAMETER_CAN_USE_MP11) get_default(D const &,::boost::mp11::mp_false) const391 get_default(D const&, ::boost::mp11::mp_false) const 392 #else 393 get_default(D const&, ::boost::mpl::false_) const 394 #endif 395 { 396 return this->arg.get_value(); 397 } 398 399 template <typename D> 400 inline BOOST_CONSTEXPR reference 401 #if defined(BOOST_PARAMETER_CAN_USE_MP11) get_default(D const & d,::boost::mp11::mp_true) const402 get_default(D const& d, ::boost::mp11::mp_true) const 403 #else 404 get_default(D const& d, ::boost::mpl::true_) const 405 #endif 406 { 407 return ( 408 this->arg.get_value() 409 ? this->arg.get_value().get() 410 : this->arg.get_value().construct(d.value) 411 ); 412 } 413 414 public: 415 inline BOOST_CONSTEXPR reference operator [](::boost::parameter::keyword<key_type> const &) const416 operator[](::boost::parameter::keyword<key_type> const&) const 417 { 418 #if !defined(BOOST_NO_CXX14_CONSTEXPR) 419 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 420 static_assert(!_holds_maybe::value, "must not hold maybe"); 421 #elif !( \ 422 BOOST_WORKAROUND(BOOST_GCC, >= 40700) && \ 423 BOOST_WORKAROUND(BOOST_GCC, < 40900) \ 424 ) && !BOOST_WORKAROUND(BOOST_GCC, >= 50000) && \ 425 !BOOST_WORKAROUND(BOOST_MSVC, < 1910) 426 BOOST_MPL_ASSERT_NOT((_holds_maybe)); 427 #endif 428 #endif 429 return this->arg.get_value(); 430 } 431 432 template <typename Default> 433 inline BOOST_CONSTEXPR reference operator [](::boost::parameter::aux::default_<key_type,Default> const & d) const434 operator[]( 435 ::boost::parameter::aux::default_<key_type,Default> const& d 436 ) const 437 { 438 return this->get_default(d, _holds_maybe()); 439 } 440 441 template <typename Default> 442 inline BOOST_CONSTEXPR reference operator [](::boost::parameter::aux::default_r_<key_type,Default> const & d) const443 operator[]( 444 ::boost::parameter::aux::default_r_<key_type,Default> const& d 445 ) const 446 { 447 return this->get_default(d, _holds_maybe()); 448 } 449 450 template <typename Default> 451 inline BOOST_CONSTEXPR reference operator [](BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const &) const452 operator[]( 453 BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const& 454 ) const 455 { 456 #if !defined(BOOST_NO_CXX14_CONSTEXPR) 457 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 458 static_assert(!_holds_maybe::value, "must not hold maybe"); 459 #elif !( \ 460 BOOST_WORKAROUND(BOOST_GCC, >= 40700) && \ 461 BOOST_WORKAROUND(BOOST_GCC, < 40900) \ 462 ) && !BOOST_WORKAROUND(BOOST_GCC, >= 50000) && \ 463 !BOOST_WORKAROUND(BOOST_MSVC, < 1910) 464 BOOST_MPL_ASSERT_NOT((_holds_maybe)); 465 #endif 466 #endif 467 return this->arg.get_value(); 468 } 469 470 // Builds an overload set including operator[]s defined 471 // in base classes. 472 using Next::operator[]; 473 474 // 475 // End of indexing support 476 // 477 478 // For parameter_requirements matching this node's key_type, return 479 // a bool constant wrapper indicating whether the requirements are 480 // satisfied by TaggedArg. Used only for compile-time computation 481 // and never really called, so a declaration is enough. 482 template <typename HasDefault, typename Predicate, typename ArgPack> 483 static typename ::boost::lazy_enable_if< 484 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 485 ::boost::mp11::mp_if< 486 EmitsErrors 487 , ::boost::mp11::mp_true 488 , _has_unique_key 489 > 490 , ::boost::parameter::aux::augment_predicate_mp11< 491 #else 492 typename ::boost::mpl::if_< 493 EmitsErrors 494 , ::boost::mpl::true_ 495 , _has_unique_key 496 >::type 497 , ::boost::parameter::aux::augment_predicate< 498 #endif 499 Predicate 500 , reference 501 , key_type 502 , value_type 503 , ArgPack 504 > 505 >::type 506 satisfies( 507 ::boost::parameter::aux::parameter_requirements< 508 key_type 509 , Predicate 510 , HasDefault 511 >* 512 , ArgPack* 513 ); 514 515 // Builds an overload set including satisfies functions defined 516 // in base classes. 517 using Next::satisfies; 518 519 // Comma operator to compose argument list without using parameters<>. 520 // Useful for argument lists with undetermined length. 521 template <typename KW, typename T2> 522 inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list< 523 ::boost::parameter::aux::tagged_argument<KW,T2> 524 , self 525 > operator ,(::boost::parameter::aux::tagged_argument<KW,T2> const & x) const526 operator,( 527 ::boost::parameter::aux::tagged_argument<KW,T2> const& x 528 ) const 529 { 530 return ::boost::parameter::aux::arg_list< 531 ::boost::parameter::aux::tagged_argument<KW,T2> 532 , self 533 >(x, *this); 534 } 535 536 template <typename KW, typename T2> 537 inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list< 538 ::boost::parameter::aux::tagged_argument_rref<KW,T2> 539 , self 540 > operator ,(::boost::parameter::aux::tagged_argument_rref<KW,T2> const & x) const541 operator,( 542 ::boost::parameter::aux::tagged_argument_rref<KW,T2> const& x 543 ) const 544 { 545 return ::boost::parameter::aux::arg_list< 546 ::boost::parameter::aux::tagged_argument_rref<KW,T2> 547 , self 548 >(x, *this); 549 } 550 551 // MPL sequence support 552 typedef self type; // Convenience for users 553 typedef Next tail_type; // For the benefit of iterators 554 // For dispatching to sequence intrinsics 555 typedef ::boost::parameter::aux::arg_list_tag tag; 556 }; 557 }}} // namespace boost::parameter::aux 558 559 #else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) 560 561 #include <boost/preprocessor/repetition/enum_params.hpp> 562 #include <boost/preprocessor/facilities/intercept.hpp> 563 564 namespace boost { namespace parameter { namespace aux { 565 566 // Terminates arg_list<> and represents an empty list. Since this is just 567 // the terminating case, you might want to look at arg_list first to get a 568 // feel for what's really happening here. 569 struct empty_arg_list 570 { empty_arg_listboost::parameter::aux::empty_arg_list571 inline BOOST_CONSTEXPR empty_arg_list() 572 { 573 } 574 575 // Constructor taking BOOST_PARAMETER_COMPOSE_MAX_ARITY empty_arg_list 576 // arguments; this makes initialization. empty_arg_listboost::parameter::aux::empty_arg_list577 inline BOOST_CONSTEXPR empty_arg_list( 578 BOOST_PP_ENUM_PARAMS( 579 BOOST_PARAMETER_COMPOSE_MAX_ARITY 580 , ::boost::parameter::void_ BOOST_PP_INTERCEPT 581 ) 582 ) 583 { 584 } 585 586 // A metafunction class that, given a keyword and a default type, 587 // returns the appropriate result type for a keyword lookup given 588 // that default. 589 struct binding 590 { 591 template <typename KW, typename Default, typename Reference> 592 struct apply 593 { 594 typedef Default type; 595 }; 596 }; 597 598 // Terminator for has_key, indicating that the keyword is unique. 599 template <typename KW> 600 static ::boost::parameter::aux::no_tag has_key(KW*); 601 602 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 603 // The overload set technique doesn't work with these older compilers, 604 // so they need some explicit handholding. 605 606 // A metafunction class that, given a keyword, returns the type of the 607 // base sublist whose get() function can produce the value for that key. 608 struct key_owner 609 { 610 template <typename KW> 611 struct apply 612 { 613 typedef ::boost::parameter::aux::empty_arg_list type; 614 }; 615 }; 616 #endif // Borland workarounds needed 617 618 // If either of these operators are called, it means there is no 619 // argument in the list that matches the supplied keyword. Just 620 // return the default value. 621 template <typename K, typename Default> 622 inline BOOST_CONSTEXPR Default& operator []boost::parameter::aux::empty_arg_list623 operator[](::boost::parameter::aux::default_<K,Default> x) const 624 { 625 return x.value; 626 } 627 628 // If this operator is called, it means there is no argument in the 629 // list that matches the supplied keyword. Just evaluate and return 630 // the default value. 631 template <typename K, typename F> 632 inline BOOST_CONSTEXPR 633 typename ::boost::parameter::aux::result_of0<F>::type operator []boost::parameter::aux::empty_arg_list634 operator[](BOOST_PARAMETER_lazy_default_fallback<K,F> x) const 635 { 636 return x.compute_default(); 637 } 638 639 // No argument corresponding to ParameterRequirements::key_type 640 // was found if we match this overload, so unless that parameter 641 // has a default, we indicate that the actual arguments don't 642 // match the function's requirements. 643 template <typename ParameterRequirements, typename ArgPack> 644 static typename ParameterRequirements::has_default 645 satisfies(ParameterRequirements*, ArgPack*); 646 647 // MPL sequence support 648 typedef ::boost::parameter::aux::empty_arg_list type; // convenience 649 // For dispatching to sequence intrinsics 650 typedef ::boost::parameter::aux::arg_list_tag tag; 651 }; 652 }}} // namespace boost::parameter::aux 653 654 #include <boost/parameter/aux_/yesno.hpp> 655 #include <boost/parameter/aux_/is_maybe.hpp> 656 #include <boost/parameter/aux_/tagged_argument_fwd.hpp> 657 #include <boost/parameter/aux_/parameter_requirements.hpp> 658 #include <boost/parameter/aux_/augment_predicate.hpp> 659 #include <boost/parameter/keyword_fwd.hpp> 660 #include <boost/mpl/bool.hpp> 661 #include <boost/mpl/if.hpp> 662 #include <boost/mpl/eval_if.hpp> 663 #include <boost/mpl/apply_wrap.hpp> 664 #include <boost/mpl/assert.hpp> 665 #include <boost/type_traits/is_same.hpp> 666 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 667 #include <boost/preprocessor/repetition/enum_shifted_params.hpp> 668 669 #if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) 670 #include <boost/core/enable_if.hpp> 671 #endif 672 673 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 674 #include <boost/parameter/aux_/preprocessor/nullptr.hpp> 675 #endif 676 677 namespace boost { namespace parameter { namespace aux { 678 679 // A tuple of tagged arguments, terminated with empty_arg_list. Every 680 // TaggedArg is an instance of tagged_argument<>. 681 template < 682 typename TaggedArg 683 , typename Next = ::boost::parameter::aux::empty_arg_list 684 , typename EmitsErrors = ::boost::mpl::true_ 685 > 686 class arg_list : public Next 687 { 688 typedef typename ::boost::parameter::aux 689 ::is_maybe<typename TaggedArg::value_type>::type _holds_maybe; 690 691 TaggedArg arg; // Stores the argument 692 693 public: 694 typedef TaggedArg tagged_arg; 695 typedef ::boost::parameter::aux::arg_list<TaggedArg,Next> self; 696 typedef typename TaggedArg::key_type key_type; 697 698 typedef typename ::boost::mpl::eval_if< 699 _holds_maybe 700 , ::boost::parameter::aux 701 ::get_reference<typename TaggedArg::value_type> 702 , ::boost::parameter::aux::get_reference<TaggedArg> 703 >::type reference; 704 705 typedef typename ::boost::mpl::if_< 706 _holds_maybe 707 , reference 708 , typename TaggedArg::value_type 709 >::type value_type; 710 711 // Create a new list by prepending arg to a copy of tail. Used when 712 // incrementally building this structure with the comma operator. arg_list(TaggedArg const & head,Next const & tail)713 inline BOOST_CONSTEXPR arg_list( 714 TaggedArg const& head 715 , Next const& tail 716 ) : Next(tail), arg(head) 717 { 718 } 719 720 // Store the arguments in successive nodes of this list. 721 template < 722 // typename A0, typename A1, ... 723 BOOST_PP_ENUM_PARAMS( 724 BOOST_PARAMETER_COMPOSE_MAX_ARITY 725 , typename A 726 ) 727 > arg_list(BOOST_PP_ENUM_BINARY_PARAMS (BOOST_PARAMETER_COMPOSE_MAX_ARITY,A,& a))728 inline BOOST_CONSTEXPR arg_list( 729 // A0& a0, A1& a1, ... 730 BOOST_PP_ENUM_BINARY_PARAMS( 731 BOOST_PARAMETER_COMPOSE_MAX_ARITY 732 , A 733 , & a 734 ) 735 ) : Next( 736 // a1, a2, ... 737 BOOST_PP_ENUM_SHIFTED_PARAMS( 738 BOOST_PARAMETER_COMPOSE_MAX_ARITY 739 , a 740 ) 741 , ::boost::parameter::aux::void_reference() 742 ) 743 , arg(a0) 744 { 745 } 746 747 // A metafunction class that, given a keyword and a default type, 748 // returns the appropriate result type for a keyword lookup given 749 // that default. 750 struct binding 751 { 752 typedef typename Next::binding next_binding; 753 754 template <typename KW, typename Default, typename Reference> 755 struct apply 756 { 757 typedef typename ::boost::mpl::eval_if< 758 ::boost::is_same<KW,key_type> 759 , ::boost::mpl::if_<Reference,reference,value_type> 760 , ::boost::mpl::apply_wrap3< 761 next_binding 762 , KW 763 , Default 764 , Reference 765 > 766 >::type type; 767 }; 768 }; 769 770 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 771 // Overload for key_type, so the assert below will fire 772 // if the same keyword is used again. 773 static ::boost::parameter::aux::yes_tag has_key(key_type*); 774 using Next::has_key; 775 776 private: 777 #if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(BOOST_MSVC, < 1800) 778 BOOST_MPL_ASSERT_MSG( 779 sizeof( 780 Next::has_key( 781 static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR) 782 ) 783 ) == sizeof(::boost::parameter::aux::no_tag) 784 , duplicate_keyword 785 , (key_type) 786 ); 787 #else 788 typedef ::boost::mpl::bool_< 789 sizeof( 790 Next::has_key( 791 static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR) 792 ) 793 ) == sizeof(::boost::parameter::aux::no_tag) 794 > _has_unique_key; 795 796 BOOST_MPL_ASSERT_MSG( 797 !(EmitsErrors::value) || (_has_unique_key::value) 798 , duplicate_keyword 799 , (key_type) 800 ); 801 #endif // SFINAE/MSVC workarounds needed 802 #endif // Borland workarounds not needed 803 804 private: 805 // 806 // Begin implementation of indexing operators 807 // for looking up specific arguments by name. 808 // 809 810 // Helpers that handle the case when TaggedArg is empty<T>. 811 template <typename D> 812 inline BOOST_CONSTEXPR reference get_default(D const &,::boost::mpl::false_) const813 get_default(D const&, ::boost::mpl::false_) const 814 { 815 return this->arg.get_value(); 816 } 817 818 template <typename D> 819 inline BOOST_CONSTEXPR reference get_default(D const & d,::boost::mpl::true_) const820 get_default(D const& d, ::boost::mpl::true_) const 821 { 822 return ( 823 this->arg.get_value() 824 ? this->arg.get_value().get() 825 : this->arg.get_value().construct(d.value) 826 ); 827 } 828 829 public: 830 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 831 // These older compilers don't support the overload set creation 832 // idiom well, so we need to do all the return type calculation 833 // for the compiler and dispatch through an outer function template. 834 835 // A metafunction class that, given a keyword, returns the base 836 // sublist whose get() function can produce the value for that key. 837 struct key_owner 838 { 839 typedef typename Next::key_owner next_key_owner; 840 841 template <typename KW> 842 struct apply 843 { 844 typedef typename ::boost::mpl::eval_if< 845 ::boost::is_same<KW,key_type> 846 , ::boost::mpl::identity< 847 ::boost::parameter::aux::arg_list<TaggedArg,Next> 848 > 849 , ::boost::mpl::apply_wrap1<next_key_owner,KW> 850 >::type type; 851 }; 852 }; 853 854 // Outer indexing operators that dispatch to the right node's 855 // get() function. 856 template <typename KW> 857 inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3< 858 binding 859 , KW 860 , ::boost::parameter::void_ 861 , ::boost::mpl::true_ 862 >::type operator [](::boost::parameter::keyword<KW> const & x) const863 operator[](::boost::parameter::keyword<KW> const& x) const 864 { 865 typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const& 866 sublist = *this; 867 return sublist.get(x); 868 } 869 870 template <typename KW, typename Default> 871 inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3< 872 binding 873 , KW 874 , Default& 875 , ::boost::mpl::true_ 876 >::type operator [](::boost::parameter::aux::default_<KW,Default> const & x) const877 operator[]( 878 ::boost::parameter::aux::default_<KW,Default> const& x 879 ) const 880 { 881 typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const& 882 sublist = *this; 883 return sublist.get(x); 884 } 885 886 template <typename KW, typename F> 887 inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3< 888 binding 889 , KW 890 , typename ::boost::parameter::aux::result_of0<F>::type 891 , ::boost::mpl::true_ 892 >::type operator [](BOOST_PARAMETER_lazy_default_fallback<KW,F> const & x) const893 operator[]( 894 BOOST_PARAMETER_lazy_default_fallback<KW,F> const& x 895 ) const 896 { 897 typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const& 898 sublist = *this; 899 return sublist.get(x); 900 } 901 902 // These just return the stored value; when empty_arg_list is reached, 903 // indicating no matching argument was passed, the default is 904 // returned, or if no default_ or lazy_default was passed, compilation 905 // fails. 906 inline BOOST_CONSTEXPR reference get(::boost::parameter::keyword<key_type> const &) const907 get(::boost::parameter::keyword<key_type> const&) const 908 { 909 BOOST_MPL_ASSERT_NOT((_holds_maybe)); 910 return this->arg.get_value(); 911 } 912 913 template <typename Default> 914 inline BOOST_CONSTEXPR reference get(::boost::parameter::aux::default_<key_type,Default> const & d) const915 get( 916 ::boost::parameter::aux::default_<key_type,Default> const& d 917 ) const 918 { 919 return this->get_default(d, _holds_maybe()); 920 } 921 922 template <typename Default> 923 inline BOOST_CONSTEXPR reference get(BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const &) const924 get( 925 BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const& 926 ) const 927 { 928 return this->arg.get_value(); 929 } 930 #else // !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 931 inline BOOST_CONSTEXPR reference 932 operator[](::boost::parameter::keyword<key_type> const&) const 933 { 934 BOOST_MPL_ASSERT_NOT((_holds_maybe)); 935 return this->arg.get_value(); 936 } 937 938 template <typename Default> 939 inline BOOST_CONSTEXPR reference 940 operator[]( 941 ::boost::parameter::aux::default_<key_type,Default> const& d 942 ) const 943 { 944 return this->get_default(d, _holds_maybe()); 945 } 946 947 template <typename Default> 948 inline BOOST_CONSTEXPR reference 949 operator[]( 950 BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const& 951 ) const 952 { 953 BOOST_MPL_ASSERT_NOT((_holds_maybe)); 954 return this->arg.get_value(); 955 } 956 957 // Builds an overload set including operator[]s defined 958 // in base classes. 959 using Next::operator[]; 960 961 // 962 // End of indexing support 963 // 964 965 // For parameter_requirements matching this node's key_type, return 966 // a bool constant wrapper indicating whether the requirements are 967 // satisfied by TaggedArg. Used only for compile-time computation 968 // and never really called, so a declaration is enough. 969 template <typename HasDefault, typename Predicate, typename ArgPack> 970 static typename 971 #if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) 972 ::boost::lazy_enable_if< 973 typename ::boost::mpl::if_< 974 EmitsErrors 975 , ::boost::mpl::true_ 976 , _has_unique_key 977 >::type, 978 #endif 979 ::boost::parameter::aux::augment_predicate< 980 Predicate 981 , reference 982 , key_type 983 , value_type 984 , ArgPack 985 #if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) 986 > 987 #endif 988 >::type 989 satisfies( 990 ::boost::parameter::aux::parameter_requirements< 991 key_type 992 , Predicate 993 , HasDefault 994 >* 995 , ArgPack* 996 ); 997 998 // Builds an overload set including satisfies functions defined 999 // in base classes. 1000 using Next::satisfies; 1001 #endif // Borland workarounds needed 1002 1003 // Comma operator to compose argument list without using parameters<>. 1004 // Useful for argument lists with undetermined length. 1005 template <typename KW, typename T2> 1006 inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list< 1007 ::boost::parameter::aux::tagged_argument<KW,T2> 1008 , self 1009 > operator ,(::boost::parameter::aux::tagged_argument<KW,T2> const & x) const1010 operator,( 1011 ::boost::parameter::aux::tagged_argument<KW,T2> const& x 1012 ) const 1013 { 1014 return ::boost::parameter::aux::arg_list< 1015 ::boost::parameter::aux::tagged_argument<KW,T2> 1016 , self 1017 >(x, *this); 1018 } 1019 1020 // MPL sequence support 1021 typedef self type; // Convenience for users 1022 typedef Next tail_type; // For the benefit of iterators 1023 // For dispatching to sequence intrinsics 1024 typedef ::boost::parameter::aux::arg_list_tag tag; 1025 }; 1026 }}} // namespace boost::parameter::aux 1027 1028 #endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING 1029 1030 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 1031 1032 namespace boost { namespace parameter { namespace aux { 1033 1034 template <typename ...ArgTuples> 1035 struct arg_list_cons; 1036 1037 template <> 1038 struct arg_list_cons<> 1039 { 1040 using type = ::boost::parameter::aux::empty_arg_list; 1041 }; 1042 1043 template <typename ArgTuple0, typename ...Tuples> 1044 struct arg_list_cons<ArgTuple0,Tuples...> 1045 { 1046 using type = ::boost::parameter::aux::arg_list< 1047 typename ArgTuple0::tagged_arg 1048 , typename ::boost::parameter::aux::arg_list_cons<Tuples...>::type 1049 , typename ArgTuple0::emits_errors 1050 >; 1051 }; 1052 1053 template < 1054 typename Keyword 1055 , typename TaggedArg 1056 , typename EmitsErrors = ::boost::mp11::mp_true 1057 > 1058 struct flat_like_arg_tuple 1059 { 1060 using tagged_arg = TaggedArg; 1061 using emits_errors = EmitsErrors; 1062 }; 1063 1064 template <typename ...ArgTuples> 1065 class flat_like_arg_list 1066 : public ::boost::parameter::aux::arg_list_cons<ArgTuples...>::type 1067 { 1068 using _base_type = typename ::boost::parameter::aux 1069 ::arg_list_cons<ArgTuples...>::type; 1070 1071 public: flat_like_arg_list(typename _base_type::tagged_arg const & head,typename _base_type::tail_type const & tail)1072 inline BOOST_CONSTEXPR flat_like_arg_list( 1073 typename _base_type::tagged_arg const& head 1074 , typename _base_type::tail_type const& tail 1075 ) : _base_type(head, tail) 1076 { 1077 } 1078 1079 template <typename ...Args> flat_like_arg_list(Args &&...args)1080 inline BOOST_CONSTEXPR flat_like_arg_list(Args&&... args) 1081 : _base_type(::std::forward<Args>(args)...) 1082 { 1083 } 1084 1085 using _base_type::operator[]; 1086 using _base_type::satisfies; 1087 1088 // Comma operator to compose argument list without using parameters<>. 1089 // Useful for argument lists with undetermined length. 1090 template <typename TaggedArg> 1091 inline BOOST_CONSTEXPR ::boost::parameter::aux::flat_like_arg_list< 1092 ::boost::parameter::aux::flat_like_arg_tuple< 1093 typename TaggedArg::base_type::key_type 1094 , typename TaggedArg::base_type 1095 > 1096 , ArgTuples... 1097 > operator ,(TaggedArg const & x) const1098 operator,(TaggedArg const& x) const 1099 { 1100 return ::boost::parameter::aux::flat_like_arg_list< 1101 ::boost::parameter::aux::flat_like_arg_tuple< 1102 typename TaggedArg::base_type::key_type 1103 , typename TaggedArg::base_type 1104 > 1105 , ArgTuples... 1106 >( 1107 static_cast<typename TaggedArg::base_type const&>(x) 1108 , static_cast<_base_type const&>(*this) 1109 ); 1110 } 1111 }; 1112 1113 template <> 1114 class flat_like_arg_list<> 1115 : public ::boost::parameter::aux::empty_arg_list 1116 { 1117 using _base_type = ::boost::parameter::aux::empty_arg_list; 1118 1119 public: 1120 template <typename ...Args> flat_like_arg_list(Args &&...args)1121 inline BOOST_CONSTEXPR flat_like_arg_list(Args&&... args) 1122 : _base_type(::std::forward<Args>(args)...) 1123 { 1124 } 1125 1126 using _base_type::operator[]; 1127 using _base_type::satisfies; 1128 1129 // Comma operator to compose argument list without using parameters<>. 1130 // Useful for argument lists with undetermined length. 1131 template <typename TaggedArg> 1132 inline BOOST_CONSTEXPR ::boost::parameter::aux::flat_like_arg_list< 1133 ::boost::parameter::aux::flat_like_arg_tuple< 1134 typename TaggedArg::base_type::key_type 1135 , typename TaggedArg::base_type 1136 > 1137 > operator ,(TaggedArg const & x) const1138 operator,(TaggedArg const& x) const 1139 { 1140 return ::boost::parameter::aux::flat_like_arg_list< 1141 ::boost::parameter::aux::flat_like_arg_tuple< 1142 typename TaggedArg::base_type::key_type 1143 , typename TaggedArg::base_type 1144 > 1145 >( 1146 static_cast<typename TaggedArg::base_type const&>(x) 1147 , static_cast<_base_type const&>(*this) 1148 ); 1149 } 1150 }; 1151 }}} // namespace boost::parameter::aux 1152 1153 #endif // BOOST_PARAMETER_CAN_USE_MP11 1154 1155 #include <boost/mpl/iterator_tags.hpp> 1156 1157 namespace boost { namespace parameter { namespace aux { 1158 1159 // MPL sequence support 1160 template <typename ArgumentPack> 1161 struct arg_list_iterator 1162 { 1163 typedef ::boost::mpl::forward_iterator_tag category; 1164 1165 // The incremented iterator 1166 typedef ::boost::parameter::aux 1167 ::arg_list_iterator<typename ArgumentPack::tail_type> next; 1168 1169 // dereferencing yields the key type 1170 typedef typename ArgumentPack::key_type type; 1171 }; 1172 1173 template <> 1174 struct arg_list_iterator< ::boost::parameter::aux::empty_arg_list> 1175 { 1176 }; 1177 }}} // namespace boost::parameter::aux 1178 1179 #include <boost/mpl/begin_end_fwd.hpp> 1180 1181 // MPL sequence support 1182 namespace boost { namespace mpl { 1183 1184 template <> 1185 struct begin_impl< ::boost::parameter::aux::arg_list_tag> 1186 { 1187 template <typename S> 1188 struct apply 1189 { 1190 typedef ::boost::parameter::aux::arg_list_iterator<S> type; 1191 }; 1192 }; 1193 1194 template <> 1195 struct end_impl< ::boost::parameter::aux::arg_list_tag> 1196 { 1197 template <typename> 1198 struct apply 1199 { 1200 typedef ::boost::parameter::aux::arg_list_iterator< 1201 ::boost::parameter::aux::empty_arg_list 1202 > type; 1203 }; 1204 }; 1205 }} // namespace boost::mpl 1206 1207 #include <boost/parameter/value_type.hpp> 1208 #include <boost/mpl/has_key_fwd.hpp> 1209 #include <boost/type_traits/is_void.hpp> 1210 1211 namespace boost { namespace mpl { 1212 1213 template <> 1214 struct has_key_impl< ::boost::parameter::aux::arg_list_tag> 1215 { 1216 template <typename ArgList, typename Keyword> 1217 struct apply 1218 { 1219 typedef typename ::boost::mpl::if_< 1220 ::boost::is_void< 1221 typename ::boost::parameter 1222 ::value_type<ArgList,Keyword,void>::type 1223 > 1224 , ::boost::mpl::false_ 1225 , ::boost::mpl::true_ 1226 >::type type; 1227 }; 1228 }; 1229 }} // namespace boost::mpl 1230 1231 #include <boost/mpl/count_fwd.hpp> 1232 #include <boost/mpl/int.hpp> 1233 1234 namespace boost { namespace mpl { 1235 1236 template <> 1237 struct count_impl< ::boost::parameter::aux::arg_list_tag> 1238 { 1239 template <typename ArgList, typename Keyword> 1240 struct apply 1241 { 1242 typedef typename ::boost::mpl::if_< 1243 ::boost::is_void< 1244 typename ::boost::parameter 1245 ::value_type<ArgList,Keyword,void>::type 1246 > 1247 , ::boost::mpl::int_<0> 1248 , ::boost::mpl::int_<1> 1249 >::type type; 1250 }; 1251 }; 1252 }} // namespace boost::mpl 1253 1254 #include <boost/mpl/key_type_fwd.hpp> 1255 #include <boost/mpl/identity.hpp> 1256 1257 namespace boost { namespace mpl { 1258 1259 template <> 1260 struct key_type_impl< ::boost::parameter::aux::arg_list_tag> 1261 { 1262 template <typename ArgList, typename Keyword> 1263 struct apply 1264 { 1265 typedef typename ::boost::mpl::eval_if< 1266 ::boost::is_void< 1267 typename ::boost::parameter 1268 ::value_type<ArgList,Keyword,void>::type 1269 > 1270 , void 1271 , ::boost::mpl::identity<Keyword> 1272 >::type type; 1273 }; 1274 }; 1275 }} // namespace boost::mpl 1276 1277 #include <boost/mpl/value_type_fwd.hpp> 1278 1279 namespace boost { namespace mpl { 1280 1281 template <> 1282 struct value_type_impl< ::boost::parameter::aux::arg_list_tag> 1283 : ::boost::mpl::key_type_impl< ::boost::parameter::aux::arg_list_tag> 1284 { 1285 }; 1286 }} // namespace boost::mpl 1287 1288 #include <boost/mpl/at_fwd.hpp> 1289 1290 namespace boost { namespace mpl { 1291 1292 template <> 1293 struct at_impl< ::boost::parameter::aux::arg_list_tag> 1294 : ::boost::mpl::key_type_impl< ::boost::parameter::aux::arg_list_tag> 1295 { 1296 }; 1297 }} // namespace boost::mpl 1298 1299 #include <boost/mpl/order_fwd.hpp> 1300 #include <boost/mpl/void.hpp> 1301 #include <boost/mpl/find.hpp> 1302 #include <boost/mpl/distance.hpp> 1303 1304 namespace boost { namespace mpl { 1305 1306 template <> 1307 struct order_impl< ::boost::parameter::aux::arg_list_tag> 1308 { 1309 template <typename ArgList, typename Keyword> 1310 struct apply 1311 { 1312 typedef typename ::boost::mpl::find<ArgList,Keyword>::type Itr; 1313 typedef typename ::boost::mpl::eval_if< 1314 ::boost::is_void< 1315 typename ::boost::parameter 1316 ::value_type<ArgList,Keyword,void>::type 1317 > 1318 , ::boost::mpl::identity< ::boost::mpl::void_> 1319 , ::boost::mpl::distance< 1320 Itr 1321 , ::boost::parameter::aux::arg_list_iterator< 1322 ::boost::parameter::aux::empty_arg_list 1323 > 1324 > 1325 >::type type; 1326 }; 1327 }; 1328 }} // namespace boost::mpl 1329 1330 #endif // include guard 1331 1332