parameters.hpp
来自「support vector clustering for vc++」· HPP 代码 · 共 932 行 · 第 1/2 页
HPP
932 行
// 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
>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?