Home | History | Annotate | Download | only in tr1
      1 // TR1 type_traits -*- C++ -*-
      2 
      3 // Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
      4 // Free Software Foundation, Inc.
      5 //
      6 // This file is part of the GNU ISO C++ Library.  This library is free
      7 // software; you can redistribute it and/or modify it under the
      8 // terms of the GNU General Public License as published by the
      9 // Free Software Foundation; either version 3, or (at your option)
     10 // any later version.
     11 
     12 // This library is distributed in the hope that it will be useful,
     13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 // GNU General Public License for more details.
     16 
     17 // Under Section 7 of GPL version 3, you are granted additional
     18 // permissions described in the GCC Runtime Library Exception, version
     19 // 3.1, as published by the Free Software Foundation.
     20 
     21 // You should have received a copy of the GNU General Public License and
     22 // a copy of the GCC Runtime Library Exception along with this program;
     23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24 // <http://www.gnu.org/licenses/>.
     25 
     26 /** @file tr1/type_traits
     27  *  This is a TR1 C++ Library header. 
     28  */
     29 
     30 #ifndef _GLIBCXX_TR1_TYPE_TRAITS
     31 #define _GLIBCXX_TR1_TYPE_TRAITS 1
     32 
     33 #pragma GCC system_header
     34 
     35 #include <bits/c++config.h>
     36 
     37 namespace std _GLIBCXX_VISIBILITY(default)
     38 {
     39 namespace tr1
     40 {
     41 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     42 
     43   /**
     44    * @defgroup metaprogramming Type Traits
     45    * @ingroup utilities
     46    *
     47    * Compile time type transformation and information.
     48    * @{
     49    */
     50 
     51   struct __sfinae_types
     52   {
     53     typedef char __one;
     54     typedef struct { char __arr[2]; } __two;
     55   };
     56 
     57 #define _DEFINE_SPEC_0_HELPER                          \
     58   template<>
     59 
     60 #define _DEFINE_SPEC_1_HELPER                          \
     61   template<typename _Tp>
     62 
     63 #define _DEFINE_SPEC_2_HELPER                          \
     64   template<typename _Tp, typename _Cp>
     65 
     66 #define _DEFINE_SPEC(_Order, _Trait, _Type, _Value)    \
     67   _DEFINE_SPEC_##_Order##_HELPER                       \
     68     struct _Trait<_Type>                               \
     69     : public integral_constant<bool, _Value> { };
     70 
     71   // helper classes [4.3].
     72 
     73   /// integral_constant
     74   template<typename _Tp, _Tp __v>
     75     struct integral_constant
     76     {
     77       static const _Tp                      value = __v;
     78       typedef _Tp                           value_type;
     79       typedef integral_constant<_Tp, __v>   type;
     80     };
     81   
     82   /// typedef for true_type
     83   typedef integral_constant<bool, true>     true_type;
     84 
     85   /// typedef for false_type
     86   typedef integral_constant<bool, false>    false_type;
     87 
     88   template<typename _Tp, _Tp __v>
     89     const _Tp integral_constant<_Tp, __v>::value;
     90 
     91   /// remove_cv
     92   template<typename>
     93     struct remove_cv;
     94 
     95   template<typename>
     96     struct __is_void_helper
     97     : public false_type { };
     98   _DEFINE_SPEC(0, __is_void_helper, void, true)
     99 
    100   // primary type categories [4.5.1].
    101 
    102   /// is_void
    103   template<typename _Tp>
    104     struct is_void
    105     : public integral_constant<bool, (__is_void_helper<typename
    106 				      remove_cv<_Tp>::type>::value)>
    107     { };
    108 
    109   template<typename>
    110     struct __is_integral_helper
    111     : public false_type { };
    112   _DEFINE_SPEC(0, __is_integral_helper, bool, true)
    113   _DEFINE_SPEC(0, __is_integral_helper, char, true)
    114   _DEFINE_SPEC(0, __is_integral_helper, signed char, true)
    115   _DEFINE_SPEC(0, __is_integral_helper, unsigned char, true)
    116 #ifdef _GLIBCXX_USE_WCHAR_T
    117   _DEFINE_SPEC(0, __is_integral_helper, wchar_t, true)
    118 #endif
    119   _DEFINE_SPEC(0, __is_integral_helper, short, true)
    120   _DEFINE_SPEC(0, __is_integral_helper, unsigned short, true)
    121   _DEFINE_SPEC(0, __is_integral_helper, int, true)
    122   _DEFINE_SPEC(0, __is_integral_helper, unsigned int, true)
    123   _DEFINE_SPEC(0, __is_integral_helper, long, true)
    124   _DEFINE_SPEC(0, __is_integral_helper, unsigned long, true)
    125   _DEFINE_SPEC(0, __is_integral_helper, long long, true)
    126   _DEFINE_SPEC(0, __is_integral_helper, unsigned long long, true)
    127 
    128   /// is_integral
    129   template<typename _Tp>
    130     struct is_integral
    131     : public integral_constant<bool, (__is_integral_helper<typename
    132 				      remove_cv<_Tp>::type>::value)>
    133     { };
    134 
    135   template<typename>
    136     struct __is_floating_point_helper
    137     : public false_type { };
    138   _DEFINE_SPEC(0, __is_floating_point_helper, float, true)
    139   _DEFINE_SPEC(0, __is_floating_point_helper, double, true)
    140   _DEFINE_SPEC(0, __is_floating_point_helper, long double, true)
    141 
    142   /// is_floating_point
    143   template<typename _Tp>
    144     struct is_floating_point
    145     : public integral_constant<bool, (__is_floating_point_helper<typename
    146 				      remove_cv<_Tp>::type>::value)>
    147     { };
    148 
    149   /// is_array
    150   template<typename>
    151     struct is_array
    152     : public false_type { };
    153 
    154   template<typename _Tp, std::size_t _Size>
    155     struct is_array<_Tp[_Size]>
    156     : public true_type { };
    157 
    158   template<typename _Tp>
    159     struct is_array<_Tp[]>
    160     : public true_type { };
    161 
    162   template<typename>
    163     struct __is_pointer_helper
    164     : public false_type { };
    165   _DEFINE_SPEC(1, __is_pointer_helper, _Tp*, true)
    166 
    167   /// is_pointer
    168   template<typename _Tp>
    169     struct is_pointer
    170     : public integral_constant<bool, (__is_pointer_helper<typename
    171 				      remove_cv<_Tp>::type>::value)>
    172     { };
    173 
    174   /// is_reference
    175   template<typename _Tp>
    176     struct is_reference;
    177 
    178   /// is_function
    179   template<typename _Tp>
    180     struct is_function;
    181 
    182   template<typename>
    183     struct __is_member_object_pointer_helper
    184     : public false_type { };
    185   _DEFINE_SPEC(2, __is_member_object_pointer_helper, _Tp _Cp::*,
    186 	       !is_function<_Tp>::value)
    187 
    188   /// is_member_object_pointer
    189   template<typename _Tp>
    190     struct is_member_object_pointer
    191     : public integral_constant<bool, (__is_member_object_pointer_helper<
    192 				      typename remove_cv<_Tp>::type>::value)>
    193     { };
    194 
    195   template<typename>
    196     struct __is_member_function_pointer_helper
    197     : public false_type { };
    198   _DEFINE_SPEC(2, __is_member_function_pointer_helper, _Tp _Cp::*,
    199 	       is_function<_Tp>::value)
    200 
    201   /// is_member_function_pointer
    202   template<typename _Tp>
    203     struct is_member_function_pointer
    204     : public integral_constant<bool, (__is_member_function_pointer_helper<
    205 				      typename remove_cv<_Tp>::type>::value)>
    206     { };
    207 
    208   /// is_enum
    209   template<typename _Tp>
    210     struct is_enum
    211     : public integral_constant<bool, __is_enum(_Tp)>
    212     { };
    213 
    214   /// is_union
    215   template<typename _Tp>
    216     struct is_union
    217     : public integral_constant<bool, __is_union(_Tp)>
    218     { };
    219 
    220   /// is_class
    221   template<typename _Tp>
    222     struct is_class
    223     : public integral_constant<bool, __is_class(_Tp)>
    224     { };
    225 
    226   /// is_function
    227   template<typename>
    228     struct is_function
    229     : public false_type { };
    230   template<typename _Res, typename... _ArgTypes>
    231     struct is_function<_Res(_ArgTypes...)>
    232     : public true_type { };
    233   template<typename _Res, typename... _ArgTypes>
    234     struct is_function<_Res(_ArgTypes......)>
    235     : public true_type { };
    236   template<typename _Res, typename... _ArgTypes>
    237     struct is_function<_Res(_ArgTypes...) const>
    238     : public true_type { };
    239   template<typename _Res, typename... _ArgTypes>
    240     struct is_function<_Res(_ArgTypes......) const>
    241     : public true_type { };
    242   template<typename _Res, typename... _ArgTypes>
    243     struct is_function<_Res(_ArgTypes...) volatile>
    244     : public true_type { };
    245   template<typename _Res, typename... _ArgTypes>
    246     struct is_function<_Res(_ArgTypes......) volatile>
    247     : public true_type { };
    248   template<typename _Res, typename... _ArgTypes>
    249     struct is_function<_Res(_ArgTypes...) const volatile>
    250     : public true_type { };
    251   template<typename _Res, typename... _ArgTypes>
    252     struct is_function<_Res(_ArgTypes......) const volatile>
    253     : public true_type { };
    254 
    255   // composite type traits [4.5.2].
    256   
    257   /// is_arithmetic
    258   template<typename _Tp>
    259     struct is_arithmetic
    260     : public integral_constant<bool, (is_integral<_Tp>::value
    261 				      || is_floating_point<_Tp>::value)>
    262     { };
    263 
    264   /// is_fundamental
    265   template<typename _Tp>
    266     struct is_fundamental
    267     : public integral_constant<bool, (is_arithmetic<_Tp>::value
    268 				      || is_void<_Tp>::value)>
    269     { };
    270 
    271   /// is_object
    272   template<typename _Tp>
    273     struct is_object
    274     : public integral_constant<bool, !(is_function<_Tp>::value
    275 				       || is_reference<_Tp>::value
    276 				       || is_void<_Tp>::value)>
    277     { };
    278 
    279   /// is_member_pointer
    280   template<typename _Tp>
    281     struct is_member_pointer;
    282 
    283   /// is_scalar
    284   template<typename _Tp>
    285     struct is_scalar
    286     : public integral_constant<bool, (is_arithmetic<_Tp>::value
    287 				      || is_enum<_Tp>::value
    288 				      || is_pointer<_Tp>::value
    289 				      || is_member_pointer<_Tp>::value)>
    290     { };
    291 
    292   /// is_compound
    293   template<typename _Tp>
    294     struct is_compound
    295     : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
    296 
    297   /// is_member_pointer
    298   template<typename _Tp>
    299     struct __is_member_pointer_helper
    300     : public false_type { };
    301   _DEFINE_SPEC(2, __is_member_pointer_helper, _Tp _Cp::*, true)
    302 
    303   template<typename _Tp>
    304   struct is_member_pointer
    305     : public integral_constant<bool, (__is_member_pointer_helper<
    306 				      typename remove_cv<_Tp>::type>::value)>
    307     { };
    308 
    309   // type properties [4.5.3].
    310   /// is_const
    311   template<typename>
    312     struct is_const
    313     : public false_type { };
    314 
    315   template<typename _Tp>
    316     struct is_const<_Tp const>
    317     : public true_type { };
    318   
    319   /// is_volatile
    320   template<typename>
    321     struct is_volatile
    322     : public false_type { };
    323 
    324   template<typename _Tp>
    325     struct is_volatile<_Tp volatile>
    326     : public true_type { };
    327 
    328   /// is_empty
    329   template<typename _Tp>
    330     struct is_empty
    331     : public integral_constant<bool, __is_empty(_Tp)>
    332     { };
    333 
    334   /// is_polymorphic
    335   template<typename _Tp>
    336     struct is_polymorphic
    337     : public integral_constant<bool, __is_polymorphic(_Tp)>
    338     { };
    339 
    340   /// is_abstract
    341   template<typename _Tp>
    342     struct is_abstract
    343     : public integral_constant<bool, __is_abstract(_Tp)>
    344     { };
    345 
    346   /// has_virtual_destructor
    347   template<typename _Tp>
    348     struct has_virtual_destructor
    349     : public integral_constant<bool, __has_virtual_destructor(_Tp)>
    350     { };
    351 
    352   /// alignment_of
    353   template<typename _Tp>
    354     struct alignment_of
    355     : public integral_constant<std::size_t, __alignof__(_Tp)> { };
    356   
    357   /// rank
    358   template<typename>
    359     struct rank
    360     : public integral_constant<std::size_t, 0> { };
    361    
    362   template<typename _Tp, std::size_t _Size>
    363     struct rank<_Tp[_Size]>
    364     : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
    365 
    366   template<typename _Tp>
    367     struct rank<_Tp[]>
    368     : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
    369 
    370   /// extent
    371   template<typename, unsigned _Uint = 0>
    372     struct extent
    373     : public integral_constant<std::size_t, 0> { };
    374   
    375   template<typename _Tp, unsigned _Uint, std::size_t _Size>
    376     struct extent<_Tp[_Size], _Uint>
    377     : public integral_constant<std::size_t,
    378 			       _Uint == 0 ? _Size : extent<_Tp,
    379 							   _Uint - 1>::value>
    380     { };
    381 
    382   template<typename _Tp, unsigned _Uint>
    383     struct extent<_Tp[], _Uint>
    384     : public integral_constant<std::size_t,
    385 			       _Uint == 0 ? 0 : extent<_Tp,
    386 						       _Uint - 1>::value>
    387     { };
    388 
    389   // relationships between types [4.6].
    390 
    391   /// is_same
    392   template<typename, typename>
    393     struct is_same
    394     : public false_type { };
    395 
    396   template<typename _Tp>
    397     struct is_same<_Tp, _Tp>
    398     : public true_type { };
    399 
    400   // const-volatile modifications [4.7.1].
    401 
    402   /// remove_const
    403   template<typename _Tp>
    404     struct remove_const
    405     { typedef _Tp     type; };
    406 
    407   template<typename _Tp>
    408     struct remove_const<_Tp const>
    409     { typedef _Tp     type; };
    410   
    411   /// remove_volatile
    412   template<typename _Tp>
    413     struct remove_volatile
    414     { typedef _Tp     type; };
    415 
    416   template<typename _Tp>
    417     struct remove_volatile<_Tp volatile>
    418     { typedef _Tp     type; };
    419   
    420   /// remove_cv
    421   template<typename _Tp>
    422     struct remove_cv
    423     {
    424       typedef typename
    425       remove_const<typename remove_volatile<_Tp>::type>::type     type;
    426     };
    427   
    428   /// add_const
    429   template<typename _Tp>
    430     struct add_const
    431     { typedef _Tp const     type; };
    432    
    433   /// add_volatile
    434   template<typename _Tp>
    435     struct add_volatile
    436     { typedef _Tp volatile     type; };
    437   
    438   /// add_cv
    439   template<typename _Tp>
    440     struct add_cv
    441     {
    442       typedef typename
    443       add_const<typename add_volatile<_Tp>::type>::type     type;
    444     };
    445 
    446   // array modifications [4.7.3].
    447 
    448   /// remove_extent
    449   template<typename _Tp>
    450     struct remove_extent
    451     { typedef _Tp     type; };
    452 
    453   template<typename _Tp, std::size_t _Size>
    454     struct remove_extent<_Tp[_Size]>
    455     { typedef _Tp     type; };
    456 
    457   template<typename _Tp>
    458     struct remove_extent<_Tp[]>
    459     { typedef _Tp     type; };
    460 
    461   /// remove_all_extents
    462   template<typename _Tp>
    463     struct remove_all_extents
    464     { typedef _Tp     type; };
    465 
    466   template<typename _Tp, std::size_t _Size>
    467     struct remove_all_extents<_Tp[_Size]>
    468     { typedef typename remove_all_extents<_Tp>::type     type; };
    469 
    470   template<typename _Tp>
    471     struct remove_all_extents<_Tp[]>
    472     { typedef typename remove_all_extents<_Tp>::type     type; };
    473 
    474   // pointer modifications [4.7.4].
    475 
    476   template<typename _Tp, typename>
    477     struct __remove_pointer_helper
    478     { typedef _Tp     type; };
    479 
    480   template<typename _Tp, typename _Up>
    481     struct __remove_pointer_helper<_Tp, _Up*>
    482     { typedef _Up     type; };
    483 
    484   /// remove_pointer
    485   template<typename _Tp>
    486     struct remove_pointer
    487     : public __remove_pointer_helper<_Tp, typename remove_cv<_Tp>::type>
    488     { };
    489 
    490   template<typename>
    491     struct remove_reference;
    492 
    493   /// add_pointer
    494   template<typename _Tp>
    495     struct add_pointer
    496     { typedef typename remove_reference<_Tp>::type*     type; };
    497 
    498   template<typename>
    499     struct is_reference
    500     : public false_type { };
    501 
    502   template<typename _Tp>
    503     struct is_reference<_Tp&>
    504     : public true_type { };
    505 
    506   template<typename _Tp>
    507     struct is_pod
    508     : public integral_constant<bool, __is_pod(_Tp) || is_void<_Tp>::value>
    509     { };
    510 
    511   template<typename _Tp>
    512     struct has_trivial_constructor
    513     : public integral_constant<bool, is_pod<_Tp>::value>
    514     { };
    515 
    516   template<typename _Tp>
    517     struct has_trivial_copy
    518     : public integral_constant<bool, is_pod<_Tp>::value>
    519     { };
    520 
    521   template<typename _Tp>
    522     struct has_trivial_assign
    523     : public integral_constant<bool, is_pod<_Tp>::value>
    524     { };
    525 
    526   template<typename _Tp>
    527     struct has_trivial_destructor
    528     : public integral_constant<bool, is_pod<_Tp>::value>
    529     { };
    530 
    531   template<typename _Tp>
    532     struct has_nothrow_constructor
    533     : public integral_constant<bool, is_pod<_Tp>::value>
    534     { };
    535 
    536   template<typename _Tp>
    537     struct has_nothrow_copy
    538     : public integral_constant<bool, is_pod<_Tp>::value>
    539     { };
    540 
    541   template<typename _Tp>
    542     struct has_nothrow_assign
    543     : public integral_constant<bool, is_pod<_Tp>::value>
    544     { };
    545 
    546   template<typename>
    547     struct __is_signed_helper
    548     : public false_type { };
    549   _DEFINE_SPEC(0, __is_signed_helper, signed char, true)
    550   _DEFINE_SPEC(0, __is_signed_helper, short, true)
    551   _DEFINE_SPEC(0, __is_signed_helper, int, true)
    552   _DEFINE_SPEC(0, __is_signed_helper, long, true)
    553   _DEFINE_SPEC(0, __is_signed_helper, long long, true)
    554 
    555   template<typename _Tp>
    556     struct is_signed
    557     : public integral_constant<bool, (__is_signed_helper<typename
    558 				      remove_cv<_Tp>::type>::value)>
    559     { };
    560 
    561   template<typename>
    562     struct __is_unsigned_helper
    563     : public false_type { };
    564   _DEFINE_SPEC(0, __is_unsigned_helper, unsigned char, true)
    565   _DEFINE_SPEC(0, __is_unsigned_helper, unsigned short, true)
    566   _DEFINE_SPEC(0, __is_unsigned_helper, unsigned int, true)
    567   _DEFINE_SPEC(0, __is_unsigned_helper, unsigned long, true)
    568   _DEFINE_SPEC(0, __is_unsigned_helper, unsigned long long, true)
    569 
    570   template<typename _Tp>
    571     struct is_unsigned
    572     : public integral_constant<bool, (__is_unsigned_helper<typename
    573 				      remove_cv<_Tp>::type>::value)>
    574     { };
    575 
    576   template<typename _Base, typename _Derived>
    577     struct __is_base_of_helper
    578     {
    579       typedef typename remove_cv<_Base>::type    _NoCv_Base;
    580       typedef typename remove_cv<_Derived>::type _NoCv_Derived;
    581       static const bool __value = (is_same<_Base, _Derived>::value
    582 				   || (__is_base_of(_Base, _Derived)
    583 				       && !is_same<_NoCv_Base,
    584 				                   _NoCv_Derived>::value));
    585     };
    586  
    587   template<typename _Base, typename _Derived>
    588     struct is_base_of
    589     : public integral_constant<bool,
    590 			       __is_base_of_helper<_Base, _Derived>::__value>
    591     { };
    592 
    593   template<typename _From, typename _To>
    594     struct __is_convertible_simple
    595     : public __sfinae_types
    596     {
    597     private:
    598       static __one __test(_To);
    599       static __two __test(...);
    600       static _From __makeFrom();
    601     
    602     public:
    603       static const bool __value = sizeof(__test(__makeFrom())) == 1;
    604     };
    605 
    606   template<typename _Tp>
    607     struct add_reference;
    608 
    609   template<typename _Tp>
    610     struct __is_int_or_cref
    611     {
    612       typedef typename remove_reference<_Tp>::type __rr_Tp;
    613       static const bool __value = (is_integral<_Tp>::value
    614 				   || (is_integral<__rr_Tp>::value
    615 				       && is_const<__rr_Tp>::value
    616 				       && !is_volatile<__rr_Tp>::value));
    617     };
    618 
    619   template<typename _From, typename _To,
    620 	   bool = (is_void<_From>::value || is_void<_To>::value
    621 		   || is_function<_To>::value || is_array<_To>::value
    622 		   // This special case is here only to avoid warnings.	
    623 		   || (is_floating_point<typename
    624 		       remove_reference<_From>::type>::value
    625 		       && __is_int_or_cref<_To>::__value))>
    626     struct __is_convertible_helper
    627     {
    628       // "An imaginary lvalue of type From...".
    629       static const bool __value = (__is_convertible_simple<typename
    630 				   add_reference<_From>::type, _To>::__value);
    631     };
    632 
    633   template<typename _From, typename _To>
    634     struct __is_convertible_helper<_From, _To, true>
    635     { static const bool __value = (is_void<_To>::value
    636 				   || (__is_int_or_cref<_To>::__value
    637 				       && !is_void<_From>::value)); };
    638 
    639   template<typename _From, typename _To>
    640     struct is_convertible
    641     : public integral_constant<bool,
    642 			       __is_convertible_helper<_From, _To>::__value>
    643     { };
    644 
    645   // reference modifications [4.7.2].
    646   template<typename _Tp>
    647     struct remove_reference
    648     { typedef _Tp     type; };
    649 
    650   template<typename _Tp>
    651     struct remove_reference<_Tp&>
    652     { typedef _Tp     type; };
    653 
    654   // NB: Careful with reference to void.
    655   template<typename _Tp, bool = (is_void<_Tp>::value
    656 				 || is_reference<_Tp>::value)>
    657     struct __add_reference_helper
    658     { typedef _Tp&    type; };
    659 
    660   template<typename _Tp>
    661     struct __add_reference_helper<_Tp, true>
    662     { typedef _Tp     type; };
    663 
    664   template<typename _Tp>
    665     struct add_reference
    666     : public __add_reference_helper<_Tp>
    667     { };
    668 
    669   // other transformations [4.8].
    670   template<std::size_t _Len, std::size_t _Align>
    671     struct aligned_storage
    672     { 
    673       union type
    674       {
    675 	unsigned char __data[_Len];
    676 	struct __attribute__((__aligned__((_Align)))) { } __align; 
    677       };
    678     };
    679 
    680 #undef _DEFINE_SPEC_0_HELPER
    681 #undef _DEFINE_SPEC_1_HELPER
    682 #undef _DEFINE_SPEC_2_HELPER
    683 #undef _DEFINE_SPEC
    684 
    685 _GLIBCXX_END_NAMESPACE_VERSION
    686 }
    687 }
    688 
    689 #endif // _GLIBCXX_TR1_TYPE_TRAITS
    690