ossrv_pub/boost_apis/boost/parameter/aux_/arg_list.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright Daniel Wallin, David Abrahams 2005. Use, modification and
       
     2 // distribution is subject to the Boost Software License, Version 1.0. (See
       
     3 // accompanying file LICENSE_1_0.txt or copy at
       
     4 // http://www.boost.org/LICENSE_1_0.txt)
       
     5 
       
     6 #ifndef ARG_LIST_050329_HPP
       
     7 #define ARG_LIST_050329_HPP
       
     8 
       
     9 #include <boost/parameter/aux_/void.hpp>
       
    10 #include <boost/parameter/aux_/result_of0.hpp>
       
    11 #include <boost/parameter/aux_/default.hpp>
       
    12 #include <boost/parameter/aux_/parameter_requirements.hpp>
       
    13 #include <boost/parameter/aux_/yesno.hpp>
       
    14 #include <boost/parameter/config.hpp>
       
    15 
       
    16 #include <boost/mpl/apply.hpp>
       
    17 #include <boost/mpl/assert.hpp>
       
    18 #include <boost/mpl/begin.hpp>
       
    19 #include <boost/mpl/end.hpp>
       
    20 #include <boost/mpl/iterator_tags.hpp>
       
    21 
       
    22 #include <boost/type_traits/add_reference.hpp>
       
    23 #include <boost/type_traits/is_same.hpp>
       
    24 #include <boost/type_traits/is_base_and_derived.hpp>
       
    25 #include <boost/preprocessor/repetition/enum_params.hpp>
       
    26 #include <boost/preprocessor/facilities/intercept.hpp>
       
    27 
       
    28 namespace boost { namespace parameter { 
       
    29 
       
    30 // Forward declaration for aux::arg_list, below.
       
    31 template<class T> struct keyword;
       
    32 
       
    33 namespace aux {
       
    34 
       
    35 // Tag type passed to MPL lambda.
       
    36 struct lambda_tag;
       
    37 
       
    38 //
       
    39 // Structures used to build the tuple of actual arguments.  The
       
    40 // tuple is a nested cons-style list of arg_list specializations
       
    41 // terminated by an empty_arg_list.
       
    42 //
       
    43 // Each specialization of arg_list is derived from its successor in
       
    44 // the list type.  This feature is used along with using
       
    45 // declarations to build member function overload sets that can
       
    46 // match against keywords.
       
    47 //
       
    48   
       
    49 // MPL sequence support
       
    50 struct arg_list_tag;
       
    51 
       
    52 // Terminates arg_list<> and represents an empty list.  Since this
       
    53 // is just the terminating case you might want to look at arg_list
       
    54 // first, to get a feel for what's really happening here.
       
    55 
       
    56 struct empty_arg_list
       
    57 {
       
    58     empty_arg_list() {}
       
    59 
       
    60     // Constructor taking BOOST_PARAMETER_MAX_ARITY empty_arg_list
       
    61     // arguments; this makes initialization
       
    62     empty_arg_list(
       
    63         BOOST_PP_ENUM_PARAMS(
       
    64             BOOST_PARAMETER_MAX_ARITY, void_ BOOST_PP_INTERCEPT
       
    65         ))
       
    66     {}
       
    67 
       
    68     // A metafunction class that, given a keyword and a default
       
    69     // type, returns the appropriate result type for a keyword
       
    70     // lookup given that default
       
    71     struct binding
       
    72     {
       
    73         template<class KW, class Default, class Reference>
       
    74         struct apply
       
    75         {
       
    76             typedef Default type;
       
    77         };
       
    78     };
       
    79 
       
    80 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
       
    81     // Terminator for has_key, indicating that the keyword is unique
       
    82     template <class KW>
       
    83     static no_tag has_key(KW*);
       
    84 #endif
       
    85     
       
    86 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
       
    87     || (BOOST_WORKAROUND(__GNUC__, < 3)) \
       
    88     || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
       
    89     
       
    90     // The overload set technique doesn't work with these older
       
    91     // compilers, so they need some explicit handholding.
       
    92       
       
    93     // A metafunction class that, given a keyword, returns the type
       
    94     // of the base sublist whose get() function can produce the
       
    95     // value for that key
       
    96     struct key_owner
       
    97     {
       
    98         template<class KW>
       
    99         struct apply
       
   100         {
       
   101             typedef empty_arg_list type;
       
   102         };
       
   103     };
       
   104 
       
   105     template <class K, class T>
       
   106     T& get(default_<K,T> x) const
       
   107     {
       
   108         return x.value;
       
   109     }
       
   110 
       
   111     template <class K, class F>
       
   112     typename result_of0<F>::type
       
   113     get(lazy_default<K,F> x) const
       
   114     {
       
   115         return x.compute_default();
       
   116     }
       
   117 #endif
       
   118 
       
   119     // If this function is called, it means there is no argument
       
   120     // in the list that matches the supplied keyword. Just return
       
   121     // the default value.
       
   122     template <class K, class Default>
       
   123     Default& operator[](default_<K, Default> x) const
       
   124     {
       
   125         return x.value;
       
   126     }
       
   127 
       
   128     // If this function is called, it means there is no argument
       
   129     // in the list that matches the supplied keyword. Just evaluate
       
   130     // and return the default value.
       
   131     template <class K, class F>
       
   132     typename result_of0<F>::type
       
   133     operator[](
       
   134         BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
       
   135     {
       
   136         return x.compute_default();
       
   137     }
       
   138 
       
   139     // No argument corresponding to ParameterRequirements::key_type
       
   140     // was found if we match this overload, so unless that parameter
       
   141     // has a default, we indicate that the actual arguments don't
       
   142     // match the function's requirements.
       
   143     template <class ParameterRequirements, class ArgPack>
       
   144     static typename ParameterRequirements::has_default
       
   145     satisfies(ParameterRequirements*, ArgPack*);
       
   146 
       
   147     // MPL sequence support
       
   148     typedef empty_arg_list type;   // convenience
       
   149     typedef arg_list_tag tag; // For dispatching to sequence intrinsics
       
   150 };
       
   151 
       
   152 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
       
   153 template<class KW>
       
   154 no_tag operator*(empty_arg_list, KW*);
       
   155 #endif
       
   156 
       
   157 // Forward declaration for arg_list::operator,
       
   158 template <class KW, class T>
       
   159 struct tagged_argument;
       
   160 
       
   161 // Forward declaration for arg_list::operator[], with
       
   162 // IS_XXX helper
       
   163 struct maybe_base;
       
   164 
       
   165 template <class T>
       
   166 struct is_maybe
       
   167   : is_base_and_derived<maybe_base, T>
       
   168 {};
       
   169 
       
   170 template <class T>
       
   171 struct get_reference
       
   172 {
       
   173     typedef typename T::reference type;
       
   174 };
       
   175 
       
   176 // A tuple of tagged arguments, terminated with empty_arg_list.
       
   177 // Every TaggedArg is an instance of tagged_argument<>.
       
   178 template <class TaggedArg, class Next = empty_arg_list>
       
   179 struct arg_list : Next
       
   180 {
       
   181     typedef arg_list<TaggedArg,Next> self;
       
   182     typedef typename TaggedArg::key_type key_type;
       
   183 
       
   184     typedef typename is_maybe<typename TaggedArg::value_type>::type holds_maybe;
       
   185 
       
   186     typedef typename mpl::eval_if<
       
   187         holds_maybe
       
   188       , get_reference<typename TaggedArg::value_type>
       
   189       , get_reference<TaggedArg>
       
   190     >::type reference;
       
   191 
       
   192     typedef typename mpl::if_<
       
   193         holds_maybe
       
   194       , reference
       
   195       , typename TaggedArg::value_type
       
   196     >::type value_type;
       
   197 
       
   198     TaggedArg arg;      // Stores the argument
       
   199 
       
   200     // Store the arguments in successive nodes of this list
       
   201     template< // class A0, class A1, ...
       
   202         BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)
       
   203     >
       
   204     arg_list( // A0& a0, A1& a1, ...
       
   205         BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PARAMETER_MAX_ARITY, A, & a)
       
   206     )
       
   207       : Next( // a1, a2, ...
       
   208             BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PARAMETER_MAX_ARITY, a)
       
   209           , void_reference()
       
   210         )
       
   211       , arg(a0)
       
   212     {}
       
   213 
       
   214     // Create a new list by prepending arg to a copy of tail.  Used
       
   215     // when incrementally building this structure with the comma
       
   216     // operator.
       
   217     arg_list(TaggedArg arg, Next const& tail)
       
   218       : Next(tail)
       
   219       , arg(arg)
       
   220     {}
       
   221 
       
   222     // A metafunction class that, given a keyword and a default
       
   223     // type, returns the appropriate result type for a keyword
       
   224     // lookup given that default
       
   225     struct binding
       
   226     {
       
   227         template <class KW, class Default, class Reference>
       
   228         struct apply
       
   229         {
       
   230           typedef typename mpl::eval_if<
       
   231                 boost::is_same<KW, key_type>
       
   232               , mpl::if_<Reference, reference, value_type>
       
   233               , mpl::apply_wrap3<typename Next::binding, KW, Default, Reference>
       
   234           >::type type;
       
   235         };
       
   236     };
       
   237 
       
   238 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && !BOOST_WORKAROUND(__GNUC__, == 2)
       
   239 # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
       
   240     friend yes_tag operator*(arg_list, key_type*);
       
   241 #  define BOOST_PARAMETER_CALL_HAS_KEY(next, key) (*(next*)0 * (key*)0)
       
   242 # else
       
   243     // Overload for key_type, so the assert below will fire if the
       
   244     // same keyword is used again
       
   245     static yes_tag has_key(key_type*);
       
   246     using Next::has_key;
       
   247     
       
   248 #  define BOOST_PARAMETER_CALL_HAS_KEY(next, key) next::has_key((key*)0)  
       
   249 # endif
       
   250 
       
   251     BOOST_MPL_ASSERT_MSG(
       
   252         sizeof(BOOST_PARAMETER_CALL_HAS_KEY(Next,key_type)) == sizeof(no_tag)
       
   253       , duplicate_keyword, (key_type)
       
   254     );
       
   255 
       
   256 # undef BOOST_PARAMETER_CALL_HAS_KEY
       
   257 #endif
       
   258     //
       
   259     // Begin implementation of indexing operators for looking up
       
   260     // specific arguments by name
       
   261     //
       
   262 
       
   263     // Helpers that handle the case when TaggedArg is 
       
   264     // empty<T>.
       
   265     template <class D>
       
   266     reference get_default(D const&, mpl::false_) const
       
   267     {
       
   268         return arg.value;
       
   269     }
       
   270 
       
   271     template <class D>
       
   272     reference get_default(D const& d, mpl::true_) const
       
   273     {
       
   274         return arg.value ? arg.value.get() : arg.value.construct(d.value);
       
   275     }
       
   276 
       
   277 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
       
   278     || BOOST_WORKAROUND(__GNUC__, < 3) \
       
   279     || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
       
   280     // These older compilers don't support the overload set creation
       
   281     // idiom well, so we need to do all the return type calculation
       
   282     // for the compiler and dispatch through an outer function template
       
   283 
       
   284     // A metafunction class that, given a keyword, returns the base
       
   285     // sublist whose get() function can produce the value for that
       
   286     // key.
       
   287     struct key_owner
       
   288     {
       
   289         template<class KW>
       
   290         struct apply
       
   291         {
       
   292           typedef typename mpl::eval_if<
       
   293                 boost::is_same<KW, key_type>
       
   294               , mpl::identity<arg_list<TaggedArg,Next> >
       
   295               , mpl::apply_wrap1<typename Next::key_owner,KW>
       
   296           >::type type;
       
   297         };
       
   298     };
       
   299 
       
   300     // Outer indexing operators that dispatch to the right node's
       
   301     // get() function.
       
   302     template <class KW>
       
   303     typename mpl::apply_wrap3<binding, KW, void_, mpl::true_>::type
       
   304     operator[](keyword<KW> const& x) const
       
   305     {
       
   306         typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
       
   307         return sublist.get(x);
       
   308     }
       
   309 
       
   310     template <class KW, class Default>
       
   311     typename mpl::apply_wrap3<binding, KW, Default&, mpl::true_>::type
       
   312     operator[](default_<KW, Default> x) const
       
   313     {
       
   314         typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
       
   315         return sublist.get(x);
       
   316     }
       
   317 
       
   318     template <class KW, class F>
       
   319     typename mpl::apply_wrap3<
       
   320         binding,KW
       
   321       , typename result_of0<F>::type
       
   322       , mpl::true_
       
   323     >::type
       
   324     operator[](lazy_default<KW,F> x) const
       
   325     {
       
   326         typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
       
   327         return sublist.get(x);
       
   328     }
       
   329 
       
   330     // These just return the stored value; when empty_arg_list is
       
   331     // reached, indicating no matching argument was passed, the
       
   332     // default is returned, or if no default_ or lazy_default was
       
   333     // passed, compilation fails.
       
   334     reference get(keyword<key_type> const&) const
       
   335     {
       
   336         BOOST_MPL_ASSERT_NOT((holds_maybe));
       
   337         return arg.value;
       
   338     }
       
   339 
       
   340     template <class Default>
       
   341     reference get(default_<key_type,Default> const& d) const
       
   342     {
       
   343         return get_default(d, holds_maybe());        
       
   344     }
       
   345 
       
   346     template <class Default>
       
   347     reference get(lazy_default<key_type, Default>) const
       
   348     {
       
   349         return arg.value;
       
   350     }
       
   351     
       
   352 #else
       
   353 
       
   354     reference operator[](keyword<key_type> const&) const
       
   355     {
       
   356         BOOST_MPL_ASSERT_NOT((holds_maybe));
       
   357         return arg.value;
       
   358     }
       
   359 
       
   360     template <class Default>
       
   361     reference operator[](default_<key_type, Default> const& d) const
       
   362     {
       
   363         return get_default(d, holds_maybe());
       
   364     }
       
   365 
       
   366     template <class Default>
       
   367     reference operator[](lazy_default<key_type, Default>) const
       
   368     {
       
   369         return arg.value;
       
   370     }
       
   371 
       
   372     // Builds an overload set including operator[]s defined in base
       
   373     // classes.
       
   374     using Next::operator[];
       
   375 
       
   376     //
       
   377     // End of indexing support
       
   378     //
       
   379 
       
   380 
       
   381     //
       
   382     // For parameter_requirements matching this node's key_type,
       
   383     // return a bool constant wrapper indicating whether the
       
   384     // requirements are satisfied by TaggedArg.  Used only for
       
   385     // compile-time computation and never really called, so a
       
   386     // declaration is enough.
       
   387     //
       
   388     template <class HasDefault, class Predicate, class ArgPack>
       
   389     static typename mpl::apply_wrap2<
       
   390         typename mpl::lambda<Predicate, lambda_tag>::type
       
   391       , value_type, ArgPack
       
   392     >::type
       
   393     satisfies(
       
   394         parameter_requirements<key_type,Predicate,HasDefault>*
       
   395       , ArgPack*
       
   396     );
       
   397 
       
   398     // Builds an overload set including satisfies functions defined
       
   399     // in base classes.
       
   400     using Next::satisfies;
       
   401 #endif
       
   402 
       
   403     // Comma operator to compose argument list without using parameters<>.
       
   404     // Useful for argument lists with undetermined length.
       
   405     template <class KW, class T2>
       
   406     arg_list<tagged_argument<KW, T2>, self> 
       
   407     operator,(tagged_argument<KW,T2> x) const
       
   408     {
       
   409         return arg_list<tagged_argument<KW,T2>, self>(x, *this);
       
   410     }
       
   411 
       
   412     // MPL sequence support
       
   413     typedef self type;             // Convenience for users
       
   414     typedef Next tail_type;        // For the benefit of iterators
       
   415     typedef arg_list_tag tag; // For dispatching to sequence intrinsics
       
   416 };
       
   417 
       
   418 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)  // ETI workaround
       
   419 template <> struct arg_list<int,int> {};
       
   420 #endif 
       
   421 
       
   422 // MPL sequence support
       
   423 template <class ArgumentPack>
       
   424 struct arg_list_iterator
       
   425 {
       
   426     typedef mpl::forward_iterator_tag category;
       
   427 
       
   428     // The incremented iterator
       
   429     typedef arg_list_iterator<typename ArgumentPack::tail_type> next;
       
   430     
       
   431     // dereferencing yields the key type
       
   432     typedef typename ArgumentPack::key_type type;
       
   433 };
       
   434 
       
   435 template <>
       
   436 struct arg_list_iterator<empty_arg_list> {};
       
   437 
       
   438 }} // namespace parameter::aux
       
   439 
       
   440 // MPL sequence support
       
   441 namespace mpl
       
   442 {
       
   443   template <>
       
   444   struct begin_impl<parameter::aux::arg_list_tag>
       
   445   {
       
   446       template <class S>
       
   447       struct apply
       
   448       {
       
   449           typedef parameter::aux::arg_list_iterator<S> type;
       
   450       };
       
   451   };
       
   452 
       
   453   template <>
       
   454   struct end_impl<parameter::aux::arg_list_tag>
       
   455   {
       
   456       template <class>
       
   457       struct apply
       
   458       {
       
   459           typedef parameter::aux::arg_list_iterator<parameter::aux::empty_arg_list> type;
       
   460       };
       
   461   };
       
   462 }
       
   463 
       
   464 } // namespace boost
       
   465 
       
   466 #endif // ARG_LIST_050329_HPP
       
   467