Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:08

0001 // - lambda_traits.hpp --- Boost Lambda Library ----------------------------
0002 //
0003 // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // For more information, see www.boost.org
0010 // -------------------------------------------------------------------------
0011 
0012 #ifndef BOOST_LAMBDA_LAMBDA_TRAITS_HPP
0013 #define BOOST_LAMBDA_LAMBDA_TRAITS_HPP
0014 
0015 #include "boost/type_traits/transform_traits.hpp"
0016 #include "boost/type_traits/cv_traits.hpp"
0017 #include "boost/type_traits/function_traits.hpp"
0018 #include "boost/type_traits/object_traits.hpp"
0019 #include "boost/tuple/tuple.hpp"
0020 
0021 namespace boost {
0022 namespace lambda {
0023 
0024 // -- if construct ------------------------------------------------
0025 // Proposed by Krzysztof Czarnecki and Ulrich Eisenecker
0026 
0027 namespace detail {
0028 
0029 template <bool If, class Then, class Else> struct IF { typedef Then RET; };
0030 
0031 template <class Then, class Else> struct IF<false, Then, Else> {
0032   typedef Else RET;
0033 };
0034 
0035 
0036 // An if construct that doesn't instantiate the non-matching template:
0037 
0038 // Called as: 
0039 //  IF_type<condition, A, B>::type 
0040 // The matching template must define the typeded 'type'
0041 // I.e. A::type if condition is true, B::type if condition is false
0042 // Idea from Vesa Karvonen (from C&E as well I guess)
0043 template<class T>
0044 struct IF_type_
0045 {
0046   typedef typename T::type type;
0047 };
0048 
0049 
0050 template<bool C, class T, class E>
0051 struct IF_type
0052 {
0053   typedef typename
0054     IF_type_<typename IF<C, T, E>::RET >::type type;
0055 };
0056 
0057 // helper that can be used to give typedef T to some type
0058 template <class T> struct identity_mapping { typedef T type; };
0059 
0060 // An if construct for finding an integral constant 'value'
0061 // Does not instantiate the non-matching branch
0062 // Called as IF_value<condition, A, B>::value
0063 // If condition is true A::value must be defined, otherwise B::value
0064 
0065 template<class T>
0066 struct IF_value_
0067 {
0068   BOOST_STATIC_CONSTANT(int, value = T::value);
0069 };
0070 
0071 
0072 template<bool C, class T, class E>
0073 struct IF_value
0074 {
0075   BOOST_STATIC_CONSTANT(int, value = (IF_value_<typename IF<C, T, E>::RET>::value));
0076 };
0077 
0078 
0079 // --------------------------------------------------------------
0080 
0081 // removes reference from other than function types:
0082 template<class T> class remove_reference_if_valid
0083 {
0084 
0085   typedef typename boost::remove_reference<T>::type plainT;
0086 public:
0087   typedef typename IF<
0088     boost::is_function<plainT>::value,
0089     T,
0090     plainT
0091   >::RET type;
0092 
0093 };
0094 
0095 
0096 template<class T> struct remove_reference_and_cv {
0097    typedef typename boost::remove_cv<
0098      typename boost::remove_reference<T>::type
0099    >::type type;
0100 };
0101 
0102 
0103    
0104 // returns a reference to the element of tuple T
0105 template<int N, class T> struct tuple_element_as_reference {   
0106   typedef typename
0107      boost::tuples::access_traits<
0108        typename boost::tuples::element<N, T>::type
0109      >::non_const_type type;
0110 };
0111 
0112 // returns the cv and reverence stripped type of a tuple element
0113 template<int N, class T> struct tuple_element_stripped {   
0114   typedef typename
0115      remove_reference_and_cv<
0116        typename boost::tuples::element<N, T>::type
0117      >::type type;
0118 };
0119 
0120 // is_lambda_functor -------------------------------------------------   
0121 
0122 template <class T> struct is_lambda_functor_ {
0123   BOOST_STATIC_CONSTANT(bool, value = false);
0124 };
0125    
0126 template <class Arg> struct is_lambda_functor_<lambda_functor<Arg> > {
0127   BOOST_STATIC_CONSTANT(bool, value = true);
0128 };
0129    
0130 } // end detail
0131 
0132    
0133 template <class T> struct is_lambda_functor {
0134   BOOST_STATIC_CONSTANT(bool, 
0135      value = 
0136        detail::is_lambda_functor_<
0137          typename detail::remove_reference_and_cv<T>::type
0138        >::value);
0139 };
0140    
0141 
0142 namespace detail {
0143 
0144 // -- parameter_traits_ ---------------------------------------------
0145 
0146 // An internal parameter type traits class that respects
0147 // the reference_wrapper class.
0148 
0149 // The conversions performed are:
0150 // references -> compile_time_error
0151 // T1 -> T2, 
0152 // reference_wrapper<T> -> T&
0153 // const array -> ref to const array
0154 // array -> ref to array
0155 // function -> ref to function
0156 
0157 // ------------------------------------------------------------------------
0158 
0159 template<class T1, class T2> 
0160 struct parameter_traits_ {
0161   typedef T2 type;
0162 };
0163 
0164 // Do not instantiate with reference types
0165 template<class T, class Any> struct parameter_traits_<T&, Any> {
0166   typedef typename 
0167     generate_error<T&>::
0168       parameter_traits_class_instantiated_with_reference_type type;
0169 };
0170 
0171 // Arrays can't be stored as plain types; convert them to references
0172 template<class T, int n, class Any> struct parameter_traits_<T[n], Any> {
0173   typedef T (&type)[n];
0174 };
0175    
0176 template<class T, int n, class Any> 
0177 struct parameter_traits_<const T[n], Any> {
0178   typedef const T (&type)[n];
0179 };
0180 
0181 template<class T, int n, class Any> 
0182 struct parameter_traits_<volatile T[n], Any> {
0183   typedef volatile  T (&type)[n];
0184 };
0185 template<class T, int n, class Any> 
0186 struct parameter_traits_<const volatile T[n], Any> {
0187   typedef const volatile T (&type)[n];
0188 };
0189 
0190 
0191 template<class T, class Any> 
0192 struct parameter_traits_<boost::reference_wrapper<T>, Any >{
0193   typedef T& type;
0194 };
0195 
0196 template<class T, class Any> 
0197 struct parameter_traits_<const boost::reference_wrapper<T>, Any >{
0198   typedef T& type;
0199 };
0200 
0201 template<class T, class Any> 
0202 struct parameter_traits_<volatile boost::reference_wrapper<T>, Any >{
0203   typedef T& type;
0204 };
0205 
0206 template<class T, class Any> 
0207 struct parameter_traits_<const volatile boost::reference_wrapper<T>, Any >{
0208   typedef T& type;
0209 };
0210 
0211 template<class Any>
0212 struct parameter_traits_<void, Any> {
0213   typedef void type;
0214 };
0215 
0216 template<class Arg, class Any>
0217 struct parameter_traits_<lambda_functor<Arg>, Any > {
0218   typedef lambda_functor<Arg> type;
0219 };
0220 
0221 template<class Arg, class Any>
0222 struct parameter_traits_<const lambda_functor<Arg>, Any > {
0223   typedef lambda_functor<Arg> type;
0224 };
0225 
0226 // Are the volatile versions needed?
0227 template<class Arg, class Any>
0228 struct parameter_traits_<volatile lambda_functor<Arg>, Any > {
0229   typedef lambda_functor<Arg> type;
0230 };
0231 
0232 template<class Arg, class Any>
0233 struct parameter_traits_<const volatile lambda_functor<Arg>, Any > {
0234   typedef lambda_functor<Arg> type;
0235 };
0236 
0237 } // end namespace detail
0238 
0239 
0240 // ------------------------------------------------------------------------
0241 // traits classes for lambda expressions (bind functions, operators ...)   
0242 
0243 // must be instantiated with non-reference types
0244 
0245 // The default is const plain type -------------------------
0246 // const T -> const T, 
0247 // T -> const T, 
0248 // references -> compile_time_error
0249 // reference_wrapper<T> -> T&
0250 // array -> const ref array
0251 template<class T>
0252 struct const_copy_argument {
0253   typedef typename 
0254     detail::parameter_traits_<
0255       T,
0256       typename detail::IF<boost::is_function<T>::value, T&, const T>::RET
0257     >::type type;
0258 };
0259 
0260 // T may be a function type. Without the IF test, const would be added 
0261 // to a function type, which is illegal.
0262 
0263 // all arrays are converted to const.
0264 // This traits template is used for 'const T&' parameter passing 
0265 // and thus the knowledge of the potential 
0266 // non-constness of an actual argument is lost.   
0267 template<class T, int n>  struct const_copy_argument <T[n]> {
0268   typedef const T (&type)[n];
0269 };
0270 template<class T, int n>  struct const_copy_argument <volatile T[n]> {
0271      typedef const volatile T (&type)[n];
0272 };
0273    
0274 template<class T>
0275 struct const_copy_argument<T&> {};
0276 // do not instantiate with references
0277   //  typedef typename detail::generate_error<T&>::references_not_allowed type;
0278 
0279 
0280 template<>
0281 struct const_copy_argument<void> {
0282   typedef void type;
0283 };
0284 
0285 template<>
0286 struct const_copy_argument<void const> {
0287   typedef void type;
0288 };
0289 
0290 
0291 // Does the same as const_copy_argument, but passes references through as such
0292 template<class T>
0293 struct bound_argument_conversion {
0294   typedef typename const_copy_argument<T>::type type; 
0295 };
0296 
0297 template<class T>
0298 struct bound_argument_conversion<T&> {
0299   typedef T& type; 
0300 };
0301    
0302 // The default is non-const reference -------------------------
0303 // const T -> const T&, 
0304 // T -> T&, 
0305 // references -> compile_time_error
0306 // reference_wrapper<T> -> T&
0307 template<class T>
0308 struct reference_argument {
0309   typedef typename detail::parameter_traits_<T, T&>::type type; 
0310 };
0311 
0312 template<class T>
0313 struct reference_argument<T&> {
0314   typedef typename detail::generate_error<T&>::references_not_allowed type; 
0315 };
0316 
0317 template<class Arg>
0318 struct reference_argument<lambda_functor<Arg> > {
0319   typedef lambda_functor<Arg> type;
0320 };
0321 
0322 template<class Arg>
0323 struct reference_argument<const lambda_functor<Arg> > {
0324   typedef lambda_functor<Arg> type;
0325 };
0326 
0327 // Are the volatile versions needed?
0328 template<class Arg>
0329 struct reference_argument<volatile lambda_functor<Arg> > {
0330   typedef lambda_functor<Arg> type;
0331 };
0332 
0333 template<class Arg>
0334 struct reference_argument<const volatile lambda_functor<Arg> > {
0335   typedef lambda_functor<Arg> type;
0336 };
0337 
0338 template<>
0339 struct reference_argument<void> {
0340   typedef void type;
0341 };
0342 
0343 namespace detail {
0344    
0345 // Array to pointer conversion
0346 template <class T>
0347 struct array_to_pointer { 
0348   typedef T type;
0349 };
0350 
0351 template <class T, int N>
0352 struct array_to_pointer <const T[N]> { 
0353   typedef const T* type;
0354 };
0355 template <class T, int N>
0356 struct array_to_pointer <T[N]> { 
0357   typedef T* type;
0358 };
0359 
0360 template <class T, int N>
0361 struct array_to_pointer <const T (&) [N]> { 
0362   typedef const T* type;
0363 };
0364 template <class T, int N>
0365 struct array_to_pointer <T (&) [N]> { 
0366   typedef T* type;
0367 };
0368 
0369 
0370 // ---------------------------------------------------------------------------
0371 // The call_traits for bind
0372 // Respects the reference_wrapper class.
0373 
0374 // These templates are used outside of bind functions as well.
0375 // the bind_tuple_mapper provides a shorter notation for default
0376 // bound argument storing semantics, if all arguments are treated
0377 // uniformly.
0378 
0379 // from template<class T> foo(const T& t) : bind_traits<const T>::type
0380 // from template<class T> foo(T& t) : bind_traits<T>::type
0381 
0382 // Conversions:
0383 // T -> const T,
0384 // cv T -> cv T, 
0385 // T& -> T& 
0386 // reference_wrapper<T> -> T&
0387 // const reference_wrapper<T> -> T&
0388 // array -> const ref array
0389 
0390 // make bound arguments const, this is a deliberate design choice, the
0391 // purpose is to prevent side effects to bound arguments that are stored
0392 // as copies
0393 template<class T>
0394 struct bind_traits {
0395   typedef const T type; 
0396 };
0397 
0398 template<class T>
0399 struct bind_traits<T&> {
0400   typedef T& type; 
0401 };
0402 
0403 // null_types are an exception, we always want to store them as non const
0404 // so that other templates can assume that null_type is always without const
0405 template<>
0406 struct bind_traits<null_type> {
0407   typedef null_type type;
0408 };
0409 
0410 // the bind_tuple_mapper, bind_type_generators may 
0411 // introduce const to null_type
0412 template<>
0413 struct bind_traits<const null_type> {
0414   typedef null_type type;
0415 };
0416 
0417 // Arrays can't be stored as plain types; convert them to references.
0418 // All arrays are converted to const. This is because bind takes its
0419 // parameters as const T& and thus the knowledge of the potential 
0420 // non-constness of actual argument is lost.
0421 template<class T, int n>  struct bind_traits <T[n]> {
0422   typedef const T (&type)[n];
0423 };
0424 
0425 template<class T, int n> 
0426 struct bind_traits<const T[n]> {
0427   typedef const T (&type)[n];
0428 };
0429 
0430 template<class T, int n>  struct bind_traits<volatile T[n]> {
0431   typedef const volatile T (&type)[n];
0432 };
0433 
0434 template<class T, int n> 
0435 struct bind_traits<const volatile T[n]> {
0436   typedef const volatile T (&type)[n];
0437 };
0438 
0439 template<class R>
0440 struct bind_traits<R()> {
0441     typedef R(&type)();
0442 };
0443 
0444 template<class R, class Arg1>
0445 struct bind_traits<R(Arg1)> {
0446     typedef R(&type)(Arg1);
0447 };
0448 
0449 template<class R, class Arg1, class Arg2>
0450 struct bind_traits<R(Arg1, Arg2)> {
0451     typedef R(&type)(Arg1, Arg2);
0452 };
0453 
0454 template<class R, class Arg1, class Arg2, class Arg3>
0455 struct bind_traits<R(Arg1, Arg2, Arg3)> {
0456     typedef R(&type)(Arg1, Arg2, Arg3);
0457 };
0458 
0459 template<class R, class Arg1, class Arg2, class Arg3, class Arg4>
0460 struct bind_traits<R(Arg1, Arg2, Arg3, Arg4)> {
0461     typedef R(&type)(Arg1, Arg2, Arg3, Arg4);
0462 };
0463 
0464 template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
0465 struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5)> {
0466     typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5);
0467 };
0468 
0469 template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
0470 struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {
0471     typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
0472 };
0473 
0474 template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7>
0475 struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {
0476     typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7);
0477 };
0478 
0479 template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8>
0480 struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)> {
0481     typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);
0482 };
0483 
0484 template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Arg9>
0485 struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)> {
0486     typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9);
0487 };
0488 
0489 template<class T> 
0490 struct bind_traits<reference_wrapper<T> >{
0491   typedef T& type;
0492 };
0493 
0494 template<class T> 
0495 struct bind_traits<const reference_wrapper<T> >{
0496   typedef T& type;
0497 };
0498 
0499 template<>
0500 struct bind_traits<void> {
0501   typedef void type;
0502 };
0503 
0504 
0505 
0506 template <
0507   class T0 = null_type, class T1 = null_type, class T2 = null_type, 
0508   class T3 = null_type, class T4 = null_type, class T5 = null_type, 
0509   class T6 = null_type, class T7 = null_type, class T8 = null_type, 
0510   class T9 = null_type
0511 >
0512 struct bind_tuple_mapper {
0513   typedef
0514     tuple<typename bind_traits<T0>::type, 
0515           typename bind_traits<T1>::type, 
0516           typename bind_traits<T2>::type, 
0517           typename bind_traits<T3>::type, 
0518           typename bind_traits<T4>::type, 
0519           typename bind_traits<T5>::type, 
0520           typename bind_traits<T6>::type, 
0521           typename bind_traits<T7>::type,
0522           typename bind_traits<T8>::type,
0523           typename bind_traits<T9>::type> type;
0524 };
0525 
0526 // bind_traits, except map const T& -> const T
0527   // this is needed e.g. in currying. Const reference arguments can
0528   // refer to temporaries, so it is not safe to store them as references.
0529   template <class T> struct remove_const_reference {
0530     typedef typename bind_traits<T>::type type;
0531   };
0532 
0533   template <class T> struct remove_const_reference<const T&> {
0534     typedef const T type;
0535   };
0536 
0537 
0538 // maps the bind argument types to the resulting lambda functor type
0539 template <
0540   class T0 = null_type, class T1 = null_type, class T2 = null_type, 
0541   class T3 = null_type, class T4 = null_type, class T5 = null_type, 
0542   class T6 = null_type, class T7 = null_type, class T8 = null_type, 
0543   class T9 = null_type
0544 >
0545 class bind_type_generator {
0546 
0547   typedef typename
0548   detail::bind_tuple_mapper<
0549     T0, T1, T2, T3, T4, T5, T6, T7, T8, T9
0550   >::type args_t;
0551 
0552   BOOST_STATIC_CONSTANT(int, nof_elems = boost::tuples::length<args_t>::value);
0553 
0554   typedef 
0555     action<
0556       nof_elems, 
0557       function_action<nof_elems>
0558     > action_type;
0559 
0560 public:
0561   typedef
0562     lambda_functor<
0563       lambda_functor_base<
0564         action_type, 
0565         args_t
0566       >
0567     > type; 
0568     
0569 };
0570 
0571 
0572    
0573 } // detail
0574    
0575 template <class T> inline const T&  make_const(const T& t) { return t; }
0576 
0577 
0578 } // end of namespace lambda
0579 } // end of namespace boost
0580 
0581 
0582    
0583 #endif // BOOST_LAMBDA_TRAITS_HPP