You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
931 lines
26 KiB
931 lines
26 KiB
// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and |
|
// distribution is subject to 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/detail/is_xxx.hpp> |
|
|
|
#include <boost/type_traits/is_const.hpp> |
|
|
|
#include <boost/mpl/lambda.hpp> |
|
#include <boost/mpl/apply.hpp> |
|
#include <boost/mpl/always.hpp> |
|
#include <boost/mpl/and.hpp> |
|
#include <boost/mpl/or.hpp> |
|
#include <boost/mpl/if.hpp> |
|
#include <boost/mpl/identity.hpp> |
|
#include <boost/mpl/not.hpp> |
|
#include <boost/mpl/eval_if.hpp> |
|
#include <boost/mpl/pair.hpp> |
|
|
|
#include <boost/type_traits/is_same.hpp> |
|
#include <boost/type_traits/remove_reference.hpp> |
|
|
|
#include <boost/preprocessor/repetition/enum.hpp> |
|
#include <boost/preprocessor/repetition/enum_params.hpp> |
|
#include <boost/preprocessor/repetition/enum_trailing_params.hpp> |
|
#include <boost/preprocessor/arithmetic/sub.hpp> |
|
#include <boost/preprocessor/repetition/repeat.hpp> |
|
#include <boost/preprocessor/repetition/enum_shifted.hpp> |
|
#include <boost/preprocessor/repetition/enum_binary_params.hpp> |
|
#include <boost/preprocessor/repetition/enum_shifted_params.hpp> |
|
#include <boost/preprocessor/seq/elem.hpp> |
|
#include <boost/preprocessor/iteration/iterate.hpp> |
|
#include <boost/preprocessor/facilities/intercept.hpp> |
|
#include <boost/preprocessor/cat.hpp> |
|
|
|
#include <boost/parameter/aux_/arg_list.hpp> |
|
#include <boost/parameter/aux_/yesno.hpp> |
|
#include <boost/parameter/aux_/void.hpp> |
|
#include <boost/parameter/aux_/default.hpp> |
|
#include <boost/parameter/aux_/unwrap_cv_reference.hpp> |
|
#include <boost/parameter/aux_/tagged_argument.hpp> |
|
#include <boost/parameter/aux_/tag.hpp> |
|
#include <boost/parameter/aux_/template_keyword.hpp> |
|
#include <boost/parameter/aux_/set.hpp> |
|
#include <boost/parameter/config.hpp> |
|
|
|
namespace parameter_ |
|
{ |
|
template <class T> |
|
struct unmatched_argument |
|
{ |
|
BOOST_MPL_ASSERT((boost::is_same<T,void>)); |
|
typedef int type; |
|
}; |
|
} // namespace parameter_ |
|
|
|
namespace boost { |
|
|
|
template<class T> class reference_wrapper; |
|
|
|
namespace parameter { |
|
|
|
namespace aux { struct use_default {}; } |
|
|
|
// These templates can be used to describe the treatment of particular |
|
// named parameters for the purposes of overload elimination with |
|
// SFINAE, by placing specializations in the parameters<...> list. In |
|
// order for a treated function to participate in overload resolution: |
|
// |
|
// - all keyword tags wrapped in required<...> must have a matching |
|
// actual argument |
|
// |
|
// - The actual argument type matched by every keyword tag |
|
// associated with a predicate must satisfy that predicate |
|
// |
|
// If a keyword k is specified without an optional<...> or |
|
// required<...>, wrapper, it is treated as though optional<k> were |
|
// specified. |
|
// |
|
// If a keyword k is specified with deduced<...>, that keyword |
|
// will be automatically deduced from the argument list. |
|
// |
|
template <class Tag, class Predicate = aux::use_default> |
|
struct required |
|
{ |
|
typedef Tag key_type; |
|
typedef Predicate predicate; |
|
}; |
|
|
|
template <class Tag, class Predicate = aux::use_default> |
|
struct optional |
|
{ |
|
typedef Tag key_type; |
|
typedef Predicate predicate; |
|
}; |
|
|
|
template <class Tag> |
|
struct deduced |
|
{ |
|
typedef Tag key_type; |
|
}; |
|
|
|
namespace aux |
|
{ |
|
// Defines metafunctions, is_required and is_optional, that |
|
// identify required<...>, optional<...> and deduced<...> specializations. |
|
BOOST_DETAIL_IS_XXX_DEF(required, required, 2) |
|
BOOST_DETAIL_IS_XXX_DEF(optional, optional, 2) |
|
BOOST_DETAIL_IS_XXX_DEF(deduced_aux, deduced, 1) |
|
|
|
template <class S> |
|
struct is_deduced0 |
|
: is_deduced_aux< |
|
typename S::key_type |
|
>::type |
|
{}; |
|
|
|
template <class S> |
|
struct is_deduced |
|
: mpl::eval_if< |
|
mpl::or_< |
|
is_optional<S>, is_required<S> |
|
> |
|
, is_deduced0<S> |
|
, mpl::false_ |
|
>::type |
|
{}; |
|
|
|
// |
|
// key_type, has_default, and predicate -- |
|
// |
|
// These metafunctions accept a ParameterSpec and extract the |
|
// keyword tag, whether or not a default is supplied for the |
|
// parameter, and the predicate that the corresponding actual |
|
// argument type is required match. |
|
// |
|
// a ParameterSpec is a specialization of either keyword<...>, |
|
// required<...>, optional<...> |
|
// |
|
|
|
// helper for key_type<...>, below. |
|
template <class T> |
|
struct get_tag_type0 |
|
{ |
|
typedef typename T::key_type type; |
|
}; |
|
|
|
template <class T> |
|
struct get_tag_type |
|
: mpl::eval_if< |
|
is_deduced_aux<typename T::key_type> |
|
, get_tag_type0<typename T::key_type> |
|
, mpl::identity<typename T::key_type> |
|
> |
|
{}; |
|
|
|
template <class T> |
|
struct tag_type |
|
: mpl::eval_if< |
|
mpl::or_< |
|
is_optional<T> |
|
, is_required<T> |
|
> |
|
, get_tag_type<T> |
|
, mpl::identity<T> |
|
> |
|
{}; |
|
|
|
template <class T> |
|
struct has_default |
|
: mpl::not_<is_required<T> > |
|
{}; |
|
|
|
// helper for get_predicate<...>, below |
|
template <class T> |
|
struct get_predicate_or_default |
|
{ |
|
typedef T type; |
|
}; |
|
|
|
template <> |
|
struct get_predicate_or_default<use_default> |
|
{ |
|
typedef mpl::always<mpl::true_> type; |
|
}; |
|
|
|
// helper for predicate<...>, below |
|
template <class T> |
|
struct get_predicate |
|
{ |
|
typedef typename |
|
get_predicate_or_default<typename T::predicate>::type |
|
type; |
|
}; |
|
|
|
template <class T> |
|
struct predicate |
|
: mpl::eval_if< |
|
mpl::or_< |
|
is_optional<T> |
|
, is_required<T> |
|
> |
|
, get_predicate<T> |
|
, mpl::identity<mpl::always<mpl::true_> > |
|
> |
|
{ |
|
}; |
|
|
|
|
|
// Converts a ParameterSpec into a specialization of |
|
// parameter_requirements. We need to do this in order to get the |
|
// tag_type into the type in a way that can be conveniently matched |
|
// by a satisfies(...) member function in arg_list. |
|
template <class ParameterSpec> |
|
struct as_parameter_requirements |
|
{ |
|
typedef parameter_requirements< |
|
typename tag_type<ParameterSpec>::type |
|
, typename predicate<ParameterSpec>::type |
|
, typename has_default<ParameterSpec>::type |
|
> type; |
|
}; |
|
|
|
template <class T> |
|
struct is_named_argument |
|
: mpl::or_< |
|
is_template_keyword<T> |
|
, is_tagged_argument<T> |
|
> |
|
{}; |
|
|
|
// Returns mpl::true_ iff the given ParameterRequirements are |
|
// satisfied by ArgList. |
|
template <class ArgList, class ParameterRequirements> |
|
struct satisfies |
|
{ |
|
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310) |
|
// VC7.1 can't handle the sizeof() implementation below, |
|
// so we use this instead. |
|
typedef typename mpl::apply_wrap3< |
|
typename ArgList::binding |
|
, typename ParameterRequirements::keyword |
|
, void_ |
|
, mpl::false_ |
|
>::type bound; |
|
|
|
typedef typename mpl::eval_if< |
|
is_same<bound, void_> |
|
, typename ParameterRequirements::has_default |
|
, mpl::apply_wrap2< |
|
typename mpl::lambda< |
|
typename ParameterRequirements::predicate, lambda_tag |
|
>::type |
|
, bound |
|
, ArgList |
|
> |
|
>::type type; |
|
#else |
|
BOOST_STATIC_CONSTANT( |
|
bool, value = ( |
|
sizeof( |
|
aux::to_yesno( |
|
ArgList::satisfies((ParameterRequirements*)0, (ArgList*)0) |
|
) |
|
) == sizeof(yes_tag) |
|
) |
|
); |
|
|
|
typedef mpl::bool_<satisfies::value> type; |
|
#endif |
|
}; |
|
|
|
// Returns mpl::true_ if the requirements of the given ParameterSpec |
|
// are satisfied by ArgList. |
|
template <class ArgList, class ParameterSpec> |
|
struct satisfies_requirements_of |
|
: satisfies< |
|
ArgList |
|
, typename as_parameter_requirements<ParameterSpec>::type |
|
> |
|
{}; |
|
|
|
// Tags a deduced argument Arg with the keyword tag of Spec using TagFn. |
|
// Returns the tagged argument and the mpl::set<> UsedArgs with the |
|
// tag of Spec inserted. |
|
template <class UsedArgs, class Spec, class Arg, class TagFn> |
|
struct tag_deduced |
|
{ |
|
typedef mpl::pair< |
|
typename mpl::apply_wrap2<TagFn, typename tag_type<Spec>::type, Arg>::type |
|
, typename aux::insert_<UsedArgs, typename tag_type<Spec>::type>::type |
|
> type; |
|
}; |
|
|
|
template < |
|
class Argument |
|
, class ArgumentPack |
|
, class DeducedArgs |
|
, class UsedArgs |
|
, class TagFn |
|
> |
|
struct deduce_tag; |
|
|
|
// Tag type passed to MPL lambda. |
|
struct lambda_tag; |
|
|
|
// Helper for deduce_tag<> below. |
|
template < |
|
class Argument |
|
, class ArgumentPack |
|
, class DeducedArgs |
|
, class UsedArgs |
|
, class TagFn |
|
> |
|
struct deduce_tag0 |
|
{ |
|
typedef typename DeducedArgs::spec spec; |
|
|
|
typedef typename mpl::apply_wrap2< |
|
typename mpl::lambda< |
|
typename spec::predicate, lambda_tag |
|
>::type |
|
, Argument |
|
, ArgumentPack |
|
>::type condition; |
|
|
|
// Deduced parameter matches several arguments. |
|
|
|
BOOST_MPL_ASSERT(( |
|
mpl::not_<mpl::and_< |
|
condition |
|
, aux::has_key_<UsedArgs, typename tag_type<spec>::type> |
|
> > |
|
)); |
|
|
|
typedef typename mpl::eval_if< |
|
condition |
|
, tag_deduced<UsedArgs, spec, Argument, TagFn> |
|
, deduce_tag<Argument, ArgumentPack, typename DeducedArgs::tail, UsedArgs, TagFn> |
|
>::type type; |
|
}; |
|
|
|
// Tries to deduced a keyword tag for a given Argument. |
|
// Returns an mpl::pair<> consisting of the tagged_argument<>, |
|
// and an mpl::set<> where the new tag has been inserted. |
|
// |
|
// Argument: The argument type to be tagged. |
|
// |
|
// ArgumentPack: The ArgumentPack built so far. |
|
// |
|
// DeducedArgs: A specialization of deduced_item<> (see below). |
|
// A list containing only the deduced ParameterSpecs. |
|
// |
|
// UsedArgs: An mpl::set<> containing the keyword tags used so far. |
|
// |
|
// TagFn: A metafunction class used to tag positional or deduced |
|
// arguments with a keyword tag. |
|
|
|
template < |
|
class Argument |
|
, class ArgumentPack |
|
, class DeducedArgs |
|
, class UsedArgs |
|
, class TagFn |
|
> |
|
struct deduce_tag |
|
{ |
|
typedef typename mpl::eval_if< |
|
is_same<DeducedArgs, void_> |
|
, mpl::pair<void_, UsedArgs> |
|
, deduce_tag0<Argument, ArgumentPack, DeducedArgs, UsedArgs, TagFn> |
|
>::type type; |
|
}; |
|
|
|
template < |
|
class List |
|
, class DeducedArgs |
|
, class TagFn |
|
, class Positional |
|
, class UsedArgs |
|
, class ArgumentPack |
|
, class Error |
|
> |
|
struct make_arg_list_aux; |
|
|
|
// Inserts Tagged::key_type into the UserArgs set. |
|
// Extra indirection to lazily evaluate Tagged::key_type. |
|
template <class UsedArgs, class Tagged> |
|
struct insert_tagged |
|
{ |
|
typedef typename aux::insert_< |
|
UsedArgs, typename Tagged::key_type |
|
>::type type; |
|
}; |
|
|
|
// Borland needs the insane extra-indirection workaround below |
|
// so that it doesn't magically drop the const qualifier from |
|
// the argument type. |
|
|
|
template < |
|
class List |
|
, class DeducedArgs |
|
, class TagFn |
|
, class Positional |
|
, class UsedArgs |
|
, class ArgumentPack |
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
|
, class argument |
|
#endif |
|
, class Error |
|
> |
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
|
struct make_arg_list00 |
|
#else |
|
struct make_arg_list0 |
|
#endif |
|
{ |
|
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
|
typedef typename List::arg argument; |
|
#endif |
|
typedef typename List::spec parameter_spec; |
|
typedef typename tag_type<parameter_spec>::type tag_; |
|
|
|
typedef is_named_argument<argument> is_tagged; |
|
|
|
// If this argument is either explicitly tagged or a deduced |
|
// parameter, we turn off positional matching. |
|
typedef mpl::and_< |
|
mpl::not_< |
|
mpl::or_<is_deduced<parameter_spec>, is_tagged> |
|
> |
|
, Positional |
|
> positional; |
|
|
|
// If this parameter is explicitly tagged we add it to the |
|
// used-parmeters set. We only really need to add parameters |
|
// that are deduced, but we would need a way to check if |
|
// a given tag corresponds to a deduced parameter spec. |
|
typedef typename mpl::eval_if< |
|
is_tagged |
|
, insert_tagged<UsedArgs, argument> |
|
, mpl::identity<UsedArgs> |
|
>::type used_args; |
|
|
|
// If this parameter is neither explicitly tagged, nor |
|
// positionally matched; deduce the tag from the deduced |
|
// parameter specs. |
|
typedef typename mpl::eval_if< |
|
mpl::or_<is_tagged, positional> |
|
, mpl::pair<void_, used_args> |
|
, deduce_tag<argument, ArgumentPack, DeducedArgs, used_args, TagFn> |
|
>::type deduced_data; |
|
|
|
// If this parameter is explicitly tagged.. |
|
typedef typename mpl::eval_if< |
|
is_tagged |
|
, mpl::identity<argument> // .. just use it |
|
, mpl::eval_if< // .. else, if positional matching is turned on.. |
|
positional |
|
, mpl::apply_wrap2<TagFn, tag_, argument> // .. tag it positionally |
|
, mpl::first<deduced_data> // .. else, use the deduced tag |
|
> |
|
>::type tagged; |
|
|
|
// We build the arg_list incrementally as we go, prepending new |
|
// nodes. |
|
|
|
typedef typename mpl::if_< |
|
mpl::and_< |
|
is_same<Error, void_> |
|
, is_same<tagged, void_> |
|
> |
|
, parameter_::unmatched_argument<argument> |
|
, void_ |
|
>::type error; |
|
|
|
typedef typename mpl::if_< |
|
is_same<tagged, void_> |
|
, ArgumentPack |
|
, arg_list<tagged, ArgumentPack> |
|
>::type argument_pack; |
|
|
|
typedef typename make_arg_list_aux< |
|
typename List::tail |
|
, DeducedArgs |
|
, TagFn |
|
, positional |
|
, typename deduced_data::second |
|
, argument_pack |
|
, error |
|
>::type type; |
|
}; |
|
|
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
|
template < |
|
class List |
|
, class DeducedArgs |
|
, class TagFn |
|
, class Positional |
|
, class UsedArgs |
|
, class ArgumentPack |
|
, class Error |
|
> |
|
struct make_arg_list0 |
|
{ |
|
typedef typename mpl::eval_if< |
|
typename List::is_arg_const |
|
, make_arg_list00< |
|
List |
|
, DeducedArgs |
|
, TagFn |
|
, Positional |
|
, UsedArgs |
|
, ArgumentPack |
|
, typename List::arg const |
|
, Error |
|
> |
|
, make_arg_list00< |
|
List |
|
, DeducedArgs |
|
, TagFn |
|
, Positional |
|
, UsedArgs |
|
, ArgumentPack |
|
, typename List::arg |
|
, Error |
|
> |
|
>::type type; |
|
}; |
|
#endif |
|
|
|
// Returns an ArgumentPack where the list of arguments has |
|
// been tagged with keyword tags. |
|
// |
|
// List: A specialization of item<> (see below). Contains |
|
// both the ordered ParameterSpecs, and the given arguments. |
|
// |
|
// DeducedArgs: A specialization of deduced_item<> (see below). |
|
// A list containing only the deduced ParameterSpecs. |
|
// |
|
// TagFn: A metafunction class used to tag positional or deduced |
|
// arguments with a keyword tag. |
|
// |
|
// Position: An mpl::bool_<> specialization indicating if positional |
|
// matching is to be performed. |
|
// |
|
// DeducedSet: An mpl::set<> containing the keyword tags used so far. |
|
// |
|
// ArgumentPack: The ArgumentPack built so far. This is initially an |
|
// empty_arg_list and is built incrementally. |
|
// |
|
|
|
template < |
|
class List |
|
, class DeducedArgs |
|
, class TagFn |
|
, class Positional |
|
, class DeducedSet |
|
, class ArgumentPack |
|
, class Error |
|
> |
|
struct make_arg_list_aux |
|
{ |
|
typedef typename mpl::eval_if< |
|
is_same<List, void_> |
|
, mpl::identity<mpl::pair<ArgumentPack, Error> > |
|
, make_arg_list0<List, DeducedArgs, TagFn, Positional, DeducedSet, ArgumentPack, Error> |
|
>::type type; |
|
}; |
|
|
|
// VC6.5 was choking on the default parameters for make_arg_list_aux, so |
|
// this just forwards to that adding in the defaults. |
|
template < |
|
class List |
|
, class DeducedArgs |
|
, class TagFn |
|
, class EmitErrors = mpl::true_ |
|
> |
|
struct make_arg_list |
|
{ |
|
typedef typename make_arg_list_aux< |
|
List, DeducedArgs, TagFn, mpl::true_, aux::set0, empty_arg_list, void_ |
|
>::type type; |
|
}; |
|
|
|
// A parameter spec item typelist. |
|
template <class Spec, class Arg, class Tail = void_> |
|
struct item |
|
{ |
|
typedef Spec spec; |
|
|
|
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
|
typedef is_const<Arg> is_arg_const; |
|
#endif |
|
|
|
typedef Arg arg; |
|
typedef Tail tail; |
|
}; |
|
|
|
template <class Spec, class Arg, class Tail> |
|
struct make_item |
|
{ |
|
typedef item<Spec, Arg, typename Tail::type> type; |
|
}; |
|
|
|
// Creates a item typelist. |
|
template <class Spec, class Arg, class Tail> |
|
struct make_items |
|
{ |
|
typedef typename mpl::eval_if< |
|
is_same<Arg, void_> |
|
, mpl::identity<void_> |
|
, make_item<Spec, Arg, Tail> |
|
>::type type; |
|
}; |
|
|
|
// A typelist that stored deduced parameter specs. |
|
template <class ParameterSpec, class Tail = void_> |
|
struct deduced_item |
|
{ |
|
typedef ParameterSpec spec; |
|
typedef Tail tail; |
|
}; |
|
|
|
// Evaluate Tail and construct deduced_item list. |
|
template <class Spec, class Tail> |
|
struct make_deduced_item |
|
{ |
|
typedef deduced_item<Spec, typename Tail::type> type; |
|
}; |
|
|
|
template <class Spec, class Tail> |
|
struct make_deduced_items |
|
{ |
|
typedef typename mpl::eval_if< |
|
is_same<Spec, void_> |
|
, mpl::identity<void_> |
|
, mpl::eval_if< |
|
is_deduced<Spec> |
|
, make_deduced_item<Spec, Tail> |
|
, Tail |
|
> |
|
>::type type; |
|
}; |
|
|
|
// Generates: |
|
// |
|
// make< |
|
// parameter_spec#0, argument_type#0 |
|
// , make< |
|
// parameter_spec#1, argument_type#1 |
|
// , ... mpl::identity<aux::empty_arg_list> |
|
// ...> |
|
// > |
|
#define BOOST_PARAMETER_make_arg_list(z, n, names) \ |
|
BOOST_PP_SEQ_ELEM(0,names)< \ |
|
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n), \ |
|
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,names), n), |
|
|
|
#define BOOST_PARAMETER_right_angle(z, n, text) > |
|
|
|
#define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type) \ |
|
BOOST_PP_REPEAT( \ |
|
n, BOOST_PARAMETER_make_arg_list, (make)(parameter_spec)(argument_type)) \ |
|
mpl::identity<void_> \ |
|
BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _) |
|
|
|
#define BOOST_PARAMETER_make_deduced_list(z, n, names) \ |
|
BOOST_PP_SEQ_ELEM(0,names)< \ |
|
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n), |
|
|
|
#define BOOST_PARAMETER_build_deduced_list(n, make, parameter_spec) \ |
|
BOOST_PP_REPEAT( \ |
|
n, BOOST_PARAMETER_make_deduced_list, (make)(parameter_spec)) \ |
|
mpl::identity<void_> \ |
|
BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _) |
|
|
|
struct tag_keyword_arg |
|
{ |
|
template <class K, class T> |
|
struct apply |
|
: tag<K,T> |
|
{}; |
|
}; |
|
|
|
struct tag_template_keyword_arg |
|
{ |
|
template <class K, class T> |
|
struct apply |
|
{ |
|
typedef template_keyword<K,T> type; |
|
}; |
|
}; |
|
|
|
} // namespace aux |
|
|
|
#define BOOST_PARAMETER_FORWARD_TYPEDEF(z, i, names) \ |
|
typedef BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0,names),i) BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names),i); |
|
|
|
#define BOOST_PARAMETER_FORWARD_TYPEDEFS(n, src, dest) \ |
|
BOOST_PP_REPEAT(n, BOOST_PARAMETER_FORWARD_TYPEDEF, (src)(dest)) |
|
|
|
|
|
#define BOOST_PARAMETER_TEMPLATE_ARGS(z, n, text) class BOOST_PP_CAT(PS, n) = void_ |
|
|
|
template< |
|
class PS0 |
|
, BOOST_PP_ENUM_SHIFTED(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_TEMPLATE_ARGS, _) |
|
> |
|
struct parameters |
|
{ |
|
#undef BOOST_PARAMETER_TEMPLATE_ARGS |
|
|
|
typedef typename BOOST_PARAMETER_build_deduced_list( |
|
BOOST_PARAMETER_MAX_ARITY, 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(__BORLANDC__, BOOST_TESTED_AT(0x592)) |
|
// If NamedList satisfies the PS0, PS1, ..., this is a |
|
// metafunction returning parameters. Otherwise it |
|
// has no nested ::type. |
|
template <class ArgumentPackAndError> |
|
struct match_base |
|
: mpl::if_< |
|
// mpl::and_< |
|
// aux::satisfies_requirements_of<NamedList,PS0> |
|
// , mpl::and_< |
|
// aux::satisfies_requirements_of<NamedList,PS1>... |
|
// ..., mpl::true_ |
|
// ...> > |
|
|
|
# define BOOST_PARAMETER_satisfies(z, n, text) \ |
|
mpl::and_< \ |
|
aux::satisfies_requirements_of< \ |
|
typename mpl::first<ArgumentPackAndError>::type \ |
|
, BOOST_PP_CAT(PS, n)> \ |
|
, |
|
mpl::and_< |
|
is_same<typename mpl::second<ArgumentPackAndError>::type, void_> |
|
, BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_satisfies, _) |
|
mpl::true_ |
|
BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_right_angle, _) |
|
> |
|
|
|
# undef BOOST_PARAMETER_satisfies |
|
|
|
, mpl::identity<parameters> |
|
, void_ |
|
> |
|
{}; |
|
#endif |
|
|
|
// Specializations are to be used as an optional argument to |
|
// eliminate overloads via SFINAE |
|
template< |
|
#if BOOST_WORKAROUND(__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, class A) |
|
#else |
|
BOOST_PP_ENUM_BINARY_PARAMS( |
|
BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT |
|
) |
|
#endif |
|
> |
|
struct match |
|
# if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) |
|
: match_base< |
|
typename aux::make_arg_list< |
|
typename BOOST_PARAMETER_build_arg_list( |
|
BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A |
|
)::type |
|
, deduced_list |
|
, aux::tag_keyword_arg |
|
, mpl::false_ // Don't emit errors when doing SFINAE |
|
>::type |
|
>::type |
|
{}; |
|
# else |
|
{ |
|
typedef parameters< |
|
BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) |
|
> type; |
|
}; |
|
# endif |
|
|
|
// Metafunction that returns an ArgumentPack. |
|
|
|
// TODO, bind has to instantiate the error type in the result |
|
// of make_arg_list. |
|
|
|
template < |
|
#if BOOST_WORKAROUND(__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, class A) |
|
#else |
|
BOOST_PP_ENUM_BINARY_PARAMS( |
|
BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT |
|
) |
|
#endif |
|
> |
|
struct bind |
|
{ |
|
typedef typename aux::make_arg_list< |
|
typename BOOST_PARAMETER_build_arg_list( |
|
BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A |
|
)::type |
|
, deduced_list |
|
, aux::tag_template_keyword_arg |
|
>::type result; |
|
|
|
typedef typename mpl::first<result>::type type; |
|
}; |
|
|
|
BOOST_PARAMETER_FORWARD_TYPEDEFS(BOOST_PARAMETER_MAX_ARITY, 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<> produces a reversed arg_list, so |
|
// we need to pass the arguments to its constructor |
|
// reversed. |
|
// |
|
aux::empty_arg_list operator()() const |
|
{ |
|
return aux::empty_arg_list(); |
|
} |
|
|
|
template<class A0> |
|
typename mpl::first< |
|
typename aux::make_arg_list< |
|
aux::item< |
|
PS0,A0 |
|
> |
|
, deduced_list |
|
, aux::tag_keyword_arg |
|
>::type |
|
>::type |
|
operator()(A0& a0) const |
|
{ |
|
typedef typename aux::make_arg_list< |
|
aux::item< |
|
PS0,A0 |
|
> |
|
, deduced_list |
|
, aux::tag_keyword_arg |
|
>::type result; |
|
|
|
typedef typename mpl::first<result>::type result_type; |
|
typedef typename mpl::second<result>::type error; |
|
error(); |
|
|
|
return result_type( |
|
a0 |
|
// , void_(), void_(), void_() ... |
|
BOOST_PP_ENUM_TRAILING_PARAMS( |
|
BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 1) |
|
, aux::void_reference() BOOST_PP_INTERCEPT) |
|
); |
|
} |
|
|
|
template<class A0, class A1> |
|
typename mpl::first< |
|
typename aux::make_arg_list< |
|
aux::item< |
|
PS0,A0 |
|
, aux::item< |
|
PS1,A1 |
|
> |
|
> |
|
, deduced_list |
|
, aux::tag_keyword_arg |
|
>::type |
|
>::type |
|
operator()(A0& a0, A1& a1) const |
|
{ |
|
typedef typename aux::make_arg_list< |
|
aux::item< |
|
PS0,A0 |
|
, aux::item< |
|
PS1,A1 |
|
> |
|
> |
|
, deduced_list |
|
, aux::tag_keyword_arg |
|
>::type result; |
|
|
|
typedef typename mpl::first<result>::type result_type; |
|
typedef typename mpl::second<result>::type error; |
|
error(); |
|
|
|
return result_type( |
|
a1,a0 |
|
// , void_(), void_() ... |
|
BOOST_PP_ENUM_TRAILING_PARAMS( |
|
BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 2) |
|
, aux::void_reference() BOOST_PP_INTERCEPT) |
|
); |
|
} |
|
|
|
// Higher arities are handled by the preprocessor |
|
#define BOOST_PP_ITERATION_PARAMS_1 (3,( \ |
|
3,BOOST_PARAMETER_MAX_ARITY,<boost/parameter/aux_/overloads.hpp> \ |
|
)) |
|
#include BOOST_PP_ITERATE() |
|
|
|
}; |
|
|
|
} // namespace parameter |
|
|
|
} // namespace boost |
|
|
|
#endif // BOOST_PARAMETERS_031014_HPP |
|
|
|
|