Home | History | Annotate | Download | only in include
      1 // C++0x type_traits -*- C++ -*-
      2 
      3 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/type_traits
     26  *  This is a Standard C++ Library header.
     27  */
     28 
     29 #ifndef _GLIBCXX_TYPE_TRAITS
     30 #define _GLIBCXX_TYPE_TRAITS 1
     31 
     32 #pragma GCC system_header
     33 
     34 #ifndef __GXX_EXPERIMENTAL_CXX0X__
     35 # include <c++0x_warning.h>
     36 #else
     37 
     38 #if defined(_GLIBCXX_INCLUDE_AS_TR1)
     39 #  error C++0x header cannot be included from TR1 header
     40 #endif
     41 
     42 #include <cstddef>
     43 
     44 #if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
     45 #  include <tr1_impl/type_traits>
     46 #else
     47 #  define _GLIBCXX_INCLUDE_AS_CXX0X
     48 #  define _GLIBCXX_BEGIN_NAMESPACE_TR1
     49 #  define _GLIBCXX_END_NAMESPACE_TR1
     50 #  define _GLIBCXX_TR1
     51 #  include <tr1_impl/type_traits>
     52 #  undef _GLIBCXX_TR1
     53 #  undef _GLIBCXX_END_NAMESPACE_TR1
     54 #  undef _GLIBCXX_BEGIN_NAMESPACE_TR1
     55 #  undef _GLIBCXX_INCLUDE_AS_CXX0X
     56 #endif
     57 
     58 namespace std
     59 {
     60   /** @addtogroup metaprogramming
     61    * @{
     62    */
     63 
     64   // Primary classification traits.
     65 
     66   /// is_lvalue_reference
     67   template<typename>
     68     struct is_lvalue_reference
     69     : public false_type { };
     70 
     71   template<typename _Tp>
     72     struct is_lvalue_reference<_Tp&>
     73     : public true_type { };
     74 
     75   /// is_rvalue_reference
     76   template<typename>
     77     struct is_rvalue_reference
     78     : public false_type { };
     79 
     80   template<typename _Tp>
     81     struct is_rvalue_reference<_Tp&&>
     82     : public true_type { };
     83 
     84   // Secondary classification traits.
     85 
     86   /// is_reference
     87   template<typename _Tp>
     88     struct is_reference
     89     : public integral_constant<bool, (is_lvalue_reference<_Tp>::value
     90 				      || is_rvalue_reference<_Tp>::value)>
     91     { };
     92 
     93   // Reference transformations.
     94 
     95   /// remove_reference
     96   template<typename _Tp>
     97     struct remove_reference
     98     { typedef _Tp   type; };
     99 
    100   template<typename _Tp>
    101     struct remove_reference<_Tp&>
    102     { typedef _Tp   type; };
    103 
    104   template<typename _Tp>
    105     struct remove_reference<_Tp&&>
    106     { typedef _Tp   type; };
    107 
    108   template<typename _Tp,
    109 	   bool = !is_reference<_Tp>::value && !is_void<_Tp>::value,
    110 	   bool = is_rvalue_reference<_Tp>::value>
    111     struct __add_lvalue_reference_helper
    112     { typedef _Tp   type; };
    113 
    114   template<typename _Tp>
    115     struct __add_lvalue_reference_helper<_Tp, true, false>
    116     { typedef _Tp&   type; };
    117 
    118   template<typename _Tp>
    119     struct __add_lvalue_reference_helper<_Tp, false, true>
    120     { typedef typename remove_reference<_Tp>::type&   type; };
    121 
    122   /// add_lvalue_reference
    123   template<typename _Tp>
    124     struct add_lvalue_reference
    125     : public __add_lvalue_reference_helper<_Tp>
    126     { };
    127 
    128   template<typename _Tp,
    129 	   bool = !is_reference<_Tp>::value && !is_void<_Tp>::value>
    130     struct __add_rvalue_reference_helper
    131     { typedef _Tp   type; };
    132 
    133   template<typename _Tp>
    134     struct __add_rvalue_reference_helper<_Tp, true>
    135     { typedef _Tp&&   type; };
    136 
    137   /// add_rvalue_reference
    138   template<typename _Tp>
    139     struct add_rvalue_reference
    140     : public __add_rvalue_reference_helper<_Tp>
    141     { };
    142 
    143   // Scalar properties and transformations.
    144 
    145   template<typename _Tp,
    146 	   bool = is_integral<_Tp>::value,
    147 	   bool = is_floating_point<_Tp>::value>
    148     struct __is_signed_helper
    149     : public false_type { };
    150 
    151   template<typename _Tp>
    152     struct __is_signed_helper<_Tp, false, true>
    153     : public true_type { };
    154 
    155   template<typename _Tp>
    156     struct __is_signed_helper<_Tp, true, false>
    157     : public integral_constant<bool, _Tp(-1) < _Tp(0)>
    158     { };
    159 
    160   /// is_signed
    161   template<typename _Tp>
    162     struct is_signed
    163     : public integral_constant<bool, __is_signed_helper<_Tp>::value>
    164     { };
    165 
    166   /// is_unsigned
    167   template<typename _Tp>
    168     struct is_unsigned
    169     : public integral_constant<bool, (is_arithmetic<_Tp>::value
    170 				      && !is_signed<_Tp>::value)>
    171     { };
    172 
    173   // Member introspection.
    174 
    175   /// is_pod
    176   template<typename _Tp>
    177     struct is_pod
    178     : public integral_constant<bool, __is_pod(_Tp)>
    179     { };
    180 
    181   /// has_trivial_default_constructor
    182   template<typename _Tp>
    183     struct has_trivial_default_constructor
    184     : public integral_constant<bool, __has_trivial_constructor(_Tp)>
    185     { };
    186 
    187   /// has_trivial_copy_constructor
    188   template<typename _Tp>
    189     struct has_trivial_copy_constructor
    190     : public integral_constant<bool, __has_trivial_copy(_Tp)>
    191     { };
    192 
    193   /// has_trivial_assign
    194   template<typename _Tp>
    195     struct has_trivial_assign
    196     : public integral_constant<bool, __has_trivial_assign(_Tp)>
    197     { };
    198 
    199   /// has_trivial_destructor
    200   template<typename _Tp>
    201     struct has_trivial_destructor
    202     : public integral_constant<bool, __has_trivial_destructor(_Tp)>
    203     { };
    204 
    205   /// has_nothrow_default_constructor
    206   template<typename _Tp>
    207     struct has_nothrow_default_constructor
    208     : public integral_constant<bool, __has_nothrow_constructor(_Tp)>
    209     { };
    210 
    211   /// has_nothrow_copy_constructor
    212   template<typename _Tp>
    213     struct has_nothrow_copy_constructor
    214     : public integral_constant<bool, __has_nothrow_copy(_Tp)>
    215     { };
    216 
    217   /// has_nothrow_assign
    218   template<typename _Tp>
    219     struct has_nothrow_assign
    220     : public integral_constant<bool, __has_nothrow_assign(_Tp)>
    221     { };
    222 
    223   /// is_base_of
    224   template<typename _Base, typename _Derived>
    225     struct is_base_of
    226     : public integral_constant<bool, __is_base_of(_Base, _Derived)>
    227     { };
    228 
    229   // Relationships between types.
    230   template<typename _From, typename _To>
    231     struct __is_convertible_simple
    232     : public __sfinae_types
    233     {
    234     private:
    235       static __one __test(_To);
    236       static __two __test(...);
    237       static _From __makeFrom();
    238     
    239     public:
    240       static const bool __value = sizeof(__test(__makeFrom())) == 1;
    241     };
    242 
    243   template<typename _Tp>
    244     struct __is_int_or_cref
    245     {
    246       typedef typename remove_reference<_Tp>::type __rr_Tp;
    247       static const bool __value = (is_integral<_Tp>::value
    248 				   || (is_integral<__rr_Tp>::value
    249 				       && is_const<__rr_Tp>::value
    250 				       && !is_volatile<__rr_Tp>::value));
    251     };
    252 
    253   template<typename _From, typename _To,
    254 	   bool = (is_void<_From>::value || is_void<_To>::value
    255 		   || is_function<_To>::value || is_array<_To>::value
    256 		   // This special case is here only to avoid warnings.
    257 		   || (is_floating_point<typename
    258 		       remove_reference<_From>::type>::value
    259 		       && __is_int_or_cref<_To>::__value))>
    260     struct __is_convertible_helper
    261     {
    262       // "An imaginary lvalue of type From...".
    263       static const bool __value = (__is_convertible_simple<typename
    264 				   add_lvalue_reference<_From>::type,
    265 				   _To>::__value);
    266     };
    267 
    268   template<typename _From, typename _To>
    269     struct __is_convertible_helper<_From, _To, true>
    270     { static const bool __value = (is_void<_To>::value
    271 				   || (__is_int_or_cref<_To>::__value
    272 				       && !is_void<_From>::value)); };
    273 
    274   // XXX FIXME
    275   // The C++0x specifications are different, see N2255.
    276   /// is_convertible
    277   template<typename _From, typename _To>
    278     struct is_convertible
    279     : public integral_constant<bool,
    280 			       __is_convertible_helper<_From, _To>::__value>
    281     { };
    282 
    283   template<std::size_t _Len>
    284     struct __aligned_storage_msa
    285     { 
    286       union __type
    287       {
    288 	unsigned char __data[_Len];
    289 	struct __attribute__((__aligned__)) { } __align; 
    290       };
    291     };
    292 
    293   /**
    294    *  @brief Alignment type.
    295    *
    296    *  The value of _Align is a default-alignment which shall be the
    297    *  most stringent alignment requirement for any C++ object type
    298    *  whose size is no greater than _Len (3.9). The member typedef
    299    *  type shall be a POD type suitable for use as uninitialized
    300    *  storage for any object whose size is at most _Len and whose
    301    *  alignment is a divisor of _Align.
    302   */
    303   template<std::size_t _Len, std::size_t _Align =
    304 	   __alignof__(typename __aligned_storage_msa<_Len>::__type)>
    305     struct aligned_storage
    306     { 
    307       union type
    308       {
    309 	unsigned char __data[_Len];
    310 	struct __attribute__((__aligned__((_Align)))) { } __align; 
    311       };
    312     };
    313 
    314 
    315   // Define a nested type if some predicate holds.
    316   // Primary template.
    317   /// enable_if
    318   template<bool, typename _Tp = void>
    319     struct enable_if 
    320     { };
    321 
    322   // Partial specialization for true.
    323   template<typename _Tp>
    324     struct enable_if<true, _Tp>
    325     { typedef _Tp type; };
    326 
    327 
    328   // A conditional expression, but for types. If true, first, if false, second.
    329   // Primary template.
    330   /// conditional
    331   template<bool _Cond, typename _Iftrue, typename _Iffalse>
    332     struct conditional
    333     { typedef _Iftrue type; };
    334 
    335   // Partial specialization for false.
    336   template<typename _Iftrue, typename _Iffalse>
    337     struct conditional<false, _Iftrue, _Iffalse>
    338     { typedef _Iffalse type; };
    339 
    340 
    341   // Decay trait for arrays and functions, used for perfect forwarding
    342   // in make_pair, make_tuple, etc.
    343   template<typename _Up, 
    344 	   bool _IsArray = is_array<_Up>::value,
    345 	   bool _IsFunction = is_function<_Up>::value> 
    346     struct __decay_selector;
    347 
    348   // NB: DR 705.
    349   template<typename _Up> 
    350     struct __decay_selector<_Up, false, false>
    351     { typedef typename remove_cv<_Up>::type __type; };
    352 
    353   template<typename _Up> 
    354     struct __decay_selector<_Up, true, false>
    355     { typedef typename remove_extent<_Up>::type* __type; };
    356 
    357   template<typename _Up> 
    358     struct __decay_selector<_Up, false, true>
    359     { typedef typename add_pointer<_Up>::type __type; };
    360 
    361   /// decay
    362   template<typename _Tp> 
    363     struct decay 
    364     { 
    365     private:
    366       typedef typename remove_reference<_Tp>::type __remove_type;
    367 
    368     public:
    369       typedef typename __decay_selector<__remove_type>::__type type;
    370     };
    371 
    372 
    373   // Utility for constructing identically cv-qualified types.
    374   template<typename _Unqualified, bool _IsConst, bool _IsVol>
    375     struct __cv_selector;
    376 
    377   template<typename _Unqualified>
    378     struct __cv_selector<_Unqualified, false, false>
    379     { typedef _Unqualified __type; };
    380 
    381   template<typename _Unqualified>
    382     struct __cv_selector<_Unqualified, false, true>
    383     { typedef volatile _Unqualified __type; };
    384 
    385   template<typename _Unqualified>
    386     struct __cv_selector<_Unqualified, true, false>
    387     { typedef const _Unqualified __type; };
    388 
    389   template<typename _Unqualified>
    390     struct __cv_selector<_Unqualified, true, true>
    391     { typedef const volatile _Unqualified __type; };
    392 
    393   template<typename _Qualified, typename _Unqualified,
    394 	   bool _IsConst = is_const<_Qualified>::value,
    395 	   bool _IsVol = is_volatile<_Qualified>::value>
    396     struct __match_cv_qualifiers
    397     {
    398     private:
    399       typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match;
    400 
    401     public:
    402       typedef typename __match::__type __type; 
    403     };
    404 
    405 
    406   // Utility for finding the unsigned versions of signed integral types.
    407   template<typename _Tp>
    408     struct __make_unsigned
    409     { typedef _Tp __type; };
    410 
    411   template<>
    412     struct __make_unsigned<char>
    413     { typedef unsigned char __type; };
    414 
    415   template<>
    416     struct __make_unsigned<signed char>
    417     { typedef unsigned char __type; };
    418 
    419   template<>
    420     struct __make_unsigned<short>
    421     { typedef unsigned short __type; };
    422 
    423   template<>
    424     struct __make_unsigned<int>
    425     { typedef unsigned int __type; };
    426 
    427   template<>
    428     struct __make_unsigned<long>
    429     { typedef unsigned long __type; };
    430 
    431   template<>
    432     struct __make_unsigned<long long>
    433     { typedef unsigned long long __type; };
    434 
    435 
    436   // Select between integral and enum: not possible to be both.
    437   template<typename _Tp, 
    438 	   bool _IsInt = is_integral<_Tp>::value,
    439 	   bool _IsEnum = is_enum<_Tp>::value>
    440     struct __make_unsigned_selector;
    441   
    442   template<typename _Tp>
    443     struct __make_unsigned_selector<_Tp, true, false>
    444     {
    445     private:
    446       typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt;
    447       typedef typename __unsignedt::__type __unsigned_type;
    448       typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned;
    449 
    450     public:
    451       typedef typename __cv_unsigned::__type __type;
    452     };
    453 
    454   template<typename _Tp>
    455     struct __make_unsigned_selector<_Tp, false, true>
    456     {
    457     private:
    458       // With -fshort-enums, an enum may be as small as a char.
    459       typedef unsigned char __smallest;
    460       static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
    461       static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short);
    462       static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int);
    463       typedef conditional<__b2, unsigned int, unsigned long> __cond2;
    464       typedef typename __cond2::type __cond2_type;
    465       typedef conditional<__b1, unsigned short, __cond2_type> __cond1;
    466       typedef typename __cond1::type __cond1_type;
    467 
    468     public:
    469       typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
    470     };
    471 
    472   // Given an integral/enum type, return the corresponding unsigned
    473   // integer type.
    474   // Primary template.
    475   /// make_unsigned
    476   template<typename _Tp>
    477     struct make_unsigned 
    478     { typedef typename __make_unsigned_selector<_Tp>::__type type; };
    479 
    480   // Integral, but don't define.
    481   template<>
    482     struct make_unsigned<bool>;
    483 
    484 
    485   // Utility for finding the signed versions of unsigned integral types.
    486   template<typename _Tp>
    487     struct __make_signed
    488     { typedef _Tp __type; };
    489 
    490   template<>
    491     struct __make_signed<char>
    492     { typedef signed char __type; };
    493 
    494   template<>
    495     struct __make_signed<unsigned char>
    496     { typedef signed char __type; };
    497 
    498   template<>
    499     struct __make_signed<unsigned short>
    500     { typedef signed short __type; };
    501 
    502   template<>
    503     struct __make_signed<unsigned int>
    504     { typedef signed int __type; };
    505 
    506   template<>
    507     struct __make_signed<unsigned long>
    508     { typedef signed long __type; };
    509 
    510   template<>
    511     struct __make_signed<unsigned long long>
    512     { typedef signed long long __type; };
    513 
    514 
    515   // Select between integral and enum: not possible to be both.
    516   template<typename _Tp, 
    517 	   bool _IsInt = is_integral<_Tp>::value,
    518 	   bool _IsEnum = is_enum<_Tp>::value>
    519     struct __make_signed_selector;
    520   
    521   template<typename _Tp>
    522     struct __make_signed_selector<_Tp, true, false>
    523     {
    524     private:
    525       typedef __make_signed<typename remove_cv<_Tp>::type> __signedt;
    526       typedef typename __signedt::__type __signed_type;
    527       typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed;
    528 
    529     public:
    530       typedef typename __cv_signed::__type __type;
    531     };
    532 
    533   template<typename _Tp>
    534     struct __make_signed_selector<_Tp, false, true>
    535     {
    536     private:
    537       // With -fshort-enums, an enum may be as small as a char.
    538       typedef signed char __smallest;
    539       static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
    540       static const bool __b1 = sizeof(_Tp) <= sizeof(signed short);
    541       static const bool __b2 = sizeof(_Tp) <= sizeof(signed int);
    542       typedef conditional<__b2, signed int, signed long> __cond2;
    543       typedef typename __cond2::type __cond2_type;
    544       typedef conditional<__b1, signed short, __cond2_type> __cond1;
    545       typedef typename __cond1::type __cond1_type;
    546 
    547     public:
    548       typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
    549     };
    550 
    551   // Given an integral/enum type, return the corresponding signed
    552   // integer type.
    553   // Primary template.
    554   /// make_signed
    555   template<typename _Tp>
    556     struct make_signed 
    557     { typedef typename __make_signed_selector<_Tp>::__type type; };
    558 
    559   // Integral, but don't define.
    560   template<>
    561     struct make_signed<bool>;
    562 
    563   /// common_type
    564   template<typename... _Tp>
    565     struct common_type;
    566 
    567   template<typename _Tp>
    568     struct common_type<_Tp>
    569     {
    570       static_assert(sizeof(_Tp) > 0, "must be complete type");
    571       typedef _Tp type;
    572     };
    573 
    574   template<typename _Tp, typename _Up>
    575     class common_type<_Tp, _Up>
    576     {
    577       static_assert(sizeof(_Tp) > 0, "must be complete type");
    578       static_assert(sizeof(_Up) > 0, "must be complete type");
    579 
    580       static _Tp&& __t();
    581       static _Up&& __u();
    582 
    583       // HACK: Prevents optimization of ?: in the decltype
    584       // expression when the condition is the literal, "true".
    585       // See, PR36628.
    586       static bool __true_or_false();
    587 
    588     public:
    589       typedef decltype(__true_or_false() ? __t() : __u()) type;
    590     };
    591 
    592   template<typename _Tp, typename _Up, typename... _Vp>
    593     struct common_type<_Tp, _Up, _Vp...>
    594     {
    595       typedef typename
    596         common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
    597     };
    598 
    599   // @} group metaprogramming
    600 }
    601 
    602 #endif  // __GXX_EXPERIMENTAL_CXX0X__
    603 
    604 #endif  // _GLIBCXX_TYPE_TRAITS 
    605 
    606