// Copyright Daniel Wallin 2006. // 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_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_DISPATCH_LAYER_HPP #define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_DISPATCH_LAYER_HPP #include // Expands to keyword_tag_type for some keyword_tag. #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(keyword_tag) \ BOOST_PP_CAT(keyword_tag, _type) /**/ // Expands to a template parameter for each dispatch function. #define BOOST_PARAMETER_FUNCTION_DISPATCH_TEMPLATE_ARG(r, macro, arg) \ , typename BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg)) /**/ #include #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) // Expands to a forwarding parameter for a dispatch function. #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_DEFN(r, macro, arg) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg))&& macro(arg) /**/ #include // Expands to an argument passed from one dispatch function to the next. #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD(r, macro, arg) \ , ::std::forward< \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg)) \ >(macro(arg)) /**/ #else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) // Expands to a forwarding parameter for a dispatch function. The parameter // type stores its const-ness. #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_DEFN(r, macro, arg) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_TYPE(macro(arg))& macro(arg) /**/ #include // Expands to an argument passed from one dispatch function to the next. // Explicit forwarding takes the form of forcing the argument to be an lvalue. #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD(r, macro, arg) \ , ::boost::parameter::aux::as_lvalue(macro(arg)) /**/ #endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING #include #include #include #include // Iterates through all required arguments and the first n optional arguments, // passing each argument to the specified macro. #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT(macro, n, split_args) \ BOOST_PP_SEQ_FOR_EACH( \ macro \ , BOOST_PARAMETER_FN_ARG_NAME \ , BOOST_PARAMETER_SPLIT_ARG_REQ_SEQ(split_args) \ ) \ BOOST_PP_SEQ_FOR_EACH( \ macro \ , BOOST_PARAMETER_FN_ARG_NAME \ , BOOST_PP_SEQ_FIRST_N( \ n, BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(split_args) \ ) \ ) /**/ #include #include #include // Produces a name for the dispatch functions. #define BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, n) \ BOOST_PP_CAT( \ BOOST_PP_CAT( \ BOOST_PP_IF( \ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \ , boost_param_dispatch_const_ \ , boost_param_dispatch_ \ ) \ , BOOST_PP_CAT(BOOST_PP_CAT(n, boost_), __LINE__) \ ) \ , BOOST_PARAMETER_MEMBER_FUNCTION_NAME( \ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \ ) \ ) /**/ // Expands to the template parameter list of the dispatch function with all // required and first n optional parameters; also extracts the static keyword // if present. #define BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \ template < \ typename ResultType, typename Args \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_TEMPLATE_ARG \ , n \ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ > BOOST_PARAMETER_MEMBER_FUNCTION_STATIC( \ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \ ) /**/ #include #include #include // Expands to the result type, name, parenthesized list of all required and // n optional parameters, and const-ness of the dispatch function; the bit // value b determines whether or not this dispatch function takes in // boost::parameter::aux::use_default_tag as its last parameter. #define BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, b1, b2) \ ResultType BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, b1)( \ ResultType(*)(), Args const& args, long \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_DEFN \ , n \ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ BOOST_PP_COMMA_IF(b2) \ BOOST_PP_EXPR_IF(b2, ::boost::parameter::aux::use_default_tag) \ ) BOOST_PP_EXPR_IF(BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x), const) /**/ // Expands to a forward declaration of the dispatch function that takes in // all required and the first n optional parameters, but not // boost::parameter::aux::use_default_tag. #define BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_0_Z(z, n, x) \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 0); /**/ // Expands to a forward declaration of the dispatch function that takes in // all required parameters, the first n optional parameters, and // boost::parameter::aux::use_default_tag. #define BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_1_Z(z, n, x) \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 1); /**/ #include // Expands to the default value of the (n + 1)th optional parameter. #define BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT_AUX(n, s_args) \ BOOST_PARAMETER_FN_ARG_DEFAULT( \ BOOST_PP_SEQ_ELEM(n, BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(s_args)) \ ) /**/ #include // Expands to the assignment portion which binds the default value to the // (n + 1)th optional parameter before composing it with the argument-pack // parameter passed in to the n-th dispatch function. #define BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT(n, s_args, tag_ns) \ ::boost::parameter::keyword< \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME( \ BOOST_PP_SEQ_ELEM(n, BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ(s_args)) \ ) \ >::instance = BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT_AUX(n, s_args) /**/ #include // Takes in the arg tuple (name, pred) and the tag namespace. // Extracts the corresponding required argument from the pack. // This form enables BOOST_PARAMETER_FUNCTION_DISPATCH_LAYER to use it // from within BOOST_PP_SEQ_FOR_EACH. #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) // The boost::parameter::aux::forward wrapper is necessary to transmit the // target type to the next dispatch function. Otherwise, the argument will // retain its original type. -- Cromwell D. Enage #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_CAST_R(r, tag_ns, arg) \ , ::boost::parameter::aux::forward< \ BOOST_PARAMETER_FUNCTION_CAST_T( \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ , BOOST_PARAMETER_FN_ARG_PRED(arg) \ , Args \ ) \ , BOOST_PARAMETER_FUNCTION_CAST_B( \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ , BOOST_PARAMETER_FN_ARG_PRED(arg) \ , Args \ ) \ >( \ args[ \ ::boost::parameter::keyword< \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ >::instance \ ] \ ) /**/ #else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) // The explicit type cast is necessary to transmit the target type to the next // dispatch function. Otherwise, the argument will retain its original type. // -- Cromwell D. Enage #define BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_CAST_R(r, tag_ns, arg) \ , BOOST_PARAMETER_FUNCTION_CAST_T( \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ , BOOST_PARAMETER_FN_ARG_PRED(arg) \ , Args \ )( \ args[ \ ::boost::parameter::keyword< \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ >::instance \ ] \ ) /**/ #endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING // Takes in the arg tuple (name, pred, default) and the tag namespace. // Extracts the corresponding optional argument from the pack if specified, // otherwise temporarily passes use_default_tag() to the dispatch functions. #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) // The boost::parameter::aux::forward wrapper is necessary to transmit the // target type to the next dispatch function. Otherwise, the argument will // retain its original type. -- Cromwell D. Enage #define BOOST_PARAMETER_FUNCTION_DISPATCH_OPT_ARG_CAST(arg, tag_ns) \ ::boost::parameter::aux::forward< \ BOOST_PARAMETER_FUNCTION_CAST_T( \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ , BOOST_PARAMETER_FN_ARG_PRED(arg) \ , Args \ ) \ , BOOST_PARAMETER_FUNCTION_CAST_B( \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ , BOOST_PARAMETER_FN_ARG_PRED(arg) \ , Args \ ) \ >( \ args[ \ ::boost::parameter::keyword< \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ >::instance || ::boost::parameter::aux::use_default_tag() \ ] \ ) /**/ #else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) #define BOOST_PARAMETER_FUNCTION_DISPATCH_OPT_ARG_CAST(arg, tag_ns) \ BOOST_PARAMETER_FUNCTION_CAST_B( \ args[ \ ::boost::parameter::keyword< \ tag_ns::BOOST_PARAMETER_FN_ARG_NAME(arg) \ >::instance || ::boost::parameter::aux::use_default_tag() \ ] \ , BOOST_PARAMETER_FN_ARG_PRED(arg) \ , Args \ ) /**/ #endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING #include // Expands to three dispatch functions that take in all required parameters // and the first n optional parameters. The third dispatch function bears // the same name as the first but takes in use_default_tag as the last // parameter. The second dispatch function bears a different name from the // other two. // // x is a tuple: // // (name, split_args, is_const, tag_namespace) // // Where name is the base name of the functions, and split_args is a tuple: // // (required_count, required_args, optional_count, required_args) // // The first dispatch function queries args if it has bound the (n + 1)th // optional parameter to a user-defined argument. If so, then it forwards // its own arguments followed by the user-defined argument to the dispatch // function that takes in all required parameters and the first (n + 1) // optional parameters, but not use_default_tag. Otherwise, it forwards // its own arguments to the third dispatch function. // // The third dispatch function appends the default value of the (n + 1)th // optional parameter to its copy of args. Then it forwards this copy, all // required parameters, and the first n (not n + 1) optional parameters to // the second dispatch function. // // The second dispatch function forwards its arguments, then the (n + 1)th // optional parameter that it extracts from args, to the other-named dispatch // function that takes in all required parameters and the first (n + 1) // optional parameters, but not use_default_tag. #define BOOST_PARAMETER_FUNCTION_DISPATCH_OVERLOAD_Z(z, n, x) \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 0) \ { \ return BOOST_PP_EXPR_IF( \ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \ , this-> \ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 0)( \ static_cast(BOOST_PARAMETER_AUX_PP_NULLPTR) \ , args \ , 0L \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD \ , n \ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_OPT_ARG_CAST( \ BOOST_PP_SEQ_ELEM( \ n \ , BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ ) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x) \ ) \ ); \ } \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 1, 0) \ { \ return BOOST_PP_EXPR_IF( \ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \ , this-> \ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 0)( \ static_cast(BOOST_PARAMETER_AUX_PP_NULLPTR) \ , args \ , 0L \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD \ , n \ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ , args[ \ ::boost::parameter::keyword< \ BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x):: \ BOOST_PARAMETER_FN_ARG_NAME( \ BOOST_PP_SEQ_ELEM( \ n \ , BOOST_PARAMETER_SPLIT_ARG_OPT_SEQ( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ ) \ ) \ >::instance \ ] \ ); \ } \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL(n, x) \ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN(n, x, 0, 1) \ { \ return BOOST_PP_EXPR_IF( \ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \ , this-> \ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 1)( \ static_cast(BOOST_PARAMETER_AUX_PP_NULLPTR) \ , (args \ , BOOST_PARAMETER_FUNCTION_DISPATCH_DEFAULT( \ n \ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x) \ ) \ ) \ , 0L \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_REPEAT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_FWD \ , n \ , BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ ); \ } /**/ #include #include #include #include // x is a tuple: // // (base_name, split_args, is_member, is_const, tag_namespace) // // Generates all dispatch functions for the function named base_name. Each // dispatch function that takes in n optional parameters passes the default // value of the (n + 1)th optional parameter to the next dispatch function. // The last dispatch function is the back-end implementation, so only the // header is generated: the user is expected to supply the body. // // Also generates the front-end implementation function, which uses // BOOST_PARAMETER_FUNCTION_CAST to extract each argument from the argument // pack. #define BOOST_PARAMETER_FUNCTION_DISPATCH_LAYER(fwd_decl, x) \ BOOST_PP_IF(fwd_decl, BOOST_PP_REPEAT_FROM_TO, BOOST_PP_TUPLE_EAT(4))( \ 0 \ , BOOST_PP_INC( \ BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ ) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_0_Z \ , x \ ) \ BOOST_PP_IF(fwd_decl, BOOST_PP_REPEAT_FROM_TO, BOOST_PP_TUPLE_EAT(4))( \ 0 \ , BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_FWD_DECL_1_Z \ , x \ ) \ template BOOST_PARAMETER_MEMBER_FUNCTION_STATIC( \ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \ ) inline typename BOOST_PARAMETER_FUNCTION_RESULT_NAME( \ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \ )::type BOOST_PARAMETER_FUNCTION_IMPL_NAME( \ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \ )(Args const& args) \ BOOST_PP_EXPR_IF(BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x), const) \ { \ return BOOST_PP_EXPR_IF( \ BOOST_PARAMETER_FUNCTION_DISPATCH_IS_MEMBER(x) \ , this-> \ ) BOOST_PARAMETER_FUNCTION_DISPATCH_NAME(x, 0)( \ static_cast< \ typename BOOST_PARAMETER_FUNCTION_RESULT_NAME( \ BOOST_PARAMETER_FUNCTION_DISPATCH_BASE_NAME(x) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_IS_CONST(x) \ )::type(*)() \ >(BOOST_PARAMETER_AUX_PP_NULLPTR) \ , args \ , 0L \ BOOST_PP_SEQ_FOR_EACH( \ BOOST_PARAMETER_FUNCTION_DISPATCH_ARG_CAST_R \ , BOOST_PARAMETER_FUNCTION_DISPATCH_TAG_NAMESPACE(x) \ , BOOST_PARAMETER_SPLIT_ARG_REQ_SEQ( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ ) \ ); \ } \ BOOST_PP_REPEAT_FROM_TO( \ 0 \ , BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ , BOOST_PARAMETER_FUNCTION_DISPATCH_OVERLOAD_Z \ , x \ ) \ BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_TPL( \ BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ , x \ ) \ inline BOOST_PARAMETER_FUNCTION_DISPATCH_HEAD_PRN( \ BOOST_PARAMETER_SPLIT_ARG_OPT_COUNT( \ BOOST_PARAMETER_FUNCTION_DISPATCH_SPLIT_ARGS(x) \ ) \ , x \ , 0 \ , 0 \ ) /**/ #endif // include guard