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