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