1 // Copyright David Abrahams, Daniel Wallin 2003. Use, modification and
2 // distribution is subject to the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef BOOST_PARAMETERS_031014_HPP
7 #define BOOST_PARAMETERS_031014_HPP
9 #include <boost/detail/is_xxx.hpp>
11 #include <boost/mpl/lambda.hpp>
12 #include <boost/mpl/apply.hpp>
13 #include <boost/mpl/always.hpp>
14 #include <boost/mpl/and.hpp>
15 #include <boost/mpl/or.hpp>
16 #include <boost/mpl/if.hpp>
17 #include <boost/mpl/identity.hpp>
18 #include <boost/mpl/not.hpp>
19 #include <boost/mpl/eval_if.hpp>
21 #include <boost/type_traits/is_same.hpp>
22 #include <boost/type_traits/remove_reference.hpp>
24 #include <boost/preprocessor/repetition/enum.hpp>
25 #include <boost/preprocessor/repetition/enum_params.hpp>
26 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
27 #include <boost/preprocessor/arithmetic/sub.hpp>
28 #include <boost/preprocessor/repetition/enum_shifted.hpp>
29 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
30 #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
31 #include <boost/preprocessor/seq/elem.hpp>
32 #include <boost/preprocessor/iteration/iterate.hpp>
33 #include <boost/preprocessor/facilities/intercept.hpp>
34 #include <boost/preprocessor/cat.hpp>
36 #include <boost/parameter/aux_/arg_list.hpp>
37 #include <boost/parameter/aux_/yesno.hpp>
38 #include <boost/parameter/aux_/void.hpp>
39 #include <boost/parameter/aux_/default.hpp>
40 #include <boost/parameter/aux_/unwrap_cv_reference.hpp>
41 #include <boost/parameter/aux_/tagged_argument.hpp>
42 #include <boost/parameter/aux_/tag.hpp>
43 #include <boost/parameter/config.hpp>
48 template<class T> class reference_wrapper;
52 namespace aux { struct use_default {}; }
54 // These templates can be used to describe the treatment of particular
55 // named parameters for the purposes of overload elimination with
56 // SFINAE, by placing specializations in the parameters<...> list. In
57 // order for a treated function to participate in overload resolution:
59 // - all keyword tags wrapped in required<...> must have a matching
62 // - The actual argument type matched by every keyword tag
63 // associated with a predicate must satisfy that predicate
65 // If a keyword k is specified without an optional<...> or
66 // required<...>, wrapper, it is treated as though optional<k> were
69 template <class Tag, class Predicate = aux::use_default>
73 typedef Predicate predicate;
76 template <class Tag, class Predicate = aux::use_default>
80 typedef Predicate predicate;
91 // Defines metafunctions, is_required and is_optional, that
92 // identify required<...> and optional<...> specializations.
93 BOOST_DETAIL_IS_XXX_DEF(required, required, 2)
94 BOOST_DETAIL_IS_XXX_DEF(optional, optional, 2)
97 // key_type, has_default, and predicate --
99 // These metafunctions accept a ParameterSpec and extract the
100 // keyword tag, whether or not a default is supplied for the
101 // parameter, and the predicate that the corresponding actual
102 // argument type is required match.
104 // a ParameterSpec is a specialization of either keyword<...>,
105 // required<...> or optional<...>.
108 // helper for key_type<...>, below.
111 { typedef typename T::key_type type; };
128 : mpl::not_<typename is_required<T>::type>
132 // helper for get_predicate<...>, below
134 struct get_predicate_or_default
140 struct get_predicate_or_default<use_default>
142 typedef mpl::always<mpl::true_> type;
145 // helper for predicate<...>, below
150 get_predicate_or_default<typename T::predicate>::type
162 , mpl::identity<mpl::always<mpl::true_> >
168 // Converts a ParameterSpec into a specialization of
169 // parameter_requirements. We need to do this in order to get the
170 // key_type into the type in a way that can be conveniently matched
171 // by a satisfies(...) member function in arg_list.
172 template <class ParameterSpec>
173 struct as_parameter_requirements
175 typedef parameter_requirements<
176 typename key_type<ParameterSpec>::type
177 , typename predicate<ParameterSpec>::type
178 , typename has_default<ParameterSpec>::type
182 // Labels Arg with default keyword tag DefaultTag if it is not
183 // already a tagged_argument
184 template <class DefaultTag, class Arg>
185 struct as_tagged_argument
187 is_tagged_argument<Arg>
189 , tag<typename key_type<DefaultTag>::type, Arg const>
193 #if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // ETI workaround
195 struct as_tagged_argument<int,int>
201 // Returns mpl::true_ iff the given ParameterRequirements are
202 // satisfied by ArgList.
203 template <class ArgList, class ParameterRequirements>
206 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
207 // VC7.1 can't handle the sizeof() implementation below,
208 // so we use this instead.
209 typedef typename mpl::apply_wrap2<
210 typename ArgList::binding
211 , typename ParameterRequirements::keyword
215 typedef typename mpl::eval_if<
216 is_same<bound, void_>
217 , typename ParameterRequirements::has_default
219 typename ParameterRequirements::predicate
220 , typename remove_reference<bound>::type
224 BOOST_STATIC_CONSTANT(
228 ArgList::satisfies((ParameterRequirements*)0)
234 typedef mpl::bool_<satisfies::value> type;
238 // Returns mpl::true_ if the requirements of the given ParameterSpec
239 // are satisfied by ArgList.
240 template <class ArgList, class ParameterSpec>
241 struct satisfies_requirements_of
244 , typename as_parameter_requirements<ParameterSpec>::type
248 // Helper for make_partial_arg_list, below. Produce an arg_list
249 // node for the given ParameterSpec and ArgumentType, whose tail is
250 // determined by invoking the nullary metafunction TailFn.
251 template <class ParameterSpec, class ArgumentType, class TailFn>
255 typename as_tagged_argument<ParameterSpec,ArgumentType>::type
256 , typename TailFn::type
260 // Just like make_arg_list, except if ArgumentType is void_, the
261 // result is empty_arg_list. Used to build arg_lists whose length
262 // depends on the number of non-default (void_) arguments passed to
269 struct make_partial_arg_list
271 is_same<ArgumentType,void_>
272 , mpl::identity<empty_arg_list>
273 , make_arg_list<ParameterSpec, ArgumentType, TailFn>
280 // parameter_spec#0, argument_type#0
282 // parameter_spec#1, argument_type#1
283 // , ... mpl::identity<aux::empty_arg_list>
286 #define BOOST_PARAMETER_make_arg_list(z, n, names) \
287 BOOST_PP_SEQ_ELEM(0,names)< \
288 BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n), \
289 BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,names), n),
291 #define BOOST_PARAMETER_right_angle(z, n, text) >
293 #define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type) \
295 n, BOOST_PARAMETER_make_arg_list, (make)(parameter_spec)(argument_type)) \
296 mpl::identity<aux::empty_arg_list> \
297 BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)
301 #define BOOST_PARAMETER_TEMPLATE_ARGS(z, n, text) class BOOST_PP_CAT(PS, n) = aux::void_
305 , BOOST_PP_ENUM_SHIFTED(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_TEMPLATE_ARGS, _)
309 #undef BOOST_PARAMETER_TEMPLATE_ARGS
311 // if the elements of NamedList match the criteria of overload
312 // resolution, returns a type which can be constructed from
313 // parameters. Otherwise, this is not a valid metafunction (no nested
317 #ifndef BOOST_NO_SFINAE
318 // If NamedList satisfies the PS0, PS1, ..., this is a
319 // metafunction returning parameters. Otherwise it
320 // has no nested ::type.
321 template <class NamedList>
325 // aux::satisfies_requirements_of<NamedList,PS0>
327 // aux::satisfies_requirements_of<NamedList,PS1>...
331 # define BOOST_PARAMETER_satisfies(z, n, text) \
333 aux::satisfies_requirements_of<NamedList, BOOST_PP_CAT(PS, n)> ,
335 BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_satisfies, _)
337 BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_right_angle, _)
339 # undef BOOST_PARAMETER_satisfies
341 , mpl::identity<parameters>
347 // Specializations are to be used as an optional argument to
348 // eliminate overloads via SFINAE
350 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
351 // Borland simply can't handle default arguments in member
352 // class templates. People wishing to write portable code can
353 // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments
354 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)
356 BOOST_PP_ENUM_BINARY_PARAMS(
357 BOOST_PARAMETER_MAX_ARITY, class A, = aux::void_ BOOST_PP_INTERCEPT
362 # ifndef BOOST_NO_SFINAE
364 typename BOOST_PARAMETER_build_arg_list(
365 BOOST_PARAMETER_MAX_ARITY, aux::make_partial_arg_list, PS, A
372 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
378 // The function call operator is used to build an arg_list that
379 // labels the positional parameters and maintains whatever other
380 // tags may have been specified by the caller.
382 aux::empty_arg_list operator()() const
384 return aux::empty_arg_list();
389 aux::make_arg_list<PS0,A0, mpl::identity<aux::empty_arg_list> >
391 operator()( A0 const& a0) const
394 aux::make_arg_list<PS0, A0, mpl::identity<aux::empty_arg_list> >
399 // , void_(), void_(), void_() ...
400 BOOST_PP_ENUM_TRAILING_PARAMS(
401 BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 1)
402 , aux::void_() BOOST_PP_INTERCEPT)
406 template<class A0, class A1>
410 , aux::make_arg_list<
412 , mpl::identity<aux::empty_arg_list>
416 operator()(A0 const& a0, A1 const& a1) const
421 , aux::make_arg_list<
423 , mpl::identity<aux::empty_arg_list>
431 // , void_(), void_() ...
432 BOOST_PP_ENUM_TRAILING_PARAMS(
433 BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 2)
434 , aux::void_() BOOST_PP_INTERCEPT)
438 // Higher arities are handled by the preprocessor
439 #define BOOST_PP_ITERATION_PARAMS_1 (3,( \
440 3,BOOST_PARAMETER_MAX_ARITY,<boost/parameter/aux_/overloads.hpp> \
442 #include BOOST_PP_ITERATE()
444 #undef BOOST_PARAMETER_build_arg_list
445 #undef BOOST_PARAMETER_make_arg_list
446 #undef BOOST_PARAMETER_right_angle
450 } // namespace parameter
454 #endif // BOOST_PARAMETERS_031014_HPP