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)
|
---|
5 |
|
---|
6 | #ifndef BOOST_PARAMETERS_031014_HPP
|
---|
7 | #define BOOST_PARAMETERS_031014_HPP
|
---|
8 |
|
---|
9 | #include <boost/detail/is_xxx.hpp>
|
---|
10 |
|
---|
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>
|
---|
20 |
|
---|
21 | #include <boost/type_traits/is_same.hpp>
|
---|
22 | #include <boost/type_traits/remove_reference.hpp>
|
---|
23 |
|
---|
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>
|
---|
35 |
|
---|
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>
|
---|
44 |
|
---|
45 |
|
---|
46 | namespace boost {
|
---|
47 |
|
---|
48 | template<class T> class reference_wrapper;
|
---|
49 |
|
---|
50 | namespace parameter {
|
---|
51 |
|
---|
52 | namespace aux { struct use_default {}; }
|
---|
53 |
|
---|
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:
|
---|
58 | //
|
---|
59 | // - all keyword tags wrapped in required<...> must have a matching
|
---|
60 | // actual argument
|
---|
61 | //
|
---|
62 | // - The actual argument type matched by every keyword tag
|
---|
63 | // associated with a predicate must satisfy that predicate
|
---|
64 | //
|
---|
65 | // If a keyword k is specified without an optional<...> or
|
---|
66 | // required<...>, wrapper, it is treated as though optional<k> were
|
---|
67 | // specified.
|
---|
68 | //
|
---|
69 | template <class Tag, class Predicate = aux::use_default>
|
---|
70 | struct required
|
---|
71 | {
|
---|
72 | typedef Tag key_type;
|
---|
73 | typedef Predicate predicate;
|
---|
74 | };
|
---|
75 |
|
---|
76 | template <class Tag, class Predicate = aux::use_default>
|
---|
77 | struct optional
|
---|
78 | {
|
---|
79 | typedef Tag key_type;
|
---|
80 | typedef Predicate predicate;
|
---|
81 | };
|
---|
82 |
|
---|
83 | template <class Tag>
|
---|
84 | struct unnamed
|
---|
85 | {
|
---|
86 | typedef Tag key_type;
|
---|
87 | };
|
---|
88 |
|
---|
89 | namespace aux
|
---|
90 | {
|
---|
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)
|
---|
95 |
|
---|
96 | //
|
---|
97 | // key_type, has_default, and predicate --
|
---|
98 | //
|
---|
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.
|
---|
103 | //
|
---|
104 | // a ParameterSpec is a specialization of either keyword<...>,
|
---|
105 | // required<...> or optional<...>.
|
---|
106 | //
|
---|
107 |
|
---|
108 | // helper for key_type<...>, below.
|
---|
109 | template <class T>
|
---|
110 | struct get_key_type
|
---|
111 | { typedef typename T::key_type type; };
|
---|
112 |
|
---|
113 | template <class T>
|
---|
114 | struct key_type
|
---|
115 | : mpl::eval_if<
|
---|
116 | mpl::or_<
|
---|
117 | is_optional<T>
|
---|
118 | , is_required<T>
|
---|
119 | >
|
---|
120 | , get_key_type<T>
|
---|
121 | , mpl::identity<T>
|
---|
122 | >
|
---|
123 | {
|
---|
124 | };
|
---|
125 |
|
---|
126 | template <class T>
|
---|
127 | struct has_default
|
---|
128 | : mpl::not_<typename is_required<T>::type>
|
---|
129 | {
|
---|
130 | };
|
---|
131 |
|
---|
132 | // helper for get_predicate<...>, below
|
---|
133 | template <class T>
|
---|
134 | struct get_predicate_or_default
|
---|
135 | {
|
---|
136 | typedef T type;
|
---|
137 | };
|
---|
138 |
|
---|
139 | template <>
|
---|
140 | struct get_predicate_or_default<use_default>
|
---|
141 | {
|
---|
142 | typedef mpl::always<mpl::true_> type;
|
---|
143 | };
|
---|
144 |
|
---|
145 | // helper for predicate<...>, below
|
---|
146 | template <class T>
|
---|
147 | struct get_predicate
|
---|
148 | {
|
---|
149 | typedef typename
|
---|
150 | get_predicate_or_default<typename T::predicate>::type
|
---|
151 | type;
|
---|
152 | };
|
---|
153 |
|
---|
154 | template <class T>
|
---|
155 | struct predicate
|
---|
156 | : mpl::eval_if<
|
---|
157 | mpl::or_<
|
---|
158 | is_optional<T>
|
---|
159 | , is_required<T>
|
---|
160 | >
|
---|
161 | , get_predicate<T>
|
---|
162 | , mpl::identity<mpl::always<mpl::true_> >
|
---|
163 | >
|
---|
164 | {
|
---|
165 | };
|
---|
166 |
|
---|
167 |
|
---|
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
|
---|
174 | {
|
---|
175 | typedef parameter_requirements<
|
---|
176 | typename key_type<ParameterSpec>::type
|
---|
177 | , typename predicate<ParameterSpec>::type
|
---|
178 | , typename has_default<ParameterSpec>::type
|
---|
179 | > type;
|
---|
180 | };
|
---|
181 |
|
---|
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
|
---|
186 | : mpl::eval_if<
|
---|
187 | is_tagged_argument<Arg>
|
---|
188 | , mpl::identity<Arg>
|
---|
189 | , tag<typename key_type<DefaultTag>::type, Arg const>
|
---|
190 | >
|
---|
191 | {};
|
---|
192 |
|
---|
193 | #if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // ETI workaround
|
---|
194 | template <>
|
---|
195 | struct as_tagged_argument<int,int>
|
---|
196 | {
|
---|
197 | typedef int type;
|
---|
198 | };
|
---|
199 | #endif
|
---|
200 |
|
---|
201 | // Returns mpl::true_ iff the given ParameterRequirements are
|
---|
202 | // satisfied by ArgList.
|
---|
203 | template <class ArgList, class ParameterRequirements>
|
---|
204 | struct satisfies
|
---|
205 | {
|
---|
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
|
---|
212 | , void_
|
---|
213 | >::type bound;
|
---|
214 |
|
---|
215 | typedef typename mpl::eval_if<
|
---|
216 | is_same<bound, void_>
|
---|
217 | , typename ParameterRequirements::has_default
|
---|
218 | , mpl::apply1<
|
---|
219 | typename ParameterRequirements::predicate
|
---|
220 | , typename remove_reference<bound>::type
|
---|
221 | >
|
---|
222 | >::type type;
|
---|
223 | #else
|
---|
224 | BOOST_STATIC_CONSTANT(
|
---|
225 | bool, value = (
|
---|
226 | sizeof(
|
---|
227 | aux::to_yesno(
|
---|
228 | ArgList::satisfies((ParameterRequirements*)0)
|
---|
229 | )
|
---|
230 | ) == sizeof(yes_tag)
|
---|
231 | )
|
---|
232 | );
|
---|
233 |
|
---|
234 | typedef mpl::bool_<satisfies::value> type;
|
---|
235 | #endif
|
---|
236 | };
|
---|
237 |
|
---|
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
|
---|
242 | : satisfies<
|
---|
243 | ArgList
|
---|
244 | , typename as_parameter_requirements<ParameterSpec>::type
|
---|
245 | >
|
---|
246 | {};
|
---|
247 |
|
---|
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>
|
---|
252 | struct make_arg_list
|
---|
253 | {
|
---|
254 | typedef arg_list<
|
---|
255 | typename as_tagged_argument<ParameterSpec,ArgumentType>::type
|
---|
256 | , typename TailFn::type
|
---|
257 | > type;
|
---|
258 | };
|
---|
259 |
|
---|
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
|
---|
263 | // a class template.
|
---|
264 | template <
|
---|
265 | class ParameterSpec
|
---|
266 | , class ArgumentType
|
---|
267 | , class TailFn
|
---|
268 | >
|
---|
269 | struct make_partial_arg_list
|
---|
270 | : mpl::eval_if<
|
---|
271 | is_same<ArgumentType,void_>
|
---|
272 | , mpl::identity<empty_arg_list>
|
---|
273 | , make_arg_list<ParameterSpec, ArgumentType, TailFn>
|
---|
274 | >
|
---|
275 | {};
|
---|
276 |
|
---|
277 | // Generates:
|
---|
278 | //
|
---|
279 | // make<
|
---|
280 | // parameter_spec#0, argument_type#0
|
---|
281 | // , make<
|
---|
282 | // parameter_spec#1, argument_type#1
|
---|
283 | // , ... mpl::identity<aux::empty_arg_list>
|
---|
284 | // ...>
|
---|
285 | // >
|
---|
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),
|
---|
290 |
|
---|
291 | #define BOOST_PARAMETER_right_angle(z, n, text) >
|
---|
292 |
|
---|
293 | #define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type) \
|
---|
294 | BOOST_PP_REPEAT( \
|
---|
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, _)
|
---|
298 |
|
---|
299 | } // namespace aux
|
---|
300 |
|
---|
301 | #define BOOST_PARAMETER_TEMPLATE_ARGS(z, n, text) class BOOST_PP_CAT(PS, n) = aux::void_
|
---|
302 |
|
---|
303 | template<
|
---|
304 | class PS0
|
---|
305 | , BOOST_PP_ENUM_SHIFTED(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_TEMPLATE_ARGS, _)
|
---|
306 | >
|
---|
307 | struct parameters
|
---|
308 | {
|
---|
309 | #undef BOOST_PARAMETER_TEMPLATE_ARGS
|
---|
310 |
|
---|
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
|
---|
314 | // ::type).
|
---|
315 |
|
---|
316 |
|
---|
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>
|
---|
322 | struct match_base
|
---|
323 | : mpl::if_<
|
---|
324 | // mpl::and_<
|
---|
325 | // aux::satisfies_requirements_of<NamedList,PS0>
|
---|
326 | // , mpl::and_<
|
---|
327 | // aux::satisfies_requirements_of<NamedList,PS1>...
|
---|
328 | // ..., mpl::true_
|
---|
329 | // ...> >
|
---|
330 |
|
---|
331 | # define BOOST_PARAMETER_satisfies(z, n, text) \
|
---|
332 | mpl::and_< \
|
---|
333 | aux::satisfies_requirements_of<NamedList, BOOST_PP_CAT(PS, n)> ,
|
---|
334 |
|
---|
335 | BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_satisfies, _)
|
---|
336 | mpl::true_
|
---|
337 | BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_right_angle, _)
|
---|
338 |
|
---|
339 | # undef BOOST_PARAMETER_satisfies
|
---|
340 |
|
---|
341 | , mpl::identity<parameters>
|
---|
342 | , aux::void_
|
---|
343 | >
|
---|
344 | {};
|
---|
345 | #endif
|
---|
346 |
|
---|
347 | // Specializations are to be used as an optional argument to
|
---|
348 | // eliminate overloads via SFINAE
|
---|
349 | template<
|
---|
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)
|
---|
355 | #else
|
---|
356 | BOOST_PP_ENUM_BINARY_PARAMS(
|
---|
357 | BOOST_PARAMETER_MAX_ARITY, class A, = aux::void_ BOOST_PP_INTERCEPT
|
---|
358 | )
|
---|
359 | #endif
|
---|
360 | >
|
---|
361 | struct match
|
---|
362 | # ifndef BOOST_NO_SFINAE
|
---|
363 | : match_base<
|
---|
364 | typename BOOST_PARAMETER_build_arg_list(
|
---|
365 | BOOST_PARAMETER_MAX_ARITY, aux::make_partial_arg_list, PS, A
|
---|
366 | )::type
|
---|
367 | >::type
|
---|
368 | {};
|
---|
369 | # else
|
---|
370 | {
|
---|
371 | typedef parameters<
|
---|
372 | BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
|
---|
373 | > type;
|
---|
374 | };
|
---|
375 | # endif
|
---|
376 |
|
---|
377 | //
|
---|
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.
|
---|
381 | //
|
---|
382 | aux::empty_arg_list operator()() const
|
---|
383 | {
|
---|
384 | return aux::empty_arg_list();
|
---|
385 | }
|
---|
386 |
|
---|
387 | template<class A0>
|
---|
388 | typename
|
---|
389 | aux::make_arg_list<PS0,A0, mpl::identity<aux::empty_arg_list> >
|
---|
390 | ::type
|
---|
391 | operator()( A0 const& a0) const
|
---|
392 | {
|
---|
393 | typedef typename
|
---|
394 | aux::make_arg_list<PS0, A0, mpl::identity<aux::empty_arg_list> >
|
---|
395 | ::type result_type;
|
---|
396 |
|
---|
397 | return result_type(
|
---|
398 | a0
|
---|
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)
|
---|
403 | );
|
---|
404 | }
|
---|
405 |
|
---|
406 | template<class A0, class A1>
|
---|
407 | typename
|
---|
408 | aux::make_arg_list<
|
---|
409 | PS0,A0
|
---|
410 | , aux::make_arg_list<
|
---|
411 | PS1,A1
|
---|
412 | , mpl::identity<aux::empty_arg_list>
|
---|
413 | >
|
---|
414 | >
|
---|
415 | ::type
|
---|
416 | operator()(A0 const& a0, A1 const& a1) const
|
---|
417 | {
|
---|
418 | typedef typename
|
---|
419 | aux::make_arg_list<
|
---|
420 | PS0,A0
|
---|
421 | , aux::make_arg_list<
|
---|
422 | PS1,A1
|
---|
423 | , mpl::identity<aux::empty_arg_list>
|
---|
424 | >
|
---|
425 | >
|
---|
426 | ::type result_type;
|
---|
427 |
|
---|
428 |
|
---|
429 | return result_type(
|
---|
430 | a0, a1
|
---|
431 | // , void_(), void_() ...
|
---|
432 | BOOST_PP_ENUM_TRAILING_PARAMS(
|
---|
433 | BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 2)
|
---|
434 | , aux::void_() BOOST_PP_INTERCEPT)
|
---|
435 | );
|
---|
436 | }
|
---|
437 |
|
---|
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> \
|
---|
441 | ))
|
---|
442 | #include BOOST_PP_ITERATE()
|
---|
443 |
|
---|
444 | #undef BOOST_PARAMETER_build_arg_list
|
---|
445 | #undef BOOST_PARAMETER_make_arg_list
|
---|
446 | #undef BOOST_PARAMETER_right_angle
|
---|
447 |
|
---|
448 | };
|
---|
449 |
|
---|
450 | } // namespace parameter
|
---|
451 |
|
---|
452 | } // namespace boost
|
---|
453 |
|
---|
454 | #endif // BOOST_PARAMETERS_031014_HPP
|
---|
455 |
|
---|