2def8e9fc02a37c47fe5f6c0b1e79b4bf858b930
[senf.git] / boost / parameter / aux_ / arg_list.hpp
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
23 namespace boost { namespace parameter { 
24
25 // Forward declaration for aux::arg_list, below.
26 template<class T> struct keyword;
27
28 namespace 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.
44 struct 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,
131 template <class KW, class T>
132 struct tagged_argument;
133
134 // A tuple of tagged arguments, terminated with empty_arg_list.
135 // Every TaggedArg is an instance of tagged_argument<>.
136 template <class TaggedArg, class Next = empty_arg_list>
137 struct 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
320 template <> struct arg_list<int,int> {};
321 #endif 
322
323 }}} // namespace boost::parameter::aux
324
325 #endif // ARG_LIST_050329_HPP
326