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 
BOOST_PARAMETER_FORWARD_TYPEDEFSboost::parameter::parameters828     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
operator ()boost::parameter::parameters856     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
operator ()boost::parameter::parameters892     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 
932