Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / lambda / detail / lambda_traits.hpp
1 // - lambda_traits.hpp --- Boost Lambda Library ----------------------------
2 //
3 // Copyright (C) 1999, 2000 Jaakko J√§rvi (jaakko.jarvi@cs.utu.fi)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // For more information, see www.boost.org
10 // -------------------------------------------------------------------------
11
12 #ifndef BOOST_LAMBDA_LAMBDA_TRAITS_HPP
13 #define BOOST_LAMBDA_LAMBDA_TRAITS_HPP
14
15 #include "boost/type_traits/transform_traits.hpp"
16 #include "boost/type_traits/cv_traits.hpp"
17 #include "boost/type_traits/function_traits.hpp"
18 #include "boost/type_traits/object_traits.hpp"
19
20 namespace boost {
21 namespace lambda {
22
23 // -- if construct ------------------------------------------------
24 // Proposed by Krzysztof Czarnecki and Ulrich Eisenecker
25
26 namespace detail {
27
28 template <bool If, class Then, class Else> struct IF { typedef Then RET; };
29
30 template <class Then, class Else> struct IF<false, Then, Else> {
31   typedef Else RET;
32 };
33
34
35 // An if construct that doesn't instantiate the non-matching template:
36
37 // Called as: 
38 //  IF_type<condition, A, B>::type 
39 // The matching template must define the typeded 'type'
40 // I.e. A::type if condition is true, B::type if condition is false
41 // Idea from Vesa Karvonen (from C&E as well I guess)
42 template<class T>
43 struct IF_type_
44 {
45   typedef typename T::type type;
46 };
47
48
49 template<bool C, class T, class E>
50 struct IF_type
51 {
52   typedef typename
53     IF_type_<typename IF<C, T, E>::RET >::type type;
54 };
55
56 // helper that can be used to give typedef T to some type
57 template <class T> struct identity_mapping { typedef T type; };
58
59 // An if construct for finding an integral constant 'value'
60 // Does not instantiate the non-matching branch
61 // Called as IF_value<condition, A, B>::value
62 // If condition is true A::value must be defined, otherwise B::value
63
64 template<class T>
65 struct IF_value_
66 {
67   BOOST_STATIC_CONSTANT(int, value = T::value);
68 };
69
70
71 template<bool C, class T, class E>
72 struct IF_value
73 {
74   BOOST_STATIC_CONSTANT(int, value = (IF_value_<typename IF<C, T, E>::RET>::value));
75 };
76
77
78 // --------------------------------------------------------------
79
80 // removes reference from other than function types:
81 template<class T> class remove_reference_if_valid
82 {
83
84   typedef typename boost::remove_reference<T>::type plainT;
85 public:
86   typedef typename IF<
87     boost::is_function<plainT>::value,
88     T,
89     plainT
90   >::RET type;
91
92 };
93
94
95 template<class T> struct remove_reference_and_cv {
96    typedef typename boost::remove_cv<
97      typename boost::remove_reference<T>::type
98    >::type type;
99 };
100
101
102    
103 // returns a reference to the element of tuple T
104 template<int N, class T> struct tuple_element_as_reference {   
105   typedef typename
106      boost::tuples::access_traits<
107        typename boost::tuples::element<N, T>::type
108      >::non_const_type type;
109 };
110
111 // returns the cv and reverence stripped type of a tuple element
112 template<int N, class T> struct tuple_element_stripped {   
113   typedef typename
114      remove_reference_and_cv<
115        typename boost::tuples::element<N, T>::type
116      >::type type;
117 };
118
119 // is_lambda_functor -------------------------------------------------   
120
121 template <class T> struct is_lambda_functor_ {
122   BOOST_STATIC_CONSTANT(bool, value = false);
123 };
124    
125 template <class Arg> struct is_lambda_functor_<lambda_functor<Arg> > {
126   BOOST_STATIC_CONSTANT(bool, value = true);
127 };
128    
129 } // end detail
130
131    
132 template <class T> struct is_lambda_functor {
133   BOOST_STATIC_CONSTANT(bool, 
134      value = 
135        detail::is_lambda_functor_<
136          typename detail::remove_reference_and_cv<T>::type
137        >::value);
138 };
139    
140
141 namespace detail {
142
143 // -- parameter_traits_ ---------------------------------------------
144
145 // An internal parameter type traits class that respects
146 // the reference_wrapper class.
147
148 // The conversions performed are:
149 // references -> compile_time_error
150 // T1 -> T2, 
151 // reference_wrapper<T> -> T&
152 // const array -> ref to const array
153 // array -> ref to array
154 // function -> ref to function
155
156 // ------------------------------------------------------------------------
157
158 template<class T1, class T2> 
159 struct parameter_traits_ {
160   typedef T2 type;
161 };
162
163 // Do not instantiate with reference types
164 template<class T, class Any> struct parameter_traits_<T&, Any> {
165   typedef typename 
166     generate_error<T&>::
167       parameter_traits_class_instantiated_with_reference_type type;
168 };
169
170 // Arrays can't be stored as plain types; convert them to references
171 template<class T, int n, class Any> struct parameter_traits_<T[n], Any> {
172   typedef T (&type)[n];
173 };
174    
175 template<class T, int n, class Any> 
176 struct parameter_traits_<const T[n], Any> {
177   typedef const T (&type)[n];
178 };
179
180 template<class T, int n, class Any> 
181 struct parameter_traits_<volatile T[n], Any> {
182   typedef volatile  T (&type)[n];
183 };
184 template<class T, int n, class Any> 
185 struct parameter_traits_<const volatile T[n], Any> {
186   typedef const volatile T (&type)[n];
187 };
188
189
190 template<class T, class Any> 
191 struct parameter_traits_<boost::reference_wrapper<T>, Any >{
192   typedef T& type;
193 };
194
195 template<class T, class Any> 
196 struct parameter_traits_<const boost::reference_wrapper<T>, Any >{
197   typedef T& type;
198 };
199
200 template<class T, class Any> 
201 struct parameter_traits_<volatile boost::reference_wrapper<T>, Any >{
202   typedef T& type;
203 };
204
205 template<class T, class Any> 
206 struct parameter_traits_<const volatile boost::reference_wrapper<T>, Any >{
207   typedef T& type;
208 };
209
210 template<class Any>
211 struct parameter_traits_<void, Any> {
212   typedef void type;
213 };
214
215 template<class Arg, class Any>
216 struct parameter_traits_<lambda_functor<Arg>, Any > {
217   typedef lambda_functor<Arg> type;
218 };
219
220 template<class Arg, class Any>
221 struct parameter_traits_<const lambda_functor<Arg>, Any > {
222   typedef lambda_functor<Arg> type;
223 };
224
225 // Are the volatile versions needed?
226 template<class Arg, class Any>
227 struct parameter_traits_<volatile lambda_functor<Arg>, Any > {
228   typedef lambda_functor<Arg> type;
229 };
230
231 template<class Arg, class Any>
232 struct parameter_traits_<const volatile lambda_functor<Arg>, Any > {
233   typedef lambda_functor<Arg> type;
234 };
235
236 } // end namespace detail
237
238
239 // ------------------------------------------------------------------------
240 // traits classes for lambda expressions (bind functions, operators ...)   
241
242 // must be instantiated with non-reference types
243
244 // The default is const plain type -------------------------
245 // const T -> const T, 
246 // T -> const T, 
247 // references -> compile_time_error
248 // reference_wrapper<T> -> T&
249 // array -> const ref array
250 template<class T>
251 struct const_copy_argument {
252   typedef typename 
253     detail::parameter_traits_<
254       T,
255       typename detail::IF<boost::is_function<T>::value, T&, const T>::RET
256     >::type type;
257 };
258
259 // T may be a function type. Without the IF test, const would be added 
260 // to a function type, which is illegal.
261
262 // all arrays are converted to const.
263 // This traits template is used for 'const T&' parameter passing 
264 // and thus the knowledge of the potential 
265 // non-constness of an actual argument is lost.   
266 template<class T, int n>  struct const_copy_argument <T[n]> {
267   typedef const T (&type)[n];
268 };
269 template<class T, int n>  struct const_copy_argument <volatile T[n]> {
270      typedef const volatile T (&type)[n];
271 };
272    
273 template<class T>
274 struct const_copy_argument<T&> {};
275 // do not instantiate with references
276   //  typedef typename detail::generate_error<T&>::references_not_allowed type;
277
278
279 template<>
280 struct const_copy_argument<void> {
281   typedef void type;
282 };
283
284
285 // Does the same as const_copy_argument, but passes references through as such
286 template<class T>
287 struct bound_argument_conversion {
288   typedef typename const_copy_argument<T>::type type; 
289 };
290
291 template<class T>
292 struct bound_argument_conversion<T&> {
293   typedef T& type; 
294 };
295    
296 // The default is non-const reference -------------------------
297 // const T -> const T&, 
298 // T -> T&, 
299 // references -> compile_time_error
300 // reference_wrapper<T> -> T&
301 template<class T>
302 struct reference_argument {
303   typedef typename detail::parameter_traits_<T, T&>::type type; 
304 };
305
306 template<class T>
307 struct reference_argument<T&> {
308   typedef typename detail::generate_error<T&>::references_not_allowed type; 
309 };
310
311 template<class Arg>
312 struct reference_argument<lambda_functor<Arg> > {
313   typedef lambda_functor<Arg> type;
314 };
315
316 template<class Arg>
317 struct reference_argument<const lambda_functor<Arg> > {
318   typedef lambda_functor<Arg> type;
319 };
320
321 // Are the volatile versions needed?
322 template<class Arg>
323 struct reference_argument<volatile lambda_functor<Arg> > {
324   typedef lambda_functor<Arg> type;
325 };
326
327 template<class Arg>
328 struct reference_argument<const volatile lambda_functor<Arg> > {
329   typedef lambda_functor<Arg> type;
330 };
331
332 template<>
333 struct reference_argument<void> {
334   typedef void type;
335 };
336
337 namespace detail {
338    
339 // Array to pointer conversion
340 template <class T>
341 struct array_to_pointer { 
342   typedef T type;
343 };
344
345 template <class T, int N>
346 struct array_to_pointer <const T[N]> { 
347   typedef const T* type;
348 };
349 template <class T, int N>
350 struct array_to_pointer <T[N]> { 
351   typedef T* type;
352 };
353
354 template <class T, int N>
355 struct array_to_pointer <const T (&) [N]> { 
356   typedef const T* type;
357 };
358 template <class T, int N>
359 struct array_to_pointer <T (&) [N]> { 
360   typedef T* type;
361 };
362
363
364 // ---------------------------------------------------------------------------
365 // The call_traits for bind
366 // Respects the reference_wrapper class.
367
368 // These templates are used outside of bind functions as well.
369 // the bind_tuple_mapper provides a shorter notation for default
370 // bound argument storing semantics, if all arguments are treated
371 // uniformly.
372
373 // from template<class T> foo(const T& t) : bind_traits<const T>::type
374 // from template<class T> foo(T& t) : bind_traits<T>::type
375
376 // Conversions:
377 // T -> const T,
378 // cv T -> cv T, 
379 // T& -> T& 
380 // reference_wrapper<T> -> T&
381 // const reference_wrapper<T> -> T&
382 // array -> const ref array
383
384 // make bound arguments const, this is a deliberate design choice, the
385 // purpose is to prevent side effects to bound arguments that are stored
386 // as copies
387 template<class T>
388 struct bind_traits {
389   typedef const T type; 
390 };
391
392 template<class T>
393 struct bind_traits<T&> {
394   typedef T& type; 
395 };
396
397 // null_types are an exception, we always want to store them as non const
398 // so that other templates can assume that null_type is always without const
399 template<>
400 struct bind_traits<null_type> {
401   typedef null_type type;
402 };
403
404 // the bind_tuple_mapper, bind_type_generators may 
405 // introduce const to null_type
406 template<>
407 struct bind_traits<const null_type> {
408   typedef null_type type;
409 };
410
411 // Arrays can't be stored as plain types; convert them to references.
412 // All arrays are converted to const. This is because bind takes its
413 // parameters as const T& and thus the knowledge of the potential 
414 // non-constness of actual argument is lost.
415 template<class T, int n>  struct bind_traits <T[n]> {
416   typedef const T (&type)[n];
417 };
418
419 template<class T, int n> 
420 struct bind_traits<const T[n]> {
421   typedef const T (&type)[n];
422 };
423
424 template<class T, int n>  struct bind_traits<volatile T[n]> {
425   typedef const volatile T (&type)[n];
426 };
427
428 template<class T, int n> 
429 struct bind_traits<const volatile T[n]> {
430   typedef const volatile T (&type)[n];
431 };
432
433 template<class T> 
434 struct bind_traits<reference_wrapper<T> >{
435   typedef T& type;
436 };
437
438 template<class T> 
439 struct bind_traits<const reference_wrapper<T> >{
440   typedef T& type;
441 };
442
443 template<>
444 struct bind_traits<void> {
445   typedef void type;
446 };
447
448
449
450 template <
451   class T0 = null_type, class T1 = null_type, class T2 = null_type, 
452   class T3 = null_type, class T4 = null_type, class T5 = null_type, 
453   class T6 = null_type, class T7 = null_type, class T8 = null_type, 
454   class T9 = null_type
455 >
456 struct bind_tuple_mapper {
457   typedef
458     tuple<typename bind_traits<T0>::type, 
459           typename bind_traits<T1>::type, 
460           typename bind_traits<T2>::type, 
461           typename bind_traits<T3>::type, 
462           typename bind_traits<T4>::type, 
463           typename bind_traits<T5>::type, 
464           typename bind_traits<T6>::type, 
465           typename bind_traits<T7>::type,
466           typename bind_traits<T8>::type,
467           typename bind_traits<T9>::type> type;
468 };
469
470 // bind_traits, except map const T& -> const T
471   // this is needed e.g. in currying. Const reference arguments can
472   // refer to temporaries, so it is not safe to store them as references.
473   template <class T> struct remove_const_reference {
474     typedef typename bind_traits<T>::type type;
475   };
476
477   template <class T> struct remove_const_reference<const T&> {
478     typedef const T type;
479   };
480
481
482 // maps the bind argument types to the resulting lambda functor type
483 template <
484   class T0 = null_type, class T1 = null_type, class T2 = null_type, 
485   class T3 = null_type, class T4 = null_type, class T5 = null_type, 
486   class T6 = null_type, class T7 = null_type, class T8 = null_type, 
487   class T9 = null_type
488 >
489 class bind_type_generator {
490
491   typedef typename
492   detail::bind_tuple_mapper<
493     T0, T1, T2, T3, T4, T5, T6, T7, T8, T9
494   >::type args_t;
495
496   BOOST_STATIC_CONSTANT(int, nof_elems = boost::tuples::length<args_t>::value);
497
498   typedef 
499     action<
500       nof_elems, 
501       function_action<nof_elems>
502     > action_type;
503
504 public:
505   typedef
506     lambda_functor<
507       lambda_functor_base<
508         action_type, 
509         args_t
510       >
511     > type; 
512     
513 };
514
515
516    
517 } // detail
518    
519 template <class T> inline const T&  make_const(const T& t) { return t; }
520
521
522 } // end of namespace lambda
523 } // end of namespace boost
524
525
526    
527 #endif // BOOST_LAMBDA_TRAITS_HPP