// Copyright David Abrahams, Daniel Wallin 2003. Use, modification and 

// distribution is subject to the Boost Software License, Version 1.0. 

// (See accompanying file LICENSE_1_0.txt or copy at 

// http://www.boost.org/LICENSE_1_0.txt)



#ifndef BOOST_PARAMETERS_031014_HPP

#define BOOST_PARAMETERS_031014_HPP



#include <boost/detail/is_xxx.hpp>



#include <boost/type_traits/is_const.hpp>



#include <boost/mpl/lambda.hpp>

#include <boost/mpl/apply.hpp>

#include <boost/mpl/always.hpp>

#include <boost/mpl/and.hpp>

#include <boost/mpl/or.hpp>

#include <boost/mpl/if.hpp>

#include <boost/mpl/identity.hpp>

#include <boost/mpl/not.hpp>

#include <boost/mpl/eval_if.hpp>

#include <boost/mpl/pair.hpp>



#include <boost/type_traits/is_same.hpp>

#include <boost/type_traits/remove_reference.hpp>



#include <boost/preprocessor/repetition/enum.hpp>

#include <boost/preprocessor/repetition/enum_params.hpp>

#include <boost/preprocessor/repetition/enum_trailing_params.hpp>

#include <boost/preprocessor/arithmetic/sub.hpp>

#include <boost/preprocessor/repetition/repeat.hpp>

#include <boost/preprocessor/repetition/enum_shifted.hpp>

#include <boost/preprocessor/repetition/enum_binary_params.hpp>

#include <boost/preprocessor/repetition/enum_shifted_params.hpp>

#include <boost/preprocessor/seq/elem.hpp>

#include <boost/preprocessor/iteration/iterate.hpp>

#include <boost/preprocessor/facilities/intercept.hpp>

#include <boost/preprocessor/cat.hpp>



#include <boost/parameter/aux_/arg_list.hpp>

#include <boost/parameter/aux_/yesno.hpp>

#include <boost/parameter/aux_/void.hpp>

#include <boost/parameter/aux_/default.hpp>

#include <boost/parameter/aux_/unwrap_cv_reference.hpp>

#include <boost/parameter/aux_/tagged_argument.hpp>

#include <boost/parameter/aux_/tag.hpp>

#include <boost/parameter/aux_/template_keyword.hpp>

#include <boost/parameter/aux_/set.hpp>

#include <boost/parameter/config.hpp>



namespace parameter_

{

  template <class T>

  struct unmatched_argument

  {

      BOOST_MPL_ASSERT((boost::is_same<T,void>));

      typedef int type;

  }; 

} // namespace parameter_



namespace boost {



template<class T> class reference_wrapper;



namespace parameter {



namespace aux { struct use_default {}; }



// These templates can be used to describe the treatment of particular

// named parameters for the purposes of overload elimination with

// SFINAE, by placing specializations in the parameters<...> list.  In

// order for a treated function to participate in overload resolution:

//

//   - all keyword tags wrapped in required<...> must have a matching

//     actual argument

//

//   - The actual argument type matched by every keyword tag

//     associated with a predicate must satisfy that predicate

//

// If a keyword k is specified without an optional<...> or

// required<...>, wrapper, it is treated as though optional<k> were

// specified.

//

// If a keyword k is specified with deduced<...>, that keyword

// will be automatically deduced from the argument list.

//

template <class Tag, class Predicate = aux::use_default>

struct required

{

    typedef Tag key_type;

    typedef Predicate predicate;

};



template <class Tag, class Predicate = aux::use_default>

struct optional

{

    typedef Tag key_type;

    typedef Predicate predicate;

};



template <class Tag>

struct deduced

{

    typedef Tag key_type;

};



namespace aux

{

  // Defines metafunctions, is_required and is_optional, that

  // identify required<...>, optional<...> and deduced<...> specializations.

  BOOST_DETAIL_IS_XXX_DEF(required, required, 2)

  BOOST_DETAIL_IS_XXX_DEF(optional, optional, 2)

  BOOST_DETAIL_IS_XXX_DEF(deduced_aux, deduced, 1)



  template <class S>

  struct is_deduced0

    : is_deduced_aux<

          typename S::key_type

      >::type

  {};



  template <class S>

  struct is_deduced

    : mpl::eval_if<

          mpl::or_<

              is_optional<S>, is_required<S>

          >

        , is_deduced0<S>

        , mpl::false_

      >::type

  {};



  //

  // key_type, has_default, and predicate --

  //

  // These metafunctions accept a ParameterSpec and extract the

  // keyword tag, whether or not a default is supplied for the

  // parameter, and the predicate that the corresponding actual

  // argument type is required match.

  //

  // a ParameterSpec is a specialization of either keyword<...>,

  // required<...>, optional<...>

  //



  // helper for key_type<...>, below.

  template <class T>

  struct get_tag_type0

  {

      typedef typename T::key_type type;

  };



  template <class T>

  struct get_tag_type

    : mpl::eval_if<

          is_deduced_aux<typename T::key_type>

        , get_tag_type0<typename T::key_type>

        , mpl::identity<typename T::key_type>

      >

  {};



  template <class T>

  struct tag_type

    : mpl::eval_if<

          mpl::or_<

              is_optional<T>

            , is_required<T>

          >

        , get_tag_type<T>

        , mpl::identity<T>

      >

  {};



  template <class T>

  struct has_default

    : mpl::not_<is_required<T> >

  {};



  // helper for get_predicate<...>, below

  template <class T>

  struct get_predicate_or_default

  {

      typedef T type;

  };



  template <>

  struct get_predicate_or_default<use_default>

  {

      typedef mpl::always<mpl::true_> type;

  };



  // helper for predicate<...>, below

  template <class T>

  struct get_predicate

  {

      typedef typename

          get_predicate_or_default<typename T::predicate>::type

      type;

  };



  template <class T>

  struct predicate

    : mpl::eval_if<

         mpl::or_<

              is_optional<T>

            , is_required<T>

          >

        , get_predicate<T>

        , mpl::identity<mpl::always<mpl::true_> >

      >

  {

  };





  // Converts a ParameterSpec into a specialization of

  // parameter_requirements.  We need to do this in order to get the

  // tag_type into the type in a way that can be conveniently matched

  // by a satisfies(...) member function in arg_list.

  template <class ParameterSpec>

  struct as_parameter_requirements

  {

      typedef parameter_requirements<

          typename tag_type<ParameterSpec>::type

        , typename predicate<ParameterSpec>::type

        , typename has_default<ParameterSpec>::type

      > type;

  };



  template <class T>

  struct is_named_argument

    : mpl::or_<

          is_template_keyword<T>

        , is_tagged_argument<T>

      >

  {};

  

  // Returns mpl::true_ iff the given ParameterRequirements are

  // satisfied by ArgList.

  template <class ArgList, class ParameterRequirements>

  struct satisfies

  {

#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)

      // VC7.1 can't handle the sizeof() implementation below,

      // so we use this instead.

      typedef typename mpl::apply_wrap3<

          typename ArgList::binding

        , typename ParameterRequirements::keyword

        , void_

        , mpl::false_

      >::type bound;



      typedef typename mpl::eval_if<

          is_same<bound, void_>

        , typename ParameterRequirements::has_default

        , mpl::apply_wrap2<

              typename mpl::lambda<

                  typename ParameterRequirements::predicate, lambda_tag

              >::type

            , bound

            , ArgList

          >

      >::type type;

#else

      BOOST_STATIC_CONSTANT(

          bool, value = (

              sizeof(

                  aux::to_yesno(

                      ArgList::satisfies((ParameterRequirements*)0, (ArgList*)0)

                  )

              ) == sizeof(yes_tag)

          )

      );



      typedef mpl::bool_<satisfies::value> type;

#endif

  };



  // Returns mpl::true_ if the requirements of the given ParameterSpec

  // are satisfied by ArgList.

  template <class ArgList, class ParameterSpec>

  struct satisfies_requirements_of

    : satisfies<

          ArgList

        , typename as_parameter_requirements<ParameterSpec>::type

      >

  {};



  // Tags a deduced argument Arg with the keyword tag of Spec using TagFn.

  // Returns the tagged argument and the mpl::set<> UsedArgs with the

  // tag of Spec inserted.

  template <class UsedArgs, class Spec, class Arg, class TagFn>

  struct tag_deduced

  {

      typedef mpl::pair<

          typename mpl::apply_wrap2<TagFn, typename tag_type<Spec>::type, Arg>::type

        , typename aux::insert_<UsedArgs, typename tag_type<Spec>::type>::type

      > type;

  };



  template <

      class Argument

    , class ArgumentPack

    , class DeducedArgs

    , class UsedArgs

    , class TagFn

  >

  struct deduce_tag;



  // Tag type passed to MPL lambda.

  struct lambda_tag;



  // Helper for deduce_tag<> below.

  template <

      class Argument

    , class ArgumentPack

    , class DeducedArgs

    , class UsedArgs

    , class TagFn

  >

  struct deduce_tag0

  {

      typedef typename DeducedArgs::spec spec;



      typedef typename mpl::apply_wrap2<

          typename mpl::lambda<

              typename spec::predicate, lambda_tag

          >::type

        , Argument

        , ArgumentPack

      >::type condition;



      // Deduced parameter matches several arguments.



      BOOST_MPL_ASSERT((

          mpl::not_<mpl::and_<

              condition

            , aux::has_key_<UsedArgs, typename tag_type<spec>::type>

          > >

      ));



      typedef typename mpl::eval_if<

          condition

        , tag_deduced<UsedArgs, spec, Argument, TagFn>

        , deduce_tag<Argument, ArgumentPack, typename DeducedArgs::tail, UsedArgs, TagFn>

      >::type type;

  };



  // Tries to deduced a keyword tag for a given Argument.

  // Returns an mpl::pair<> consisting of the tagged_argument<>, 

  // and an mpl::set<> where the new tag has been inserted.

  //

  //  Argument: The argument type to be tagged.

  //

  //  ArgumentPack: The ArgumentPack built so far.

  //

  //  DeducedArgs: A specialization of deduced_item<> (see below).

  //               A list containing only the deduced ParameterSpecs.

  //

  //  UsedArgs: An mpl::set<> containing the keyword tags used so far.

  //

  //  TagFn: A metafunction class used to tag positional or deduced

  //         arguments with a keyword tag.



  template <

      class Argument

    , class ArgumentPack

    , class DeducedArgs

    , class UsedArgs

    , class TagFn

  >

  struct deduce_tag

  {

      typedef typename mpl::eval_if<

          is_same<DeducedArgs, void_>

        , mpl::pair<void_, UsedArgs>

        , deduce_tag0<Argument, ArgumentPack, DeducedArgs, UsedArgs, TagFn>

      >::type type;

  };



  template <

      class List

    , class DeducedArgs

    , class TagFn

    , class Positional

    , class UsedArgs

    , class ArgumentPack

    , class Error

  >

  struct make_arg_list_aux;



  // Inserts Tagged::key_type into the UserArgs set.

  // Extra indirection to lazily evaluate Tagged::key_type.

  template <class UsedArgs, class Tagged>

  struct insert_tagged

  {

      typedef typename aux::insert_<

          UsedArgs, typename Tagged::key_type

      >::type type;

  };



  // Borland needs the insane extra-indirection workaround below

  // so that it doesn't magically drop the const qualifier from

  // the argument type.



  template <

      class List

    , class DeducedArgs

    , class TagFn

    , class Positional

    , class UsedArgs

    , class ArgumentPack

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

    , class argument

#endif

    , class Error

  >

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

  struct make_arg_list00

#else

  struct make_arg_list0

#endif

  {

#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

      typedef typename List::arg argument;

#endif

      typedef typename List::spec parameter_spec;

      typedef typename tag_type<parameter_spec>::type tag_;



      typedef is_named_argument<argument> is_tagged;



      // If this argument is either explicitly tagged or a deduced

      // parameter, we turn off positional matching.

      typedef mpl::and_<

          mpl::not_<

              mpl::or_<is_deduced<parameter_spec>, is_tagged> 

          > 

        , Positional

      > positional;



      // If this parameter is explicitly tagged we add it to the

      // used-parmeters set. We only really need to add parameters

      // that are deduced, but we would need a way to check if

      // a given tag corresponds to a deduced parameter spec.

      typedef typename mpl::eval_if<

          is_tagged

        , insert_tagged<UsedArgs, argument>

        , mpl::identity<UsedArgs>

      >::type used_args;



      // If this parameter is neither explicitly tagged, nor

      // positionally matched; deduce the tag from the deduced

      // parameter specs.

      typedef typename mpl::eval_if<

          mpl::or_<is_tagged, positional>

        , mpl::pair<void_, used_args>

        , deduce_tag<argument, ArgumentPack, DeducedArgs, used_args, TagFn>

      >::type deduced_data;



      // If this parameter is explicitly tagged..

      typedef typename mpl::eval_if<

          is_tagged

        , mpl::identity<argument>                        // .. just use it

        , mpl::eval_if<                                  // .. else, if positional matching is turned on..

                positional

              , mpl::apply_wrap2<TagFn, tag_, argument>  // .. tag it positionally

              , mpl::first<deduced_data>                 // .. else, use the deduced tag

          >

      >::type tagged;



      // We build the arg_list incrementally as we go, prepending new

      // nodes.



      typedef typename mpl::if_<

          mpl::and_<

              is_same<Error, void_>

            , is_same<tagged, void_>

          >

        , parameter_::unmatched_argument<argument>

        , void_

      >::type error;



      typedef typename mpl::if_<

          is_same<tagged, void_>

        , ArgumentPack

        , arg_list<tagged, ArgumentPack>

      >::type argument_pack;



      typedef typename make_arg_list_aux<

          typename List::tail

        , DeducedArgs

        , TagFn

        , positional

        , typename deduced_data::second

        , argument_pack

        , error

      >::type type;

  };



#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

  template <

      class List

    , class DeducedArgs

    , class TagFn

    , class Positional

    , class UsedArgs

    , class ArgumentPack

    , class Error

  >

  struct make_arg_list0

  {

      typedef typename mpl::eval_if<

          typename List::is_arg_const

        , make_arg_list00<

              List

            , DeducedArgs

            , TagFn

            , Positional

            , UsedArgs

            , ArgumentPack

            , typename List::arg const

            , Error

          >

        , make_arg_list00<

              List

            , DeducedArgs

            , TagFn

            , Positional

            , UsedArgs

            , ArgumentPack

            , typename List::arg

            , Error

          >

      >::type type;

  };

#endif



  // Returns an ArgumentPack where the list of arguments has

  // been tagged with keyword tags.

  //

  //   List: A specialization of item<> (see below). Contains

  //         both the ordered ParameterSpecs, and the given arguments.

  //

  //   DeducedArgs: A specialization of deduced_item<> (see below).

  //                A list containing only the deduced ParameterSpecs.

  //

  //   TagFn: A metafunction class used to tag positional or deduced

  //          arguments with a keyword tag.

  //

  //   Position: An mpl::bool_<> specialization indicating if positional

  //             matching is to be performed.

  //

  //   DeducedSet: An mpl::set<> containing the keyword tags used so far.

  //

  //   ArgumentPack: The ArgumentPack built so far. This is initially an

  //                 empty_arg_list and is built incrementally.

  //



  template <

      class List

    , class DeducedArgs

    , class TagFn

    , class Positional

    , class DeducedSet

    , class ArgumentPack

    , class Error

  >

  struct make_arg_list_aux

  {

      typedef typename mpl::eval_if<

          is_same<List, void_>

        , mpl::identity<mpl::pair<ArgumentPack, Error> >

        , make_arg_list0<List, DeducedArgs, TagFn, Positional, DeducedSet, ArgumentPack, Error>

      >::type type;

  };



  // VC6.5 was choking on the default parameters for make_arg_list_aux, so

  // this just forwards to that adding in the defaults.

  template <

      class List

    , class DeducedArgs

    , class TagFn

    , class EmitErrors = mpl::true_

  >

  struct make_arg_list

  {

      typedef typename make_arg_list_aux<

          List, DeducedArgs, TagFn, mpl::true_, aux::set0, empty_arg_list, void_

      >::type type;

  };



  // A parameter spec item typelist.

  template <class Spec, class Arg, class Tail = void_>

  struct item

  {

      typedef Spec spec;



#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

      typedef is_const<Arg> is_arg_const;

#endif



      typedef Arg arg;

      typedef Tail tail;

  };



  template <class Spec, class Arg, class Tail>

  struct make_item

  {

      typedef item<Spec, Arg, typename Tail::type> type;

  };



  // Creates a item typelist.

  template <class Spec, class Arg, class Tail>

  struct make_items

  {

      typedef typename mpl::eval_if<

          is_same<Arg, void_>

        , mpl::identity<void_>

        , make_item<Spec, Arg, Tail>

      >::type type;

  };



  // A typelist that stored deduced parameter specs.

  template <class ParameterSpec, class Tail = void_>

  struct deduced_item

  {

      typedef ParameterSpec spec;

      typedef Tail tail;

  };



  // Evaluate Tail and construct deduced_item list.

  template <class Spec, class Tail>

  struct make_deduced_item

  {

      typedef deduced_item<Spec, typename Tail::type> type;

  };



  template <class Spec, class Tail>

  struct make_deduced_items

  {

      typedef typename mpl::eval_if<

          is_same<Spec, void_>

        , mpl::identity<void_>

        , mpl::eval_if<

              is_deduced<Spec>

            , make_deduced_item<Spec, Tail>

            , Tail

          >

      >::type type;

  };



  // Generates:

  //

  //   make<

  //       parameter_spec#0, argument_type#0

  //     , make<

  //           parameter_spec#1, argument_type#1

  //         , ... mpl::identity<aux::empty_arg_list>

  //    ...>

  //   >

#define BOOST_PARAMETER_make_arg_list(z, n, names)      \

      BOOST_PP_SEQ_ELEM(0,names)<                       \

          BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n),  \

          BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,names), n), 



#define BOOST_PARAMETER_right_angle(z, n, text) >



#define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type)      \

  BOOST_PP_REPEAT(                                                                  \

      n, BOOST_PARAMETER_make_arg_list, (make)(parameter_spec)(argument_type))      \

      mpl::identity<void_>                                                          \

  BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)



#define BOOST_PARAMETER_make_deduced_list(z, n, names)  \

      BOOST_PP_SEQ_ELEM(0,names)<                       \

          BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n),



#define BOOST_PARAMETER_build_deduced_list(n, make, parameter_spec)                 \

  BOOST_PP_REPEAT(                                                                  \

      n, BOOST_PARAMETER_make_deduced_list, (make)(parameter_spec))                 \

  mpl::identity<void_>                                                              \

  BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)



  struct tag_keyword_arg

  {

      template <class K, class T>

      struct apply

        : tag<K,T>

      {};

  };



  struct tag_template_keyword_arg

  {

      template <class K, class T>

      struct apply

      {

          typedef template_keyword<K,T> type;

      };

  };



} // namespace aux



#define BOOST_PARAMETER_FORWARD_TYPEDEF(z, i, names) \

    typedef BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0,names),i) BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names),i);



#define BOOST_PARAMETER_FORWARD_TYPEDEFS(n, src, dest) \

    BOOST_PP_REPEAT(n, BOOST_PARAMETER_FORWARD_TYPEDEF, (src)(dest))





#define BOOST_PARAMETER_TEMPLATE_ARGS(z, n, text) class BOOST_PP_CAT(PS, n) = void_



template<

     class PS0

   , BOOST_PP_ENUM_SHIFTED(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_TEMPLATE_ARGS, _)

>

struct parameters

{

#undef BOOST_PARAMETER_TEMPLATE_ARGS



    typedef typename BOOST_PARAMETER_build_deduced_list(

        BOOST_PARAMETER_MAX_ARITY, aux::make_deduced_items, PS

    )::type deduced_list;



    // if the elements of NamedList match the criteria of overload

    // resolution, returns a type which can be constructed from

    // parameters.  Otherwise, this is not a valid metafunction (no nested

    // ::type).





#if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))

    // If NamedList satisfies the PS0, PS1, ..., this is a

    // metafunction returning parameters.  Otherwise it 

    // has no nested ::type.

    template <class ArgumentPackAndError>

    struct match_base

      : mpl::if_<

            // mpl::and_<

            //    aux::satisfies_requirements_of<NamedList,PS0>

            //  , mpl::and_<

            //       aux::satisfies_requirements_of<NamedList,PS1>...

            //           ..., mpl::true_

            // ...> >

            

# define BOOST_PARAMETER_satisfies(z, n, text)                                      \

            mpl::and_<                                                              \

                aux::satisfies_requirements_of<                                     \

                    typename mpl::first<ArgumentPackAndError>::type                 \

                  , BOOST_PP_CAT(PS, n)>                                            \

                  ,

            mpl::and_<

                is_same<typename mpl::second<ArgumentPackAndError>::type, void_>

              , BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_satisfies, _)

                mpl::true_

                BOOST_PP_REPEAT(BOOST_PARAMETER_MAX_ARITY, BOOST_PARAMETER_right_angle, _)

            >



# undef BOOST_PARAMETER_satisfies



          , mpl::identity<parameters>

          , void_

        >

    {};

#endif

    

    // Specializations are to be used as an optional argument to

    // eliminate overloads via SFINAE

    template<

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

        // Borland simply can't handle default arguments in member

        // class templates.  People wishing to write portable code can

        // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments

        BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)

#else 

        BOOST_PP_ENUM_BINARY_PARAMS(

            BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT

        )

#endif

    >

    struct match

# if ! defined(BOOST_NO_SFINAE) && ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))

      : match_base<

            typename aux::make_arg_list<

                typename BOOST_PARAMETER_build_arg_list(

                    BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A

                )::type

              , deduced_list

              , aux::tag_keyword_arg

              , mpl::false_ // Don't emit errors when doing SFINAE

            >::type

        >::type

    {};

# else

    { 

        typedef parameters<

            BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)

        > type; 

    };

# endif



    // Metafunction that returns an ArgumentPack.



    // TODO, bind has to instantiate the error type in the result

    // of make_arg_list.



    template <

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

        // Borland simply can't handle default arguments in member

        // class templates.  People wishing to write portable code can

        // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments

        BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)

#else 

        BOOST_PP_ENUM_BINARY_PARAMS(

            BOOST_PARAMETER_MAX_ARITY, class A, = void_ BOOST_PP_INTERCEPT

        )

#endif            

    >

    struct bind

    {

        typedef typename aux::make_arg_list<

            typename BOOST_PARAMETER_build_arg_list(

                BOOST_PARAMETER_MAX_ARITY, aux::make_items, PS, A

            )::type

          , deduced_list

          , aux::tag_template_keyword_arg

        >::type result;



        typedef typename mpl::first<result>::type type;

    };



    BOOST_PARAMETER_FORWARD_TYPEDEFS(BOOST_PARAMETER_MAX_ARITY, PS, parameter_spec)



    //

    // The function call operator is used to build an arg_list that

    // labels the positional parameters and maintains whatever other

    // tags may have been specified by the caller.

    //

    // !!!NOTE!!!

    //

    // The make_arg_list<> produces a reversed arg_list, so

    // we need to pass the arguments to its constructor

    // reversed.

    //

    aux::empty_arg_list operator()() const

    {

       return aux::empty_arg_list();

    }



    template<class A0>

    typename mpl::first<

        typename aux::make_arg_list<

            aux::item<

                PS0,A0

            >

          , deduced_list

          , aux::tag_keyword_arg

        >::type

    >::type

    operator()(A0& a0) const

    {

        typedef typename aux::make_arg_list<

            aux::item<

                PS0,A0

            >

          , deduced_list

          , aux::tag_keyword_arg

        >::type result;



        typedef typename mpl::first<result>::type result_type;

        typedef typename mpl::second<result>::type error;

        error();



        return result_type(

            a0

            // , void_(), void_(), void_() ...

            BOOST_PP_ENUM_TRAILING_PARAMS(

                BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 1)

              , aux::void_reference() BOOST_PP_INTERCEPT)

        );

    }



    template<class A0, class A1>

    typename mpl::first<

        typename aux::make_arg_list<

            aux::item<

                PS0,A0

              , aux::item<

                    PS1,A1

                >

            >

          , deduced_list

          , aux::tag_keyword_arg

        >::type

    >::type

    operator()(A0& a0, A1& a1) const

    {

        typedef typename aux::make_arg_list<

            aux::item<

                PS0,A0

              , aux::item<

                    PS1,A1

                >

            >

          , deduced_list

          , aux::tag_keyword_arg

        >::type result;



        typedef typename mpl::first<result>::type result_type;

        typedef typename mpl::second<result>::type error;

        error();



        return result_type(

            a1,a0

            // , void_(), void_() ...

            BOOST_PP_ENUM_TRAILING_PARAMS(

                BOOST_PP_SUB(BOOST_PARAMETER_MAX_ARITY, 2)

              , aux::void_reference() BOOST_PP_INTERCEPT)

        );

    }



    // Higher arities are handled by the preprocessor

#define BOOST_PP_ITERATION_PARAMS_1 (3,( \

        3,BOOST_PARAMETER_MAX_ARITY,<boost/parameter/aux_/overloads.hpp> \

    ))

#include BOOST_PP_ITERATE()



};



} // namespace parameter



} // namespace boost



#endif // BOOST_PARAMETERS_031014_HPP



