]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/type_traits/is_const.hpp> | |
12 | ||
13 | #include <boost/mpl/lambda.hpp> | |
14 | #include <boost/mpl/apply.hpp> | |
15 | #include <boost/mpl/always.hpp> | |
16 | #include <boost/mpl/and.hpp> | |
17 | #include <boost/mpl/or.hpp> | |
18 | #include <boost/mpl/if.hpp> | |
19 | #include <boost/mpl/identity.hpp> | |
20 | #include <boost/mpl/not.hpp> | |
21 | #include <boost/mpl/eval_if.hpp> | |
22 | #include <boost/mpl/pair.hpp> | |
23 | ||
24 | #include <boost/type_traits/is_same.hpp> | |
25 | #include <boost/type_traits/remove_reference.hpp> | |
26 | ||
27 | #include <boost/preprocessor/repetition/enum.hpp> | |
28 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
29 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> | |
30 | #include <boost/preprocessor/arithmetic/sub.hpp> | |
31 | #include <boost/preprocessor/repetition/repeat.hpp> | |
32 | #include <boost/preprocessor/repetition/enum_shifted.hpp> | |
33 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> | |
34 | #include <boost/preprocessor/repetition/enum_shifted_params.hpp> | |
35 | #include <boost/preprocessor/seq/elem.hpp> | |
36 | #include <boost/preprocessor/iteration/iterate.hpp> | |
37 | #include <boost/preprocessor/facilities/intercept.hpp> | |
38 | #include <boost/preprocessor/cat.hpp> | |
39 | ||
40 | #include <boost/parameter/aux_/arg_list.hpp> | |
41 | #include <boost/parameter/aux_/yesno.hpp> | |
42 | #include <boost/parameter/aux_/void.hpp> | |
43 | #include <boost/parameter/aux_/default.hpp> | |
44 | #include <boost/parameter/aux_/unwrap_cv_reference.hpp> | |
45 | #include <boost/parameter/aux_/tagged_argument.hpp> | |
46 | #include <boost/parameter/aux_/tag.hpp> | |
47 | #include <boost/parameter/aux_/template_keyword.hpp> | |
48 | #include <boost/parameter/aux_/set.hpp> | |
49 | #include <boost/parameter/config.hpp> | |
50 | ||
51 | namespace parameter_ | |
52 | { | |
53 | template <class T> | |
54 | struct unmatched_argument | |
55 | { | |
56 | BOOST_MPL_ASSERT((boost::is_same<T,void>)); | |
57 | typedef int type; | |
58 | }; | |
59 | } // namespace parameter_ | |
60 | ||
61 | namespace boost { | |
62 | ||
63 | template<class T> class reference_wrapper; | |
64 | ||
65 | namespace parameter { | |
66 | ||
67 | namespace aux { struct use_default {}; } | |
68 | ||
69 | // These templates can be used to describe the treatment of particular | |
70 | // named parameters for the purposes of overload elimination with | |
71 | // SFINAE, by placing specializations in the parameters<...> list. In | |
72 | // order for a treated function to participate in overload resolution: | |
73 | // | |
74 | // - all keyword tags wrapped in required<...> must have a matching | |
75 | // actual argument | |
76 | // | |
77 | // - The actual argument type matched by every keyword tag | |
78 | // associated with a predicate must satisfy that predicate | |
79 | // | |
80 | // If a keyword k is specified without an optional<...> or | |
81 | // required<...>, wrapper, it is treated as though optional<k> were | |
82 | // specified. | |
83 | // | |
84 | // If a keyword k is specified with deduced<...>, that keyword | |
85 | // will be automatically deduced from the argument list. | |
86 | // | |
87 | template <class Tag, class Predicate = aux::use_default> | |
88 | struct required | |
89 | { | |
90 | typedef Tag key_type; | |
91 | typedef Predicate predicate; | |
92 | }; | |
93 | ||
94 | template <class Tag, class Predicate = aux::use_default> | |
95 | struct optional | |
96 | { | |
97 | typedef Tag key_type; | |
98 | typedef Predicate predicate; | |
99 | }; | |
100 | ||
101 | template <class Tag> | |
102 | struct deduced | |
103 | { | |
104 | typedef Tag key_type; | |
105 | }; | |
106 | ||
107 | namespace aux | |
108 | { | |
109 | // Defines metafunctions, is_required and is_optional, that | |
110 | // identify required<...>, optional<...> and deduced<...> specializations. | |
111 | BOOST_DETAIL_IS_XXX_DEF(required, required, 2) | |
112 | BOOST_DETAIL_IS_XXX_DEF(optional, optional, 2) | |
113 | BOOST_DETAIL_IS_XXX_DEF(deduced_aux, deduced, 1) | |
114 | ||
115 | template <class S> | |
116 | struct is_deduced0 | |
117 | : is_deduced_aux< | |
118 | typename S::key_type | |
119 | >::type | |
120 | {}; | |
121 | ||
122 | template <class S> | |
123 | struct is_deduced | |
124 | : mpl::eval_if< | |
125 | mpl::or_< | |
126 | is_optional<S>, is_required<S> | |
127 | > | |
128 | , is_deduced0<S> | |
129 | , mpl::false_ | |
130 | >::type | |
131 | {}; | |
132 | ||
133 | // | |
134 | // key_type, has_default, and predicate -- | |
135 | // | |
136 | // These metafunctions accept a ParameterSpec and extract the | |
137 | // keyword tag, whether or not a default is supplied for the | |
138 | // parameter, and the predicate that the corresponding actual | |
139 | // argument type is required match. | |
140 | // | |
141 | // a ParameterSpec is a specialization of either keyword<...>, | |
142 | // required<...>, optional<...> | |
143 | // | |
144 | ||
145 | // helper for key_type<...>, below. | |
146 | template <class T> | |
147 | struct get_tag_type0 | |
148 | { | |
149 | typedef typename T::key_type type; | |
150 | }; | |
151 | ||
152 | template <class T> | |
153 | struct get_tag_type | |
154 | : mpl::eval_if< | |
155 | is_deduced_aux<typename T::key_type> | |
156 | , get_tag_type0<typename T::key_type> | |
157 | , mpl::identity<typename T::key_type> | |
158 | > | |
159 | {}; | |
160 | ||
161 | template <class T> | |
162 | struct tag_type | |
163 | : mpl::eval_if< | |
164 | mpl::or_< | |
165 | is_optional<T> | |
166 | , is_required<T> | |
167 | > | |
168 | , get_tag_type<T> | |
169 | , mpl::identity<T> | |
170 | > | |
171 | {}; | |
172 | ||
173 | template <class T> | |
174 | struct has_default | |
175 | : mpl::not_<is_required<T> > | |
176 | {}; | |
177 | ||
178 | // helper for get_predicate<...>, below | |
179 | template <class T> | |
180 | struct get_predicate_or_default | |
181 | { | |
182 | typedef T type; | |
183 | }; | |
184 | ||
185 | template <> | |
186 | struct get_predicate_or_default<use_default> | |
187 | { | |
188 | typedef mpl::always<mpl::true_> type; | |
189 | }; | |
190 | ||
191 | // helper for predicate<...>, below | |
192 | template <class T> | |
193 | struct get_predicate | |
194 | { | |
195 | typedef typename | |
196 | get_predicate_or_default<typename T::predicate>::type | |
197 | type; | |
198 | }; | |
199 | ||
200 | template <class T> | |
201 | struct predicate | |
202 | : mpl::eval_if< | |
203 | mpl::or_< | |
204 | is_optional<T> | |
205 | , is_required<T> | |
206 | > | |
207 | , get_predicate<T> | |
208 | , mpl::identity<mpl::always<mpl::true_> > | |
209 | > | |
210 | { | |
211 | }; | |
212 | ||
213 | ||
214 | // Converts a ParameterSpec into a specialization of | |
215 | // parameter_requirements. We need to do this in order to get the | |
216 | // tag_type into the type in a way that can be conveniently matched | |
217 | // by a satisfies(...) member function in arg_list. | |
218 | template <class ParameterSpec> | |
219 | struct as_parameter_requirements | |
220 | { | |
221 | typedef parameter_requirements< | |
222 | typename tag_type<ParameterSpec>::type | |
223 | , typename predicate<ParameterSpec>::type | |
224 | , typename has_default<ParameterSpec>::type | |
225 | > type; | |
226 | }; | |
227 | ||
228 | template <class T> | |
229 | struct is_named_argument | |
230 | : mpl::or_< | |
231 | is_template_keyword<T> | |
232 | , is_tagged_argument<T> | |
233 | > | |
234 | {}; | |
235 | ||
236 | // Returns mpl::true_ iff the given ParameterRequirements are | |
237 | // satisfied by ArgList. | |
238 | template <class ArgList, class ParameterRequirements> | |
239 | struct satisfies | |
240 | { | |
241 | #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) | |
242 | // VC7.1 can't handle the sizeof() implementation below, | |
243 | // so we use this instead. | |
244 | typedef typename mpl::apply_wrap3< | |
245 | typename ArgList::binding | |
246 | , typename ParameterRequirements::keyword | |
247 | , void_ | |
248 | , mpl::false_ | |
249 | >::type bound; | |
250 | ||
251 | typedef typename mpl::eval_if< | |
252 | is_same<bound, void_> | |
253 | , typename ParameterRequirements::has_default | |
254 | , mpl::apply_wrap2< | |
255 | typename mpl::lambda< | |
256 | typename ParameterRequirements::predicate, lambda_tag | |
257 | >::type | |
258 | , bound | |
259 | , ArgList | |
260 | > | |
261 | >::type type; | |
262 | #else | |
263 | BOOST_STATIC_CONSTANT( | |
264 | bool, value = ( | |
265 | sizeof( | |
266 | aux::to_yesno( | |
267 | ArgList::satisfies((ParameterRequirements*)0, (ArgList*)0) | |
268 | ) | |
269 | ) == sizeof(yes_tag) | |
270 | ) | |
271 | ); | |
272 | ||
273 | typedef mpl::bool_<satisfies::value> type; | |
274 | #endif | |
275 | }; | |
276 | ||
277 | // Returns mpl::true_ if the requirements of the given ParameterSpec | |
278 | // are satisfied by ArgList. | |
279 | template <class ArgList, class ParameterSpec> | |
280 | struct satisfies_requirements_of | |
281 | : satisfies< | |
282 | ArgList | |
283 | , typename as_parameter_requirements<ParameterSpec>::type | |
284 | > | |
285 | {}; | |
286 | ||
287 | // Tags a deduced argument Arg with the keyword tag of Spec using TagFn. | |
288 | // Returns the tagged argument and the mpl::set<> UsedArgs with the | |
289 | // tag of Spec inserted. | |
290 | template <class UsedArgs, class Spec, class Arg, class TagFn> | |
291 | struct tag_deduced | |
292 | { | |
293 | typedef mpl::pair< | |
294 | typename mpl::apply_wrap2<TagFn, typename tag_type<Spec>::type, Arg>::type | |
295 | , typename aux::insert_<UsedArgs, typename tag_type<Spec>::type>::type | |
296 | > type; | |
297 | }; | |
298 | ||
299 | template < | |
300 | class Argument | |
301 | , class ArgumentPack | |
302 | , class DeducedArgs | |
303 | , class UsedArgs | |
304 | , class TagFn | |
305 | > | |
306 | struct deduce_tag; | |
307 | ||
308 | // Tag type passed to MPL lambda. | |
309 | struct lambda_tag; | |
310 | ||
311 | // Helper for deduce_tag<> below. | |
312 | template < | |
313 | class Argument | |
314 | , class ArgumentPack | |
315 | , class DeducedArgs | |
316 | , class UsedArgs | |
317 | , class TagFn | |
318 | > | |
319 | struct deduce_tag0 | |
320 | { | |
321 | typedef typename DeducedArgs::spec spec; | |
322 | ||
323 | typedef typename mpl::apply_wrap2< | |
324 | typename mpl::lambda< | |
325 | typename spec::predicate, lambda_tag | |
326 | >::type | |
327 | , Argument | |
328 | , ArgumentPack | |
329 | >::type condition; | |
330 | ||
331 | // Deduced parameter matches several arguments. | |
332 | ||
333 | BOOST_MPL_ASSERT(( | |
334 | mpl::not_<mpl::and_< | |
335 | condition | |
336 | , aux::has_key_<UsedArgs, typename tag_type<spec>::type> | |
337 | > > | |
338 | )); | |
339 | ||
340 | typedef typename mpl::eval_if< | |
341 | condition | |
342 | , tag_deduced<UsedArgs, spec, Argument, TagFn> | |
343 | , deduce_tag<Argument, ArgumentPack, typename DeducedArgs::tail, UsedArgs, TagFn> | |
344 | >::type type; | |
345 | }; | |
346 | ||
347 | // Tries to deduced a keyword tag for a given Argument. | |
348 | // Returns an mpl::pair<> consisting of the tagged_argument<>, | |
349 | // and an mpl::set<> where the new tag has been inserted. | |
350 | // | |
351 | // Argument: The argument type to be tagged. | |
352 | // | |
353 | // ArgumentPack: The ArgumentPack built so far. | |
354 | // | |
355 | // DeducedArgs: A specialization of deduced_item<> (see below). | |
356 | // A list containing only the deduced ParameterSpecs. | |
357 | // | |
358 | // UsedArgs: An mpl::set<> containing the keyword tags used so far. | |
359 | // | |
360 | // TagFn: A metafunction class used to tag positional or deduced | |
361 | // arguments with a keyword tag. | |
362 | ||
363 | template < | |
364 | class Argument | |
365 | , class ArgumentPack | |
366 | , class DeducedArgs | |
367 | , class UsedArgs | |
368 | , class TagFn | |
369 | > | |
370 | struct deduce_tag | |
371 | { | |
372 | typedef typename mpl::eval_if< | |
373 | is_same<DeducedArgs, void_> | |
374 | , mpl::pair<void_, UsedArgs> | |
375 | , deduce_tag0<Argument, ArgumentPack, DeducedArgs, UsedArgs, TagFn> | |
376 | >::type type; | |
377 | }; | |
378 | ||
379 | template < | |
380 | class List | |
381 | , class DeducedArgs | |
382 | , class TagFn | |
383 | , class Positional | |
384 | , class UsedArgs | |
385 | , class ArgumentPack | |
386 | , class Error | |
387 | > | |
388 | struct make_arg_list_aux; | |
389 | ||
390 | // Inserts Tagged::key_type into the UserArgs set. | |
391 | // Extra indirection to lazily evaluate Tagged::key_type. | |
392 | template <class UsedArgs, class Tagged> | |
393 | struct insert_tagged | |
394 | { | |
395 | typedef typename aux::insert_< | |
396 | UsedArgs, typename Tagged::key_type | |
397 | >::type type; | |
398 | }; | |
399 | ||
400 | // Borland needs the insane extra-indirection workaround below | |
401 | // so that it doesn't magically drop the const qualifier from | |
402 | // the argument type. | |
403 | ||
404 | template < | |
405 | class List | |
406 | , class DeducedArgs | |
407 | , class TagFn | |
408 | , class Positional | |
409 | , class UsedArgs | |
410 | , class ArgumentPack | |
411 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
412 | , class argument | |
413 | #endif | |
414 | , class Error | |
415 | > | |
416 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
417 | struct make_arg_list00 | |
418 | #else | |
419 | struct make_arg_list0 | |
420 | #endif | |
421 | { | |
422 | #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
423 | typedef typename List::arg argument; | |
424 | #endif | |
425 | typedef typename List::spec parameter_spec; | |
426 | typedef typename tag_type<parameter_spec>::type tag_; | |
427 | ||
428 | typedef is_named_argument<argument> is_tagged; | |
429 | ||
430 | // If this argument is either explicitly tagged or a deduced | |
431 | // parameter, we turn off positional matching. | |
432 | typedef mpl::and_< | |
433 | mpl::not_< | |
434 | mpl::or_<is_deduced<parameter_spec>, is_tagged> | |
435 | > | |
436 | , Positional | |
437 | > positional; | |
438 | ||
439 | // If this parameter is explicitly tagged we add it to the | |
440 | // used-parmeters set. We only really need to add parameters | |
441 | // that are deduced, but we would need a way to check if | |
442 | // a given tag corresponds to a deduced parameter spec. | |
443 | typedef typename mpl::eval_if< | |
444 | is_tagged | |
445 | , insert_tagged<UsedArgs, argument> | |
446 | , mpl::identity<UsedArgs> | |
447 | >::type used_args; | |
448 | ||
449 | // If this parameter is neither explicitly tagged, nor | |
450 | // positionally matched; deduce the tag from the deduced | |
451 | // parameter specs. | |
452 | typedef typename mpl::eval_if< | |
453 | mpl::or_<is_tagged, positional> | |
454 | , mpl::pair<void_, used_args> | |
455 | , deduce_tag<argument, ArgumentPack, DeducedArgs, used_args, TagFn> | |
456 | >::type deduced_data; | |
457 | ||
458 | // If this parameter is explicitly tagged.. | |
459 | typedef typename mpl::eval_if< | |
460 | is_tagged | |
461 | , mpl::identity<argument> // .. just use it | |
462 | , mpl::eval_if< // .. else, if positional matching is turned on.. | |
463 | positional | |
464 | , mpl::apply_wrap2<TagFn, tag_, argument> // .. tag it positionally | |
465 | , mpl::first<deduced_data> // .. else, use the deduced tag | |
466 | > | |
467 | >::type tagged; | |
468 | ||
469 | // We build the arg_list incrementally as we go, prepending new | |
470 | // nodes. | |
471 | ||
472 | typedef typename mpl::if_< | |
473 | mpl::and_< | |
474 | is_same<Error, void_> | |
475 | , is_same<tagged, void_> | |
476 | > | |
477 | , parameter_::unmatched_argument<argument> | |
478 | , void_ | |
479 | >::type error; | |
480 | ||
481 | typedef typename mpl::if_< | |
482 | is_same<tagged, void_> | |
483 | , ArgumentPack | |
484 | , arg_list<tagged, ArgumentPack> | |
485 | >::type argument_pack; | |
486 | ||
487 | typedef typename make_arg_list_aux< | |
488 | typename List::tail | |
489 | , DeducedArgs | |
490 | , TagFn | |
491 | , positional | |
492 | , typename deduced_data::second | |
493 | , argument_pack | |
494 | , error | |
495 | >::type type; | |
496 | }; | |
497 | ||
498 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
499 | template < | |
500 | class List | |
501 | , class DeducedArgs | |
502 | , class TagFn | |
503 | , class Positional | |
504 | , class UsedArgs | |
505 | , class ArgumentPack | |
506 | , class Error | |
507 | > | |
508 | struct make_arg_list0 | |
509 | { | |
510 | typedef typename mpl::eval_if< | |
511 | typename List::is_arg_const | |
512 | , make_arg_list00< | |
513 | List | |
514 | , DeducedArgs | |
515 | , TagFn | |
516 | , Positional | |
517 | , UsedArgs | |
518 | , ArgumentPack | |
519 | , typename List::arg const | |
520 | , Error | |
521 | > | |
522 | , make_arg_list00< | |
523 | List | |
524 | , DeducedArgs | |
525 | , TagFn | |
526 | , Positional | |
527 | , UsedArgs | |
528 | , ArgumentPack | |
529 | , typename List::arg | |
530 | , Error | |
531 | > | |
532 | >::type type; | |
533 | }; | |
534 | #endif | |
535 | ||
536 | // Returns an ArgumentPack where the list of arguments has | |
537 | // been tagged with keyword tags. | |
538 | // | |
539 | // List: A specialization of item<> (see below). Contains | |
540 | // both the ordered ParameterSpecs, and the given arguments. | |
541 | // | |
542 | // DeducedArgs: A specialization of deduced_item<> (see below). | |
543 | // A list containing only the deduced ParameterSpecs. | |
544 | // | |
545 | // TagFn: A metafunction class used to tag positional or deduced | |
546 | // arguments with a keyword tag. | |
547 | // | |
548 | // Position: An mpl::bool_<> specialization indicating if positional | |
549 | // matching is to be performed. | |
550 | // | |
551 | // DeducedSet: An mpl::set<> containing the keyword tags used so far. | |
552 | // | |
553 | // ArgumentPack: The ArgumentPack built so far. This is initially an | |
554 | // empty_arg_list and is built incrementally. | |
555 | // | |
556 | ||
557 | template < | |
558 | class List | |
559 | , class DeducedArgs | |
560 | , class TagFn | |
561 | , class Positional | |
562 | , class DeducedSet | |
563 | , class ArgumentPack | |
564 | , class Error | |
565 | > | |
566 | struct make_arg_list_aux | |
567 | { | |
568 | typedef typename mpl::eval_if< | |
569 | is_same<List, void_> | |
570 | , mpl::identity<mpl::pair<ArgumentPack, Error> > | |
571 | , make_arg_list0<List, DeducedArgs, TagFn, Positional, DeducedSet, ArgumentPack, Error> | |
572 | >::type type; | |
573 | }; | |
574 | ||
575 | // VC6.5 was choking on the default parameters for make_arg_list_aux, so | |
576 | // this just forwards to that adding in the defaults. | |
577 | template < | |
578 | class List | |
579 | , class DeducedArgs | |
580 | , class TagFn | |
581 | , class EmitErrors = mpl::true_ | |
582 | > | |
583 | struct make_arg_list | |
584 | { | |
585 | typedef typename make_arg_list_aux< | |
586 | List, DeducedArgs, TagFn, mpl::true_, aux::set0, empty_arg_list, void_ | |
587 | >::type type; | |
588 | }; | |
589 | ||
590 | // A parameter spec item typelist. | |
591 | template <class Spec, class Arg, class Tail = void_> | |
592 | struct item | |
593 | { | |
594 | typedef Spec spec; | |
595 | ||
596 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
597 | typedef is_const<Arg> is_arg_const; | |
598 | #endif | |
599 | ||
600 | typedef Arg arg; | |
601 | typedef Tail tail; | |
602 | }; | |
603 | ||
604 | template <class Spec, class Arg, class Tail> | |
605 | struct make_item | |
606 | { | |
607 | typedef item<Spec, Arg, typename Tail::type> type; | |
608 | }; | |
609 | ||
610 | // Creates a item typelist. | |
611 | template <class Spec, class Arg, class Tail> | |
612 | struct make_items | |
613 | { | |
614 | typedef typename mpl::eval_if< | |
615 | is_same<Arg, void_> | |
616 | , mpl::identity<void_> | |
617 | , make_item<Spec, Arg, Tail> | |
618 | >::type type; | |
619 | }; | |
620 | ||
621 | // A typelist that stored deduced parameter specs. | |
622 | template <class ParameterSpec, class Tail = void_> | |
623 | struct deduced_item | |
624 | { | |
625 | typedef ParameterSpec spec; | |
626 | typedef Tail tail; | |
627 | }; | |
628 | ||
629 | // Evaluate Tail and construct deduced_item list. | |
630 | template <class Spec, class Tail> | |
631 | struct make_deduced_item | |
632 | { | |
633 | typedef deduced_item<Spec, typename Tail::type> type; | |
634 | }; | |
635 | ||
636 | template <class Spec, class Tail> | |
637 | struct make_deduced_items | |
638 | { | |
639 | typedef typename mpl::eval_if< | |
640 | is_same<Spec, void_> | |
641 | , mpl::identity<void_> | |
642 | , mpl::eval_if< | |
643 | is_deduced<Spec> | |
644 | , make_deduced_item<Spec, Tail> | |
645 | , Tail | |
646 | > | |
647 | >::type type; | |
648 | }; | |
649 | ||
650 | // Generates: | |
651 | // | |
652 | // make< | |
653 | // parameter_spec#0, argument_type#0 | |
654 | // , make< | |
655 | // parameter_spec#1, argument_type#1 | |
656 | // , ... mpl::identity<aux::empty_arg_list> | |
657 | // ...> | |
658 | // > | |
659 | #define BOOST_PARAMETER_make_arg_list(z, n, names) \ | |
660 | BOOST_PP_SEQ_ELEM(0,names)< \ | |
661 | BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n), \ | |
662 | BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,names), n), | |
663 | ||
664 | #define BOOST_PARAMETER_right_angle(z, n, text) > | |
665 | ||
666 | #define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type) \ | |
667 | BOOST_PP_REPEAT( \ | |
668 | n, BOOST_PARAMETER_make_arg_list, (make)(parameter_spec)(argument_type)) \ | |
669 | mpl::identity<void_> \ | |
670 | BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _) | |
671 | ||
672 | #define BOOST_PARAMETER_make_deduced_list(z, n, names) \ | |
673 | BOOST_PP_SEQ_ELEM(0,names)< \ | |
674 | BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n), | |
675 | ||
676 | #define BOOST_PARAMETER_build_deduced_list(n, make, parameter_spec) \ | |
677 | BOOST_PP_REPEAT( \ | |
678 | n, BOOST_PARAMETER_make_deduced_list, (make)(parameter_spec)) \ | |
679 | mpl::identity<void_> \ | |
680 | BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _) | |
681 | ||
682 | struct tag_keyword_arg | |
683 | { | |
684 | template <class K, class T> | |
685 | struct apply | |
686 | : tag<K,T> | |
687 | {}; | |
688 | }; | |
689 | ||
690 | struct tag_template_keyword_arg | |
691 | { | |
692 | template <class K, class T> | |
693 | struct apply | |
694 | { | |
695 | typedef template_keyword<K,T> type; | |
696 | }; | |
697 | }; | |
698 | ||
699 | } // namespace aux | |
700 | ||
701 | #define BOOST_PARAMETER_FORWARD_TYPEDEF(z, i, names) \ | |
702 | typedef BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0,names),i) BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names),i); | |
703 | ||
704 | #define BOOST_PARAMETER_FORWARD_TYPEDEFS(n, src, dest) \ | |
705 | BOOST_PP_REPEAT(n, BOOST_PARAMETER_FORWARD_TYPEDEF, (src)(dest)) | |
706 | ||
707 | ||
708 | #define BOOST_PARAMETER_TEMPLATE_ARGS(z, n, text) class BOOST_PP_CAT(PS, n) = void_ | |
709 | ||
710 | template< | |
711 | class PS0 | |
712 | , BOOST_PP_ENUM_SHIFTED(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_TEMPLATE_ARGS, _) | |
713 | > | |
714 | struct parameters | |
715 | { | |
716 | #undef BOOST_PARAMETER_TEMPLATE_ARGS | |
717 | ||
718 | typedef typename BOOST_PARAMETER_build_deduced_list( | |
719 | BOOST_PARAMETER_MAX_ARITY, aux::make_deduced_items, PS | |
720 | )::type deduced_list; | |
721 | ||
722 | // if the elements of NamedList match the criteria of overload | |
723 | // resolution, returns a type which can be constructed from | |
724 | // parameters. Otherwise, this is not a valid metafunction (no nested | |
725 | // ::type). | |
726 | ||
727 | ||
728 | #if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) | |
729 | // If NamedList satisfies the PS0, PS1, ..., this is a | |
730 | // metafunction returning parameters. Otherwise it | |
731 | // has no nested ::type. | |
732 | template <class ArgumentPackAndError> | |
733 | struct match_base | |
734 | : mpl::if_< | |
735 | // mpl::and_< | |
736 | // aux::satisfies_requirements_of<NamedList,PS0> | |
737 | // , mpl::and_< | |
738 | // aux::satisfies_requirements_of<NamedList,PS1>... | |
739 | // ..., mpl::true_ | |
740 | // ...> > | |
741 | ||
742 | # define BOOST_PARAMETER_satisfies(z, n, text) \ | |
743 | mpl::and_< \ | |
744 | aux::satisfies_requirements_of< \ | |
745 | typename mpl::first<ArgumentPackAndError>::type \ | |
746 | , BOOST_PP_CAT(PS, n)> \ | |
747 | , | |
748 | mpl::and_< | |
749 | is_same<typename mpl::second<ArgumentPackAndError>::type, void_> | |
750 | , BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_satisfies, _) | |
751 | mpl::true_ | |
752 | BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_right_angle, _) | |
753 | > | |
754 | ||
755 | # undef BOOST_PARAMETER_satisfies | |
756 | ||
757 | , mpl::identity<parameters> | |
758 | , void_ | |
759 | > | |
760 | {}; | |
761 | #endif | |
762 | ||
763 | // Specializations are to be used as an optional argument to | |
764 | // eliminate overloads via SFINAE | |
765 | template< | |
766 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
767 | // Borland simply can't handle default arguments in member | |
768 | // class templates. People wishing to write portable code can | |
769 | // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments | |
770 | BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A) | |
771 | #else | |
772 | BOOST_PP_ENUM_BINARY_PARAMS( | |
773 | BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT | |
774 | ) | |
775 | #endif | |
776 | > | |
777 | struct match | |
778 | # if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) | |
779 | : match_base< | |
780 | typename aux::make_arg_list< | |
781 | typename BOOST_PARAMETER_build_arg_list( | |
782 | BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A | |
783 | )::type | |
784 | , deduced_list | |
785 | , aux::tag_keyword_arg | |
786 | , mpl::false_ // Don't emit errors when doing SFINAE | |
787 | >::type | |
788 | >::type | |
789 | {}; | |
790 | # else | |
791 | { | |
792 | typedef parameters< | |
793 | BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS) | |
794 | > type; | |
795 | }; | |
796 | # endif | |
797 | ||
798 | // Metafunction that returns an ArgumentPack. | |
799 | ||
800 | // TODO, bind has to instantiate the error type in the result | |
801 | // of make_arg_list. | |
802 | ||
803 | template < | |
804 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) | |
805 | // Borland simply can't handle default arguments in member | |
806 | // class templates. People wishing to write portable code can | |
807 | // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments | |
808 | BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A) | |
809 | #else | |
810 | BOOST_PP_ENUM_BINARY_PARAMS( | |
811 | BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT | |
812 | ) | |
813 | #endif | |
814 | > | |
815 | struct bind | |
816 | { | |
817 | typedef typename aux::make_arg_list< | |
818 | typename BOOST_PARAMETER_build_arg_list( | |
819 | BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A | |
820 | )::type | |
821 | , deduced_list | |
822 | , aux::tag_template_keyword_arg | |
823 | >::type result; | |
824 | ||
825 | typedef typename mpl::first<result>::type type; | |
826 | }; | |
827 | ||
828 | BOOST_PARAMETER_FORWARD_TYPEDEFS(BOOST_PARAMETER_MAX_ARITY, PS, parameter_spec) | |
829 | ||
830 | // | |
831 | // The function call operator is used to build an arg_list that | |
832 | // labels the positional parameters and maintains whatever other | |
833 | // tags may have been specified by the caller. | |
834 | // | |
835 | // !!!NOTE!!! | |
836 | // | |
837 | // The make_arg_list<> produces a reversed arg_list, so | |
838 | // we need to pass the arguments to its constructor | |
839 | // reversed. | |
840 | // | |
841 | aux::empty_arg_list operator()() const | |
842 | { | |
843 | return aux::empty_arg_list(); | |
844 | } | |
845 | ||
846 | template<class A0> | |
847 | typename mpl::first< | |
848 | typename aux::make_arg_list< | |
849 | aux::item< | |
850 | PS0,A0 | |
851 | > | |
852 | , deduced_list | |
853 | , aux::tag_keyword_arg | |
854 | >::type | |
855 | >::type | |
856 | operator()(A0& a0) const | |
857 | { | |
858 | typedef typename aux::make_arg_list< | |
859 | aux::item< | |
860 | PS0,A0 | |
861 | > | |
862 | , deduced_list | |
863 | , aux::tag_keyword_arg | |
864 | >::type result; | |
865 | ||
866 | typedef typename mpl::first<result>::type result_type; | |
867 | typedef typename mpl::second<result>::type error; | |
868 | error(); | |
869 | ||
870 | return result_type( | |
871 | a0 | |
872 | // , void_(), void_(), void_() ... | |
873 | BOOST_PP_ENUM_TRAILING_PARAMS( | |
874 | BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 1) | |
875 | , aux::void_reference() BOOST_PP_INTERCEPT) | |
876 | ); | |
877 | } | |
878 | ||
879 | template<class A0, class A1> | |
880 | typename mpl::first< | |
881 | typename aux::make_arg_list< | |
882 | aux::item< | |
883 | PS0,A0 | |
884 | , aux::item< | |
885 | PS1,A1 | |
886 | > | |
887 | > | |
888 | , deduced_list | |
889 | , aux::tag_keyword_arg | |
890 | >::type | |
891 | >::type | |
892 | operator()(A0& a0, A1& a1) const | |
893 | { | |
894 | typedef typename aux::make_arg_list< | |
895 | aux::item< | |
896 | PS0,A0 | |
897 | , aux::item< | |
898 | PS1,A1 | |
899 | > | |
900 | > | |
901 | , deduced_list | |
902 | , aux::tag_keyword_arg | |
903 | >::type result; | |
904 | ||
905 | typedef typename mpl::first<result>::type result_type; | |
906 | typedef typename mpl::second<result>::type error; | |
907 | error(); | |
908 | ||
909 | return result_type( | |
910 | a1,a0 | |
911 | // , void_(), void_() ... | |
912 | BOOST_PP_ENUM_TRAILING_PARAMS( | |
913 | BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 2) | |
914 | , aux::void_reference() BOOST_PP_INTERCEPT) | |
915 | ); | |
916 | } | |
917 | ||
918 | // Higher arities are handled by the preprocessor | |
919 | #define BOOST_PP_ITERATION_PARAMS_1 (3,( \ | |
920 | 3,BOOST_PARAMETER_MAX_ARITY,<boost/parameter/aux_/overloads.hpp> \ | |
921 | )) | |
922 | #include BOOST_PP_ITERATE() | |
923 | ||
924 | }; | |
925 | ||
926 | } // namespace parameter | |
927 | ||
928 | } // namespace boost | |
929 | ||
930 | #endif // BOOST_PARAMETERS_031014_HPP | |
931 |