blob: a45395bdca93be9fe4971c522218f7db466189e7 [file] [log] [blame]
// 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