1 // Copyright David Abrahams, Daniel Wallin 2003. 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_PARAMETERS_031014_HPP 8 #define BOOST_PARAMETERS_031014_HPP 9 10 #include <boost/parameter/config.hpp> 11 12 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) 13 14 namespace boost { namespace parameter { namespace aux { 15 16 // The make_arg_list<> metafunction produces a reversed arg_list, 17 // so pass the arguments to the arg_list constructor reversed in turn. 18 template <typename ArgList, typename ...Args> 19 struct arg_list_factory; 20 }}} // namespace boost::parameter::aux 21 22 #include <boost/parameter/aux_/arg_list.hpp> 23 #include <utility> 24 25 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 26 #include <boost/mp11/utility.hpp> 27 #include <type_traits> 28 #else 29 #include <boost/mpl/if.hpp> 30 #include <boost/type_traits/is_same.hpp> 31 #endif 32 33 namespace boost { namespace parameter { namespace aux { 34 35 // TODO: Reduce template code bloat. -- Cromwell D. Enage 36 template <typename ArgList> 37 struct arg_list_factory<ArgList> 38 { 39 template <typename ...ReversedArgs> 40 static inline BOOST_CONSTEXPR ArgList reverseboost::parameter::aux::arg_list_factory41 reverse(ReversedArgs&&... reversed_args) 42 { 43 return ArgList( 44 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 45 ::boost::mp11::mp_if< 46 ::std::is_same< 47 #else 48 typename ::boost::mpl::if_< 49 ::boost::is_same< 50 #endif 51 typename ArgList::tagged_arg::value_type 52 , ::boost::parameter::void_ 53 > 54 , ::boost::parameter::aux::value_type_is_void 55 , ::boost::parameter::aux::value_type_is_not_void 56 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 57 >() 58 #else 59 >::type() 60 #endif 61 , ::std::forward<ReversedArgs>(reversed_args)... 62 ); 63 } 64 }; 65 66 template <typename ArgList, typename A0, typename ...Args> 67 struct arg_list_factory<ArgList,A0,Args...> 68 { 69 template <typename ...ReversedArgs> 70 static inline BOOST_CONSTEXPR ArgList reverseboost::parameter::aux::arg_list_factory71 reverse(A0&& a0, Args&&... args, ReversedArgs&&... reversed_args) 72 { 73 return ::boost::parameter::aux 74 ::arg_list_factory<ArgList,Args...>::reverse( 75 ::std::forward<Args>(args)... 76 , ::std::forward<A0>(a0) 77 , ::std::forward<ReversedArgs>(reversed_args)... 78 ); 79 } 80 }; 81 }}} // namespace boost::parameter::aux 82 83 #include <boost/parameter/aux_/void.hpp> 84 #include <boost/parameter/aux_/pack/make_arg_list.hpp> 85 #include <boost/parameter/aux_/pack/make_parameter_spec_items.hpp> 86 #include <boost/parameter/aux_/pack/tag_keyword_arg.hpp> 87 #include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp> 88 89 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 90 #include <boost/mp11/integral.hpp> 91 #include <boost/mp11/list.hpp> 92 #else 93 #include <boost/mpl/bool.hpp> 94 #include <boost/mpl/pair.hpp> 95 #include <boost/mpl/identity.hpp> 96 #endif 97 98 #if !defined(BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE) 99 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 100 //#include <boost/mp11/mpl.hpp> 101 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mp11::mp_list 102 #else 103 #include <boost/fusion/container/list/list_fwd.hpp> 104 105 // Newer versions of MSVC fail on the evaluate_category and 106 // preprocessor_eval_category test programs when parameters uses 107 // boost::fusion::list. 108 // -- Cromwell D. Enage 109 #if defined(BOOST_FUSION_HAS_VARIADIC_LIST) && ( \ 110 !defined(BOOST_MSVC) || (BOOST_MSVC < 1800) \ 111 ) 112 #include <boost/fusion/container/list.hpp> 113 #include <boost/fusion/mpl.hpp> 114 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::list 115 #else 116 #include <boost/fusion/container/deque/deque_fwd.hpp> 117 118 #if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE) 119 #include <boost/fusion/container/deque.hpp> 120 #include <boost/fusion/mpl.hpp> 121 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::deque 122 #else 123 #include <boost/mpl/vector.hpp> 124 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mpl::vector 125 #endif // BOOST_FUSION_HAS_VARIADIC_DEQUE 126 #endif // BOOST_FUSION_HAS_VARIADIC_LIST 127 #endif // BOOST_PARAMETER_CAN_USE_MP11 128 #endif // BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE 129 130 namespace boost { namespace parameter { 131 132 template <typename ...Spec> 133 struct parameters 134 { 135 typedef BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE<Spec...> parameter_spec; 136 137 typedef typename ::boost::parameter::aux 138 ::make_deduced_list<parameter_spec>::type deduced_list; 139 140 // If the elements of NamedList match the criteria of overload 141 // resolution, returns a type which can be constructed from 142 // parameters. Otherwise, this is not a valid metafunction 143 // (no nested ::type). 144 template <typename ArgumentPackAndError> 145 struct match_base 146 #if !defined(BOOST_PARAMETER_CAN_USE_MP11) 147 : ::boost::mpl::if_< 148 typename ::boost::parameter::aux::match_parameters_base_cond< 149 ArgumentPackAndError 150 , parameter_spec 151 >::type 152 , ::boost::mpl::identity< 153 ::boost::parameter::parameters<Spec...> 154 > 155 , ::boost::parameter::void_ 156 > 157 #endif 158 { 159 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 160 using type = ::boost::mp11::mp_if< 161 typename ::boost::parameter::aux::match_parameters_base_cond< 162 ArgumentPackAndError 163 , parameter_spec 164 >::type 165 , ::boost::mp11::mp_identity< 166 ::boost::parameter::parameters<Spec...> 167 > 168 , ::boost::parameter::void_ 169 >; 170 #endif 171 }; 172 173 // Specializations are to be used as an optional argument 174 // to eliminate overloads via SFINAE. 175 template <typename ...Args> 176 struct match 177 : ::boost::parameter::parameters<Spec...> 178 ::BOOST_NESTED_TEMPLATE match_base< 179 typename ::boost::parameter::aux::make_arg_list< 180 typename ::boost::parameter::aux 181 ::make_parameter_spec_items<parameter_spec,Args...>::type 182 , deduced_list 183 , ::boost::parameter::aux::tag_keyword_arg 184 // Don't emit errors when doing SFINAE. 185 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 186 , ::boost::mp11::mp_false 187 #else 188 , ::boost::mpl::false_ 189 #endif 190 >::type 191 >::type 192 { 193 }; 194 195 // Metafunction that returns an ArgumentPack. 196 template <typename ...Args> 197 struct bind 198 #if !defined(BOOST_PARAMETER_CAN_USE_MP11) 199 : ::boost::mpl::first< 200 typename ::boost::parameter::aux::make_arg_list< 201 typename ::boost::parameter::aux 202 ::make_parameter_spec_items<parameter_spec,Args...>::type 203 , deduced_list 204 , ::boost::parameter::aux::tag_template_keyword_arg 205 >::type 206 > 207 #endif 208 { 209 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 210 using type = ::boost::mp11::mp_at_c< 211 typename ::boost::parameter::aux::make_arg_list< 212 typename ::boost::parameter::aux 213 ::make_parameter_spec_items<parameter_spec,Args...>::type 214 , deduced_list 215 , ::boost::parameter::aux::tag_template_keyword_arg 216 >::type 217 , 0 218 >; 219 #endif 220 }; 221 222 // The function call operator is used to build an arg_list that 223 // labels the positional parameters and maintains whatever other 224 // tags may have been specified by the caller. operator ()boost::parameter::parameters225 inline ::boost::parameter::aux::empty_arg_list operator()() const 226 { 227 return ::boost::parameter::aux::empty_arg_list(); 228 } 229 230 template <typename A0, typename ...Args> 231 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 232 inline ::boost::mp11::mp_at_c< 233 #else 234 inline typename ::boost::mpl::first< 235 #endif 236 typename ::boost::parameter::aux::make_arg_list< 237 typename ::boost::parameter::aux 238 ::make_parameter_spec_items<parameter_spec,A0,Args...>::type 239 , deduced_list 240 , ::boost::parameter::aux::tag_keyword_arg 241 >::type 242 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 243 , 0 244 > 245 #else 246 >::type 247 #endif operator ()boost::parameter::parameters248 operator()(A0&& a0, Args&& ...args) const 249 { 250 typedef typename ::boost::parameter::aux::make_arg_list< 251 typename ::boost::parameter::aux 252 ::make_parameter_spec_items<parameter_spec,A0,Args...>::type 253 , deduced_list 254 , ::boost::parameter::aux::tag_keyword_arg 255 >::type list_error_pair; 256 257 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 258 using result_type = ::boost::mp11::mp_at_c<list_error_pair,0>; 259 260 using error = ::boost::mp11::mp_at_c<list_error_pair,1>; 261 #else 262 typedef typename ::boost::mpl 263 ::first<list_error_pair>::type result_type; 264 265 typedef typename ::boost::mpl 266 ::second<list_error_pair>::type error; 267 #endif 268 269 error(); 270 271 return ::boost::parameter::aux 272 ::arg_list_factory<result_type,A0,Args...>::reverse( 273 ::std::forward<A0>(a0) 274 , ::std::forward<Args>(args)... 275 ); 276 } 277 }; 278 }} // namespace boost::parameter 279 280 #else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) 281 282 #include <boost/parameter/aux_/void.hpp> 283 #include <boost/parameter/aux_/arg_list.hpp> 284 #include <boost/parameter/aux_/pack/make_arg_list.hpp> 285 #include <boost/parameter/aux_/pack/make_items.hpp> 286 #include <boost/parameter/aux_/pack/make_deduced_items.hpp> 287 #include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp> 288 #include <boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp> 289 #include <boost/preprocessor/arithmetic/inc.hpp> 290 #include <boost/preprocessor/repetition/enum_shifted.hpp> 291 #include <boost/preprocessor/repetition/repeat.hpp> 292 #include <boost/preprocessor/selection/min.hpp> 293 294 #if ( \ 295 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \ 296 BOOST_PARAMETER_MAX_ARITY \ 297 ) 298 #include <boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp> 299 #include <boost/mpl/pair.hpp> 300 #include <boost/preprocessor/arithmetic/dec.hpp> 301 #include <boost/preprocessor/arithmetic/sub.hpp> 302 #include <boost/preprocessor/facilities/intercept.hpp> 303 #include <boost/preprocessor/iteration/iterate.hpp> 304 #include <boost/preprocessor/repetition/enum.hpp> 305 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 306 #endif 307 308 #if !defined(BOOST_NO_SFINAE) && \ 309 !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) 310 #include <boost/parameter/aux_/pack/tag_keyword_arg.hpp> 311 #include <boost/mpl/bool.hpp> 312 #include <boost/mpl/if.hpp> 313 #include <boost/mpl/identity.hpp> 314 #include <boost/type_traits/is_same.hpp> 315 #endif 316 317 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 318 #include <boost/preprocessor/repetition/enum_params.hpp> 319 #else 320 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 321 #endif 322 323 #include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp> 324 325 namespace boost { namespace parameter { 326 327 template < 328 typename PS0 329 , BOOST_PP_ENUM_SHIFTED( 330 BOOST_PARAMETER_MAX_ARITY 331 , BOOST_PARAMETER_template_args 332 , PS 333 ) 334 > 335 struct parameters 336 { 337 typedef typename BOOST_PARAMETER_build_deduced_list( 338 BOOST_PARAMETER_MAX_ARITY 339 , ::boost::parameter::aux::make_deduced_items 340 , PS 341 )::type deduced_list; 342 343 // If the elements of NamedList match the criteria of overload 344 // resolution, returns a type which can be constructed from 345 // parameters. Otherwise, this is not a valid metafunction 346 // (no nested ::type). 347 #if !defined(BOOST_NO_SFINAE) && \ 348 !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) 349 // If NamedList satisfies the PS0, PS1, ..., this is a metafunction 350 // returning parameters. Otherwise it has no nested ::type. 351 template <typename ArgumentPackAndError> 352 struct match_base 353 : ::boost::mpl::if_< 354 // ::boost::mpl::and_< 355 // aux::satisfies_requirements_of<NamedList,PS0> 356 // , ::boost::mpl::and_< 357 // aux::satisfies_requirements_of<NamedList,PS1>... 358 // ..., ::boost::mpl::true_ 359 // ...> > 360 typename BOOST_PP_REPEAT( 361 BOOST_PARAMETER_MAX_ARITY 362 , BOOST_PARAMETER_satisfies_begin 363 , PS 364 ) 365 ::boost::is_same< 366 typename ::boost::mpl 367 ::second<ArgumentPackAndError>::type 368 , ::boost::parameter::void_ 369 > 370 BOOST_PP_REPEAT( 371 BOOST_PARAMETER_MAX_ARITY 372 , BOOST_PARAMETER_satisfies_end 373 , ::boost::mpl::false_ 374 )::type 375 , ::boost::mpl::identity< 376 ::boost::parameter::parameters< 377 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) 378 > 379 > 380 , ::boost::parameter::void_ 381 > 382 { 383 }; 384 #endif // SFINAE enabled, not Borland 385 386 // Specializations are to be used as an optional argument 387 // to eliminate overloads via SFINAE. 388 template < 389 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 390 // Borland simply can't handle default arguments in member 391 // class templates. People wishing to write portable code can 392 // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments. 393 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A) 394 #else 395 BOOST_PP_ENUM_BINARY_PARAMS( 396 BOOST_PARAMETER_MAX_ARITY 397 , typename A 398 , = ::boost::parameter::void_ BOOST_PP_INTERCEPT 399 ) 400 #endif 401 > 402 struct match 403 #if !defined(BOOST_NO_SFINAE) && \ 404 !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) 405 : ::boost::parameter::parameters< 406 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) 407 >::BOOST_NESTED_TEMPLATE match_base< 408 typename ::boost::parameter::aux::make_arg_list< 409 typename BOOST_PARAMETER_build_arg_list( 410 BOOST_PARAMETER_MAX_ARITY 411 , ::boost::parameter::aux::make_items 412 , PS 413 , A 414 )::type 415 , deduced_list 416 , ::boost::parameter::aux::tag_keyword_arg 417 // Don't emit errors when doing SFINAE. 418 , ::boost::mpl::false_ 419 >::type 420 >::type 421 { 422 }; 423 #else 424 { 425 typedef ::boost::parameter::parameters< 426 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) 427 > type; 428 }; 429 #endif // SFINAE enabled, not Borland 430 431 // Metafunction that returns an ArgumentPack. 432 433 // TODO, bind has to instantiate the error type in the result 434 // of make_arg_list. 435 436 template < 437 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 438 // Borland simply can't handle default arguments in member 439 // class templates. People wishing to write portable code can 440 // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments. 441 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A) 442 #else 443 BOOST_PP_ENUM_BINARY_PARAMS( 444 BOOST_PARAMETER_MAX_ARITY 445 , typename A 446 , = ::boost::parameter::void_ BOOST_PP_INTERCEPT 447 ) 448 #endif 449 > 450 struct bind 451 { 452 typedef typename ::boost::parameter::aux::make_arg_list< 453 typename BOOST_PARAMETER_build_arg_list( 454 BOOST_PARAMETER_MAX_ARITY 455 , ::boost::parameter::aux::make_items 456 , PS 457 , A 458 )::type 459 , deduced_list 460 , ::boost::parameter::aux::tag_template_keyword_arg 461 >::type result; 462 463 typedef typename ::boost::mpl::first<result>::type type; 464 }; 465 466 BOOST_PP_REPEAT( 467 BOOST_PARAMETER_MAX_ARITY 468 , BOOST_PARAMETER_forward_typedef 469 , (PS)(parameter_spec) 470 ) 471 472 // The function call operator is used to build an arg_list that 473 // labels the positional parameters and maintains whatever other 474 // tags may have been specified by the caller. 475 // 476 // !!!NOTE!!! 477 // 478 // The make_arg_list<> metafunction produces a reversed arg_list, 479 // so pass the arguments to the arg_list constructor reversed in turn. operator ()boost::parameter::parameters480 inline ::boost::parameter::aux::empty_arg_list operator()() const 481 { 482 return ::boost::parameter::aux::empty_arg_list(); 483 } 484 485 #if (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY) 486 BOOST_PP_REPEAT( 487 BOOST_PP_MIN( 488 BOOST_PP_INC(BOOST_PARAMETER_MAX_ARITY) 489 , BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY 490 ) 491 , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z 492 , (BOOST_PARAMETER_function_call_op_overload_R)(_) 493 ) 494 #if ( \ 495 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \ 496 BOOST_PARAMETER_MAX_ARITY \ 497 ) 498 #define BOOST_PP_ITERATION_PARAMS_1 \ 499 (3,( \ 500 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \ 501 , BOOST_PARAMETER_MAX_ARITY \ 502 , <boost/parameter/aux_/preprocessor/overloads.hpp> \ 503 )) 504 #include BOOST_PP_ITERATE() 505 #endif 506 #else // (0 == BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY) 507 template <typename A0> 508 inline typename ::boost::mpl::first< 509 typename ::boost::parameter::aux::make_arg_list< 510 ::boost::parameter::aux::item< 511 PS0,A0 512 > 513 , deduced_list 514 , ::boost::parameter::aux::tag_keyword_arg_ref 515 >::type 516 >::type 517 operator()(A0& a0) const 518 { 519 typedef typename ::boost::parameter::aux::make_arg_list< 520 ::boost::parameter::aux::item< 521 PS0,A0 522 > 523 , deduced_list 524 , ::boost::parameter::aux::tag_keyword_arg_ref 525 >::type result; 526 527 typedef typename ::boost::mpl::first<result>::type result_type; 528 typedef typename ::boost::mpl::second<result>::type error; 529 error(); 530 531 return result_type( 532 a0 533 // , void_(), void_(), void_() ... 534 BOOST_PP_ENUM_TRAILING_PARAMS( 535 BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 1) 536 , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT 537 ) 538 ); 539 } 540 541 template <typename A0, typename A1> 542 inline typename ::boost::mpl::first< 543 typename ::boost::parameter::aux::make_arg_list< 544 ::boost::parameter::aux::item< 545 PS0,A0 546 , ::boost::parameter::aux::item< 547 PS1,A1 548 > 549 > 550 , deduced_list 551 , ::boost::parameter::aux::tag_keyword_arg_ref 552 >::type 553 >::type 554 operator()(A0& a0, A1& a1) const 555 { 556 typedef typename ::boost::parameter::aux::make_arg_list< 557 ::boost::parameter::aux::item< 558 PS0,A0 559 , ::boost::parameter::aux::item< 560 PS1,A1 561 > 562 > 563 , deduced_list 564 , ::boost::parameter::aux::tag_keyword_arg 565 >::type result; 566 567 typedef typename ::boost::mpl::first<result>::type result_type; 568 typedef typename ::boost::mpl::second<result>::type error; 569 error(); 570 571 return result_type( 572 a1 573 , a0 574 // , void_(), void_() ... 575 BOOST_PP_ENUM_TRAILING_PARAMS( 576 BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 2) 577 , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT 578 ) 579 ); 580 } 581 582 #if (2 < BOOST_PARAMETER_MAX_ARITY) 583 // Higher arities are handled by the preprocessor 584 #define BOOST_PP_ITERATION_PARAMS_1 \ 585 (3,( \ 586 3 \ 587 , BOOST_PARAMETER_MAX_ARITY \ 588 , <boost/parameter/aux_/preprocessor/overloads.hpp> \ 589 )) 590 #include BOOST_PP_ITERATE() 591 #endif 592 #endif // exponential overloads 593 }; 594 }} // namespace boost::parameter 595 596 #include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp> 597 598 #endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING 599 #endif // include guard 600 601