ossrv_pub/boost_apis/boost/parameter/parameters.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 #ifndef BOOST_NO_SFINAE
       
   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 # ifndef BOOST_NO_SFINAE
       
   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 it's 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