source: NonGTP/Boost/boost/lambda/detail/lambda_traits.hpp @ 857

Revision 857, 13.7 KB checked in by igarcia, 18 years ago (diff)
Line 
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
20namespace boost {
21namespace lambda {
22
23// -- if construct ------------------------------------------------
24// Proposed by Krzysztof Czarnecki and Ulrich Eisenecker
25
26namespace detail {
27
28template <bool If, class Then, class Else> struct IF { typedef Then RET; };
29
30template <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)
42template<class T>
43struct IF_type_
44{
45  typedef typename T::type type;
46};
47
48
49template<bool C, class T, class E>
50struct 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
57template <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
64template<class T>
65struct IF_value_
66{
67  BOOST_STATIC_CONSTANT(int, value = T::value);
68};
69
70
71template<bool C, class T, class E>
72struct 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:
81template<class T> class remove_reference_if_valid
82{
83
84  typedef typename boost::remove_reference<T>::type plainT;
85public:
86  typedef typename IF<
87    boost::is_function<plainT>::value,
88    T,
89    plainT
90  >::RET type;
91
92};
93
94
95template<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
104template<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
112template<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
121template <class T> struct is_lambda_functor_ {
122  BOOST_STATIC_CONSTANT(bool, value = false);
123};
124   
125template <class Arg> struct is_lambda_functor_<lambda_functor<Arg> > {
126  BOOST_STATIC_CONSTANT(bool, value = true);
127};
128   
129} // end detail
130
131   
132template <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
141namespace 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
158template<class T1, class T2>
159struct parameter_traits_ {
160  typedef T2 type;
161};
162
163// Do not instantiate with reference types
164template<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
171template<class T, int n, class Any> struct parameter_traits_<T[n], Any> {
172  typedef T (&type)[n];
173};
174   
175template<class T, int n, class Any>
176struct parameter_traits_<const T[n], Any> {
177  typedef const T (&type)[n];
178};
179
180template<class T, int n, class Any>
181struct parameter_traits_<volatile T[n], Any> {
182  typedef volatile  T (&type)[n];
183};
184template<class T, int n, class Any>
185struct parameter_traits_<const volatile T[n], Any> {
186  typedef const volatile T (&type)[n];
187};
188
189
190template<class T, class Any>
191struct parameter_traits_<boost::reference_wrapper<T>, Any >{
192  typedef T& type;
193};
194
195template<class T, class Any>
196struct parameter_traits_<const boost::reference_wrapper<T>, Any >{
197  typedef T& type;
198};
199
200template<class T, class Any>
201struct parameter_traits_<volatile boost::reference_wrapper<T>, Any >{
202  typedef T& type;
203};
204
205template<class T, class Any>
206struct parameter_traits_<const volatile boost::reference_wrapper<T>, Any >{
207  typedef T& type;
208};
209
210template<class Any>
211struct parameter_traits_<void, Any> {
212  typedef void type;
213};
214
215template<class Arg, class Any>
216struct parameter_traits_<lambda_functor<Arg>, Any > {
217  typedef lambda_functor<Arg> type;
218};
219
220template<class Arg, class Any>
221struct parameter_traits_<const lambda_functor<Arg>, Any > {
222  typedef lambda_functor<Arg> type;
223};
224
225// Are the volatile versions needed?
226template<class Arg, class Any>
227struct parameter_traits_<volatile lambda_functor<Arg>, Any > {
228  typedef lambda_functor<Arg> type;
229};
230
231template<class Arg, class Any>
232struct 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
250template<class T>
251struct 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.   
266template<class T, int n>  struct const_copy_argument <T[n]> {
267  typedef const T (&type)[n];
268};
269template<class T, int n>  struct const_copy_argument <volatile T[n]> {
270     typedef const volatile T (&type)[n];
271};
272   
273template<class T>
274struct const_copy_argument<T&> {};
275// do not instantiate with references
276  //  typedef typename detail::generate_error<T&>::references_not_allowed type;
277
278
279template<>
280struct 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
286template<class T>
287struct bound_argument_conversion {
288  typedef typename const_copy_argument<T>::type type;
289};
290
291template<class T>
292struct 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&
301template<class T>
302struct reference_argument {
303  typedef typename detail::parameter_traits_<T, T&>::type type;
304};
305
306template<class T>
307struct reference_argument<T&> {
308  typedef typename detail::generate_error<T&>::references_not_allowed type;
309};
310
311template<class Arg>
312struct reference_argument<lambda_functor<Arg> > {
313  typedef lambda_functor<Arg> type;
314};
315
316template<class Arg>
317struct reference_argument<const lambda_functor<Arg> > {
318  typedef lambda_functor<Arg> type;
319};
320
321// Are the volatile versions needed?
322template<class Arg>
323struct reference_argument<volatile lambda_functor<Arg> > {
324  typedef lambda_functor<Arg> type;
325};
326
327template<class Arg>
328struct reference_argument<const volatile lambda_functor<Arg> > {
329  typedef lambda_functor<Arg> type;
330};
331
332template<>
333struct reference_argument<void> {
334  typedef void type;
335};
336
337namespace detail {
338   
339// Array to pointer conversion
340template <class T>
341struct array_to_pointer {
342  typedef T type;
343};
344
345template <class T, int N>
346struct array_to_pointer <const T[N]> {
347  typedef const T* type;
348};
349template <class T, int N>
350struct array_to_pointer <T[N]> {
351  typedef T* type;
352};
353
354template <class T, int N>
355struct array_to_pointer <const T (&) [N]> {
356  typedef const T* type;
357};
358template <class T, int N>
359struct 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
387template<class T>
388struct bind_traits {
389  typedef const T type;
390};
391
392template<class T>
393struct 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
399template<>
400struct 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
406template<>
407struct 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.
415template<class T, int n>  struct bind_traits <T[n]> {
416  typedef const T (&type)[n];
417};
418
419template<class T, int n>
420struct bind_traits<const T[n]> {
421  typedef const T (&type)[n];
422};
423
424template<class T, int n>  struct bind_traits<volatile T[n]> {
425  typedef const volatile T (&type)[n];
426};
427
428template<class T, int n>
429struct bind_traits<const volatile T[n]> {
430  typedef const volatile T (&type)[n];
431};
432
433template<class T>
434struct bind_traits<reference_wrapper<T> >{
435  typedef T& type;
436};
437
438template<class T>
439struct bind_traits<const reference_wrapper<T> >{
440  typedef T& type;
441};
442
443template<>
444struct bind_traits<void> {
445  typedef void type;
446};
447
448
449
450template <
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>
456struct 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
483template <
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>
489class 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
504public:
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   
519template <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
Note: See TracBrowser for help on using the repository browser.