// Copyright David Abrahams, Daniel Wallin 2003. // Copyright Cromwell D. Enage 2017. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PARAMETERS_031014_HPP #define BOOST_PARAMETERS_031014_HPP #include <boost/parameter/config.hpp> #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) namespace boost { namespace parameter { namespace aux { // The make_arg_list<> metafunction produces a reversed arg_list, // so pass the arguments to the arg_list constructor reversed in turn. template <typename ArgList, typename ...Args> struct arg_list_factory; }}} // namespace boost::parameter::aux #include <boost/parameter/aux_/arg_list.hpp> #include <utility> #if defined(BOOST_PARAMETER_CAN_USE_MP11) #include <boost/mp11/utility.hpp> #include <type_traits> #else #include <boost/mpl/if.hpp> #include <boost/type_traits/is_same.hpp> #endif namespace boost { namespace parameter { namespace aux { // TODO: Reduce template code bloat. -- Cromwell D. Enage template <typename ArgList> struct arg_list_factory<ArgList> { template <typename ...ReversedArgs> static inline BOOST_CONSTEXPR ArgList reverse(ReversedArgs&&... reversed_args) { return ArgList( #if defined(BOOST_PARAMETER_CAN_USE_MP11) ::boost::mp11::mp_if< ::std::is_same< #else typename ::boost::mpl::if_< ::boost::is_same< #endif typename ArgList::tagged_arg::value_type , ::boost::parameter::void_ > , ::boost::parameter::aux::value_type_is_void , ::boost::parameter::aux::value_type_is_not_void #if defined(BOOST_PARAMETER_CAN_USE_MP11) >() #else >::type() #endif , ::std::forward<ReversedArgs>(reversed_args)... ); } }; template <typename ArgList, typename A0, typename ...Args> struct arg_list_factory<ArgList,A0,Args...> { template <typename ...ReversedArgs> static inline BOOST_CONSTEXPR ArgList reverse(A0&& a0, Args&&... args, ReversedArgs&&... reversed_args) { return ::boost::parameter::aux ::arg_list_factory<ArgList,Args...>::reverse( ::std::forward<Args>(args)... , ::std::forward<A0>(a0) , ::std::forward<ReversedArgs>(reversed_args)... ); } }; }}} // namespace boost::parameter::aux #include <boost/parameter/aux_/void.hpp> #include <boost/parameter/aux_/pack/make_arg_list.hpp> #include <boost/parameter/aux_/pack/make_parameter_spec_items.hpp> #include <boost/parameter/aux_/pack/tag_keyword_arg.hpp> #include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp> #if defined(BOOST_PARAMETER_CAN_USE_MP11) #include <boost/mp11/integral.hpp> #include <boost/mp11/list.hpp> #else #include <boost/mpl/bool.hpp> #include <boost/mpl/pair.hpp> #include <boost/mpl/identity.hpp> #endif #if !defined(BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE) #if defined(BOOST_PARAMETER_CAN_USE_MP11) //#include <boost/mp11/mpl.hpp> #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mp11::mp_list #else #include <boost/fusion/container/list/list_fwd.hpp> // Newer versions of MSVC fail on the evaluate_category and // preprocessor_eval_category test programs when parameters uses // boost::fusion::list. // -- Cromwell D. Enage #if defined(BOOST_FUSION_HAS_VARIADIC_LIST) && ( \ !defined(BOOST_MSVC) || (BOOST_MSVC < 1800) \ ) #include <boost/fusion/container/list.hpp> #include <boost/fusion/mpl.hpp> #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::list #else #include <boost/fusion/container/deque/deque_fwd.hpp> #if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE) #include <boost/fusion/container/deque.hpp> #include <boost/fusion/mpl.hpp> #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::deque #else #include <boost/mpl/vector.hpp> #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mpl::vector #endif // BOOST_FUSION_HAS_VARIADIC_DEQUE #endif // BOOST_FUSION_HAS_VARIADIC_LIST #endif // BOOST_PARAMETER_CAN_USE_MP11 #endif // BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE namespace boost { namespace parameter { template <typename ...Spec> struct parameters { typedef BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE<Spec...> parameter_spec; typedef typename ::boost::parameter::aux ::make_deduced_list<parameter_spec>::type deduced_list; // If the elements of NamedList match the criteria of overload // resolution, returns a type which can be constructed from // parameters. Otherwise, this is not a valid metafunction // (no nested ::type). template <typename ArgumentPackAndError> struct match_base #if !defined(BOOST_PARAMETER_CAN_USE_MP11) : ::boost::mpl::if_< typename ::boost::parameter::aux::match_parameters_base_cond< ArgumentPackAndError , parameter_spec >::type , ::boost::mpl::identity< ::boost::parameter::parameters<Spec...> > , ::boost::parameter::void_ > #endif { #if defined(BOOST_PARAMETER_CAN_USE_MP11) using type = ::boost::mp11::mp_if< typename ::boost::parameter::aux::match_parameters_base_cond< ArgumentPackAndError , parameter_spec >::type , ::boost::mp11::mp_identity< ::boost::parameter::parameters<Spec...> > , ::boost::parameter::void_ >; #endif }; // Specializations are to be used as an optional argument // to eliminate overloads via SFINAE. template <typename ...Args> struct match : ::boost::parameter::parameters<Spec...> ::BOOST_NESTED_TEMPLATE match_base< typename ::boost::parameter::aux::make_arg_list< typename ::boost::parameter::aux ::make_parameter_spec_items<parameter_spec,Args...>::type , deduced_list , ::boost::parameter::aux::tag_keyword_arg // Don't emit errors when doing SFINAE. #if defined(BOOST_PARAMETER_CAN_USE_MP11) , ::boost::mp11::mp_false #else , ::boost::mpl::false_ #endif >::type >::type { }; // Metafunction that returns an ArgumentPack. template <typename ...Args> struct bind #if !defined(BOOST_PARAMETER_CAN_USE_MP11) : ::boost::mpl::first< typename ::boost::parameter::aux::make_arg_list< typename ::boost::parameter::aux ::make_parameter_spec_items<parameter_spec,Args...>::type , deduced_list , ::boost::parameter::aux::tag_template_keyword_arg >::type > #endif { #if defined(BOOST_PARAMETER_CAN_USE_MP11) using type = ::boost::mp11::mp_at_c< typename ::boost::parameter::aux::make_arg_list< typename ::boost::parameter::aux ::make_parameter_spec_items<parameter_spec,Args...>::type , deduced_list , ::boost::parameter::aux::tag_template_keyword_arg >::type , 0 >; #endif }; // The function call operator is used to build an arg_list that // labels the positional parameters and maintains whatever other // tags may have been specified by the caller. inline ::boost::parameter::aux::empty_arg_list operator()() const { return ::boost::parameter::aux::empty_arg_list(); } template <typename A0, typename ...Args> #if defined(BOOST_PARAMETER_CAN_USE_MP11) inline ::boost::mp11::mp_at_c< #else inline typename ::boost::mpl::first< #endif typename ::boost::parameter::aux::make_arg_list< typename ::boost::parameter::aux ::make_parameter_spec_items<parameter_spec,A0,Args...>::type , deduced_list , ::boost::parameter::aux::tag_keyword_arg >::type #if defined(BOOST_PARAMETER_CAN_USE_MP11) , 0 > #else >::type #endif operator()(A0&& a0, Args&& ...args) const { typedef typename ::boost::parameter::aux::make_arg_list< typename ::boost::parameter::aux ::make_parameter_spec_items<parameter_spec,A0,Args...>::type , deduced_list , ::boost::parameter::aux::tag_keyword_arg >::type list_error_pair; #if defined(BOOST_PARAMETER_CAN_USE_MP11) using result_type = ::boost::mp11::mp_at_c<list_error_pair,0>; using error = ::boost::mp11::mp_at_c<list_error_pair,1>; #else typedef typename ::boost::mpl ::first<list_error_pair>::type result_type; typedef typename ::boost::mpl ::second<list_error_pair>::type error; #endif error(); return ::boost::parameter::aux ::arg_list_factory<result_type,A0,Args...>::reverse( ::std::forward<A0>(a0) , ::std::forward<Args>(args)... ); } }; }} // namespace boost::parameter #else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) #include <boost/parameter/aux_/void.hpp> #include <boost/parameter/aux_/arg_list.hpp> #include <boost/parameter/aux_/pack/make_arg_list.hpp> #include <boost/parameter/aux_/pack/make_items.hpp> #include <boost/parameter/aux_/pack/make_deduced_items.hpp> #include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp> #include <boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp> #include <boost/preprocessor/arithmetic/inc.hpp> #include <boost/preprocessor/repetition/enum_shifted.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/selection/min.hpp> #if ( \ BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \ BOOST_PARAMETER_MAX_ARITY \ ) #include <boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp> #include <boost/mpl/pair.hpp> #include <boost/preprocessor/arithmetic/dec.hpp> #include <boost/preprocessor/arithmetic/sub.hpp> #include <boost/preprocessor/facilities/intercept.hpp> #include <boost/preprocessor/iteration/iterate.hpp> #include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum_trailing_params.hpp> #endif #if !defined(BOOST_NO_SFINAE) && \ !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x592)) #include <boost/parameter/aux_/pack/tag_keyword_arg.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/identity.hpp> #include <boost/type_traits/is_same.hpp> #endif #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) #include <boost/preprocessor/repetition/enum_params.hpp> #else #include <boost/preprocessor/repetition/enum_binary_params.hpp> #endif #include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp> namespace boost { namespace parameter { template < typename PS0 , BOOST_PP_ENUM_SHIFTED( BOOST_PARAMETER_MAX_ARITY , BOOST_PARAMETER_template_args , PS ) > struct parameters { typedef typename BOOST_PARAMETER_build_deduced_list( BOOST_PARAMETER_MAX_ARITY , ::boost::parameter::aux::make_deduced_items , PS )::type deduced_list; // If the elements of NamedList match the criteria of overload // resolution, returns a type which can be constructed from // parameters. Otherwise, this is not a valid metafunction // (no nested ::type). #if !defined(BOOST_NO_SFINAE) && \ !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x592)) // If NamedList satisfies the PS0, PS1, ..., this is a metafunction // returning parameters. Otherwise it has no nested ::type. template <typename ArgumentPackAndError> struct match_base : ::boost::mpl::if_< // ::boost::mpl::and_< // aux::satisfies_requirements_of<NamedList,PS0> // , ::boost::mpl::and_< // aux::satisfies_requirements_of<NamedList,PS1>... // ..., ::boost::mpl::true_ // ...> > typename BOOST_PP_REPEAT( BOOST_PARAMETER_MAX_ARITY , BOOST_PARAMETER_satisfies_begin , PS ) ::boost::is_same< typename ::boost::mpl ::second<ArgumentPackAndError>::type , ::boost::parameter::void_ > BOOST_PP_REPEAT( BOOST_PARAMETER_MAX_ARITY , BOOST_PARAMETER_satisfies_end , ::boost::mpl::false_ )::type , ::boost::mpl::identity< ::boost::parameter::parameters< BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) > > , ::boost::parameter::void_ > { }; #endif // SFINAE enabled, not Borland // Specializations are to be used as an optional argument // to eliminate overloads via SFINAE. template < #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) // Borland simply can't handle default arguments in member // class templates. People wishing to write portable code can // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments. BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A) #else BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PARAMETER_MAX_ARITY , typename A , = ::boost::parameter::void_ BOOST_PP_INTERCEPT ) #endif > struct match #if !defined(BOOST_NO_SFINAE) && \ !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x592)) : ::boost::parameter::parameters< BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) >::BOOST_NESTED_TEMPLATE match_base< typename ::boost::parameter::aux::make_arg_list< typename BOOST_PARAMETER_build_arg_list( BOOST_PARAMETER_MAX_ARITY , ::boost::parameter::aux::make_items , PS , A )::type , deduced_list , ::boost::parameter::aux::tag_keyword_arg // Don't emit errors when doing SFINAE. , ::boost::mpl::false_ >::type >::type { }; #else { typedef ::boost::parameter::parameters< BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) > type; }; #endif // SFINAE enabled, not Borland // Metafunction that returns an ArgumentPack. // TODO, bind has to instantiate the error type in the result // of make_arg_list. template < #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) // Borland simply can't handle default arguments in member // class templates. People wishing to write portable code can // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments. BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A) #else BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PARAMETER_MAX_ARITY , typename A , = ::boost::parameter::void_ BOOST_PP_INTERCEPT ) #endif > struct bind { typedef typename ::boost::parameter::aux::make_arg_list< typename BOOST_PARAMETER_build_arg_list( BOOST_PARAMETER_MAX_ARITY , ::boost::parameter::aux::make_items , PS , A )::type , deduced_list , ::boost::parameter::aux::tag_template_keyword_arg >::type result; typedef typename ::boost::mpl::first<result>::type type; }; BOOST_PP_REPEAT( BOOST_PARAMETER_MAX_ARITY , BOOST_PARAMETER_forward_typedef , (PS)(parameter_spec) ) // The function call operator is used to build an arg_list that // labels the positional parameters and maintains whatever other // tags may have been specified by the caller. // // !!!NOTE!!! // // The make_arg_list<> metafunction produces a reversed arg_list, // so pass the arguments to the arg_list constructor reversed in turn. inline ::boost::parameter::aux::empty_arg_list operator()() const { return ::boost::parameter::aux::empty_arg_list(); } #if (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY) BOOST_PP_REPEAT( BOOST_PP_MIN( BOOST_PP_INC(BOOST_PARAMETER_MAX_ARITY) , BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY ) , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z , (BOOST_PARAMETER_function_call_op_overload_R)(_) ) #if ( \ BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \ BOOST_PARAMETER_MAX_ARITY \ ) #define BOOST_PP_ITERATION_PARAMS_1 \ (3,( \ BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \ , BOOST_PARAMETER_MAX_ARITY \ , <boost/parameter/aux_/preprocessor/overloads.hpp> \ )) #include BOOST_PP_ITERATE() #endif #else // (0 == BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY) template <typename A0> inline typename ::boost::mpl::first< typename ::boost::parameter::aux::make_arg_list< ::boost::parameter::aux::item< PS0,A0 > , deduced_list , ::boost::parameter::aux::tag_keyword_arg_ref >::type >::type operator()(A0& a0) const { typedef typename ::boost::parameter::aux::make_arg_list< ::boost::parameter::aux::item< PS0,A0 > , deduced_list , ::boost::parameter::aux::tag_keyword_arg_ref >::type result; typedef typename ::boost::mpl::first<result>::type result_type; typedef typename ::boost::mpl::second<result>::type error; error(); return result_type( a0 // , void_(), void_(), void_() ... BOOST_PP_ENUM_TRAILING_PARAMS( BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 1) , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT ) ); } template <typename A0, typename A1> inline typename ::boost::mpl::first< typename ::boost::parameter::aux::make_arg_list< ::boost::parameter::aux::item< PS0,A0 , ::boost::parameter::aux::item< PS1,A1 > > , deduced_list , ::boost::parameter::aux::tag_keyword_arg_ref >::type >::type operator()(A0& a0, A1& a1) const { typedef typename ::boost::parameter::aux::make_arg_list< ::boost::parameter::aux::item< PS0,A0 , ::boost::parameter::aux::item< PS1,A1 > > , deduced_list , ::boost::parameter::aux::tag_keyword_arg >::type result; typedef typename ::boost::mpl::first<result>::type result_type; typedef typename ::boost::mpl::second<result>::type error; error(); return result_type( a1 , a0 // , void_(), void_() ... BOOST_PP_ENUM_TRAILING_PARAMS( BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 2) , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT ) ); } #if (2 < BOOST_PARAMETER_MAX_ARITY) // Higher arities are handled by the preprocessor #define BOOST_PP_ITERATION_PARAMS_1 \ (3,( \ 3 \ , BOOST_PARAMETER_MAX_ARITY \ , <boost/parameter/aux_/preprocessor/overloads.hpp> \ )) #include BOOST_PP_ITERATE() #endif #endif // exponential overloads }; }} // namespace boost::parameter #include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp> #endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING #endif // include guard