epoc32/include/stdapis/boost/lambda/detail/lambda_traits.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100
branchSymbian2
changeset 3 e1b950c65cb4
permissions -rw-r--r--
Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
     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