source: NonGTP/Boost/boost/parameter/aux_/arg_list.hpp @ 857

Revision 857, 9.9 KB checked in by igarcia, 18 years ago (diff)
Line 
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/config.hpp>
14
15#include <boost/mpl/apply.hpp>
16
17#include <boost/type_traits/add_reference.hpp>
18#include <boost/type_traits/is_same.hpp>
19
20#include <boost/preprocessor/repetition/enum_params.hpp>
21#include <boost/preprocessor/facilities/intercept.hpp>
22
23namespace boost { namespace parameter {
24
25// Forward declaration for aux::arg_list, below.
26template<class T> struct keyword;
27
28namespace aux {
29
30//
31// Structures used to build the tuple of actual arguments.  The
32// tuple is a nested cons-style list of arg_list specializations
33// terminated by an empty_arg_list.
34//
35// Each specialization of arg_list is derived from its successor in
36// the list type.  This feature is used along with using
37// declarations to build member function overload sets that can
38// match against keywords.
39//
40 
41// Terminates arg_list<> and represents an empty list.  Since this
42// is just the terminating case you might want to look at arg_list
43// first, to get a feel for what's really happening here.
44struct empty_arg_list
45{
46    empty_arg_list() {}
47
48    // Constructor taking BOOST_PARAMETER_MAX_ARITY empty_arg_list
49    // arguments; this makes initialization
50    empty_arg_list(
51        BOOST_PP_ENUM_PARAMS(
52            BOOST_PARAMETER_MAX_ARITY, void_ BOOST_PP_INTERCEPT
53        ))
54    {}
55
56    // A metafunction class that, given a keyword and a default
57    // type, returns the appropriate result type for a keyword
58    // lookup given that default
59    struct binding
60    {
61        template<class KW, class Default>
62        struct apply
63        {
64            typedef Default type;
65        };
66    };
67
68#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
69    || (BOOST_WORKAROUND(__GNUC__, < 3)) \
70    || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
71   
72    // The overload set technique doesn't work with these older
73    // compilers, so they need some explicit handholding.
74     
75    // A metafunction class that, given a keyword, returns the type
76    // of the base sublist whose get() function can produce the
77    // value for that key
78    struct key_owner
79    {
80        template<class KW>
81        struct apply
82        {
83            typedef empty_arg_list type;
84        };
85    };
86
87    template <class K, class T>
88    T& get(default_<K,T> x) const
89    {
90        return x.value;
91    }
92
93    template <class K, class F>
94    typename result_of0<F>::type
95    get(lazy_default<K,F> x) const
96    {
97        return x.compute_default();
98    }
99#endif
100
101    // If this function is called, it means there is no argument
102    // in the list that matches the supplied keyword. Just return
103    // the default value.
104    template <class K, class Default>
105    Default& operator[](default_<K, Default> x) const
106    {
107        return x.value;
108    }
109
110    // If this function is called, it means there is no argument
111    // in the list that matches the supplied keyword. Just evaluate
112    // and return the default value.
113    template <class K, class F>
114    typename result_of0<F>::type
115    operator[](
116        BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
117    {
118        return x.compute_default();
119    }
120
121    // No argument corresponding to ParameterRequirements::key_type
122    // was found if we match this overload, so unless that parameter
123    // has a default, we indicate that the actual arguments don't
124    // match the function's requirements.
125    template <class ParameterRequirements>
126    static typename ParameterRequirements::has_default
127    satisfies(ParameterRequirements*);
128};
129
130// Forward declaration for arg_list::operator,
131template <class KW, class T>
132struct tagged_argument;
133
134// A tuple of tagged arguments, terminated with empty_arg_list.
135// Every TaggedArg is an instance of tagged_argument<>.
136template <class TaggedArg, class Next = empty_arg_list>
137struct arg_list : Next
138{
139    typedef arg_list<TaggedArg,Next> self;
140    typedef typename TaggedArg::key_type key_type;
141    typedef typename TaggedArg::value_type value_type;
142    typedef typename TaggedArg::reference reference;
143
144    TaggedArg arg;      // Stores the argument
145
146    // Store the arguments in successive nodes of this list
147    template< // class A0, class A1, ...
148        BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A)
149    >
150    arg_list( // A0 const& a0, A1 const& a1, ...
151        BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PARAMETER_MAX_ARITY, A, const & a)
152    )
153      : Next( // a1, a2, ...
154            BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PARAMETER_MAX_ARITY, a)
155          , void_()
156        )
157      , arg(a0)
158    {}
159
160    // Create a new list by prepending arg to a copy of tail.  Used
161    // when incrementally building this structure with the comma
162    // operator.
163    arg_list(TaggedArg arg, Next const& tail)
164      : Next(tail)
165      , arg(arg)
166    {}
167
168
169    // A metafunction class that, given a keyword and a default
170    // type, returns the appropriate result type for a keyword
171    // lookup given that default
172    struct binding
173    {
174        template <class KW, class Default>
175        struct apply
176        {
177          typedef typename mpl::eval_if<
178                boost::is_same<KW, key_type>
179              , mpl::identity<reference>
180              , mpl::apply_wrap2<typename Next::binding, KW, Default>
181          >::type type;
182        };
183    };
184
185    //
186    // Begin implementation of indexing operators for looking up
187    // specific arguments by name
188    //
189
190#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
191    || BOOST_WORKAROUND(__GNUC__, < 3) \
192    || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
193    // These older compilers don't support the overload set creation
194    // idiom well, so we need to do all the return type calculation
195    // for the compiler and dispatch through an outer function template
196
197    // A metafunction class that, given a keyword, returns the base
198    // sublist whose get() function can produce the value for that
199    // key.
200    struct key_owner
201    {
202        template<class KW>
203        struct apply
204        {
205          typedef typename mpl::eval_if<
206                boost::is_same<KW, key_type>
207              , mpl::identity<arg_list<TaggedArg,Next> >
208              , mpl::apply_wrap1<typename Next::key_owner,KW>
209          >::type type;
210        };
211    };
212
213    // Outer indexing operators that dispatch to the right node's
214    // get() function.
215    template <class KW>
216    typename mpl::apply_wrap2<binding, KW, void_>::type
217    operator[](keyword<KW> const& x) const
218    {
219        typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
220        return sublist.get(x);
221    }
222
223    template <class KW, class Default>
224    typename mpl::apply_wrap2<binding, KW, Default&>::type
225    operator[](default_<KW, Default> x) const
226    {
227        typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
228        return sublist.get(x);
229    }
230
231    template <class KW, class F>
232    typename mpl::apply_wrap2<
233        binding,KW
234      , typename result_of0<F>::type
235    >::type
236    operator[](lazy_default<KW,F> x) const
237    {
238        typename mpl::apply_wrap1<key_owner, KW>::type const& sublist = *this;
239        return sublist.get(x);
240    }
241
242    // These just return the stored value; when empty_arg_list is
243    // reached, indicating no matching argument was passed, the
244    // default is returned, or if no default_ or lazy_default was
245    // passed, compilation fails.
246    reference get(keyword<key_type> const&) const
247    {
248        return arg.value;
249    }
250
251    template <class Default>
252    reference get(default_<key_type,Default>) const
253    {
254        return arg.value;
255    }
256
257    template <class Default>
258    reference get(lazy_default<key_type, Default>) const
259    {
260        return arg.value;
261    }
262   
263#else
264
265    reference operator[](keyword<key_type> const&) const
266    {
267        return arg.value;
268    }
269
270    template <class Default>
271    reference operator[](default_<key_type, Default>) const
272    {
273        return arg.value;
274    }
275
276    template <class Default>
277    reference operator[](lazy_default<key_type, Default>) const
278    {
279        return arg.value;
280    }
281
282    // Builds an overload set including operator[]s defined in base
283    // classes.
284    using Next::operator[];
285
286    //
287    // End of indexing support
288    //
289
290
291    //
292    // For parameter_requirements matching this node's key_type,
293    // return a bool constant wrapper indicating whether the
294    // requirements are satisfied by TaggedArg.  Used only for
295    // compile-time computation and never really called, so a
296    // declaration is enough.
297    //
298    template <class HasDefault, class Predicate>
299    static typename mpl::apply1<Predicate, value_type>::type
300    satisfies(
301        parameter_requirements<key_type,Predicate,HasDefault>*
302    );
303
304    // Builds an overload set including satisfies functions defined
305    // in base classes.
306    using Next::satisfies;
307#endif
308
309    // Comma operator to compose argument list without using parameters<>.
310    // Useful for argument lists with undetermined length.
311    template <class KW, class T2>
312    arg_list<tagged_argument<KW, T2>, self>
313    operator,(tagged_argument<KW,T2> x)
314    {
315        return arg_list<tagged_argument<KW,T2>, self>(x, *this);
316    }
317};
318
319#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)  // ETI workaround
320template <> struct arg_list<int,int> {};
321#endif
322
323}}} // namespace boost::parameter::aux
324
325#endif // ARG_LIST_050329_HPP
326
Note: See TracBrowser for help on using the repository browser.