type_traits

Go to the documentation of this file.
00001 // C++0x type_traits -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file include/type_traits
00026  *  This is a Standard C++ Library header.
00027  */
00028 
00029 #ifndef _GLIBCXX_TYPE_TRAITS
00030 #define _GLIBCXX_TYPE_TRAITS 1
00031 
00032 #pragma GCC system_header
00033 
00034 #ifndef __GXX_EXPERIMENTAL_CXX0X__
00035 # include <bits/c++0x_warning.h>
00036 #else
00037 
00038 #if defined(_GLIBCXX_INCLUDE_AS_TR1)
00039 #  error C++0x header cannot be included from TR1 header
00040 #endif
00041 
00042 #include <cstddef>
00043 
00044 #if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
00045 #  include <tr1_impl/type_traits>
00046 #else
00047 #  define _GLIBCXX_INCLUDE_AS_CXX0X
00048 #  define _GLIBCXX_BEGIN_NAMESPACE_TR1
00049 #  define _GLIBCXX_END_NAMESPACE_TR1
00050 #  define _GLIBCXX_TR1
00051 #  include <tr1_impl/type_traits>
00052 #  undef _GLIBCXX_TR1
00053 #  undef _GLIBCXX_END_NAMESPACE_TR1
00054 #  undef _GLIBCXX_BEGIN_NAMESPACE_TR1
00055 #  undef _GLIBCXX_INCLUDE_AS_CXX0X
00056 #endif
00057 
00058 namespace std
00059 {
00060   /**
00061    * @addtogroup metaprogramming
00062    * @{
00063    */
00064 
00065   // Primary classification traits.
00066 
00067   /// is_lvalue_reference
00068   template<typename>
00069     struct is_lvalue_reference
00070     : public false_type { };
00071 
00072   template<typename _Tp>
00073     struct is_lvalue_reference<_Tp&>
00074     : public true_type { };
00075 
00076   /// is_rvalue_reference
00077   template<typename>
00078     struct is_rvalue_reference
00079     : public false_type { };
00080 
00081   template<typename _Tp>
00082     struct is_rvalue_reference<_Tp&&>
00083     : public true_type { };
00084 
00085   // Secondary classification traits.
00086 
00087   /// is_reference
00088   template<typename _Tp>
00089     struct is_reference
00090     : public integral_constant<bool, (is_lvalue_reference<_Tp>::value
00091                       || is_rvalue_reference<_Tp>::value)>
00092     { };
00093 
00094   // Reference transformations.
00095 
00096   /// remove_reference
00097   template<typename _Tp>
00098     struct remove_reference
00099     { typedef _Tp   type; };
00100 
00101   template<typename _Tp>
00102     struct remove_reference<_Tp&>
00103     { typedef _Tp   type; };
00104 
00105   template<typename _Tp>
00106     struct remove_reference<_Tp&&>
00107     { typedef _Tp   type; };
00108 
00109   template<typename _Tp,
00110        bool = !is_reference<_Tp>::value && !is_void<_Tp>::value,
00111        bool = is_rvalue_reference<_Tp>::value>
00112     struct __add_lvalue_reference_helper
00113     { typedef _Tp   type; };
00114 
00115   template<typename _Tp>
00116     struct __add_lvalue_reference_helper<_Tp, true, false>
00117     { typedef _Tp&   type; };
00118 
00119   template<typename _Tp>
00120     struct __add_lvalue_reference_helper<_Tp, false, true>
00121     { typedef typename remove_reference<_Tp>::type&   type; };
00122 
00123   /// add_lvalue_reference
00124   template<typename _Tp>
00125     struct add_lvalue_reference
00126     : public __add_lvalue_reference_helper<_Tp>
00127     { };
00128 
00129   template<typename _Tp,
00130        bool = !is_reference<_Tp>::value && !is_void<_Tp>::value>
00131     struct __add_rvalue_reference_helper
00132     { typedef _Tp   type; };
00133 
00134   template<typename _Tp>
00135     struct __add_rvalue_reference_helper<_Tp, true>
00136     { typedef _Tp&&   type; };
00137 
00138   /// add_rvalue_reference
00139   template<typename _Tp>
00140     struct add_rvalue_reference
00141     : public __add_rvalue_reference_helper<_Tp>
00142     { };
00143 
00144   // Scalar properties and transformations.
00145 
00146   template<typename _Tp,
00147        bool = is_integral<_Tp>::value,
00148        bool = is_floating_point<_Tp>::value>
00149     struct __is_signed_helper
00150     : public false_type { };
00151 
00152   template<typename _Tp>
00153     struct __is_signed_helper<_Tp, false, true>
00154     : public true_type { };
00155 
00156   template<typename _Tp>
00157     struct __is_signed_helper<_Tp, true, false>
00158     : public integral_constant<bool, static_cast<bool>(_Tp(-1) < _Tp(0))>
00159     { };
00160 
00161   /// is_signed
00162   template<typename _Tp>
00163     struct is_signed
00164     : public integral_constant<bool, __is_signed_helper<_Tp>::value>
00165     { };
00166 
00167   /// is_unsigned
00168   template<typename _Tp>
00169     struct is_unsigned
00170     : public integral_constant<bool, (is_arithmetic<_Tp>::value
00171                       && !is_signed<_Tp>::value)>
00172     { };
00173 
00174   // Member introspection.
00175 
00176   /// is_trivial
00177   template<typename _Tp>
00178     struct is_trivial
00179     : public integral_constant<bool, __is_trivial(_Tp)>
00180     { };
00181 
00182   /// is_standard_layout
00183   template<typename _Tp>
00184     struct is_standard_layout
00185     : public integral_constant<bool, __is_standard_layout(_Tp)>
00186     { };
00187 
00188   /// is_pod
00189   // Could use is_standard_layout && is_trivial instead of the builtin.
00190   template<typename _Tp>
00191     struct is_pod
00192     : public integral_constant<bool, __is_pod(_Tp)>
00193     { };
00194 
00195   template<typename _Tp>
00196     typename add_rvalue_reference<_Tp>::type declval();
00197 
00198   template<typename _Tp, typename... _Args>
00199     class __is_constructible_helper
00200     : public __sfinae_types
00201     {
00202       template<typename _Tp1, typename... _Args1>
00203         static decltype(_Tp1(declval<_Args1>()...), __one()) __test(int);
00204 
00205       template<typename, typename...>
00206         static __two __test(...);
00207 
00208     public:
00209       static const bool __value = sizeof(__test<_Tp, _Args...>(0)) == 1;
00210     };
00211 
00212   template<typename _Tp, typename _Arg>
00213     class __is_constructible_helper<_Tp, _Arg>
00214     : public __sfinae_types
00215     {
00216       template<typename _Tp1, typename _Arg1>
00217         static decltype(static_cast<_Tp1>(declval<_Arg1>()), __one())
00218     __test(int);
00219 
00220       template<typename, typename>
00221         static __two __test(...);
00222 
00223     public:
00224       static const bool __value = sizeof(__test<_Tp, _Arg>(0)) == 1;
00225     };
00226 
00227   /// is_constructible
00228   // XXX FIXME
00229   // The C++0x specifications require front-end support, see N2255.
00230   template<typename _Tp, typename... _Args>
00231     struct is_constructible
00232     : public integral_constant<bool,
00233                    __is_constructible_helper<_Tp,
00234                              _Args...>::__value>
00235     { };
00236 
00237   /// has_trivial_default_constructor
00238   template<typename _Tp>
00239     struct has_trivial_default_constructor
00240     : public integral_constant<bool, __has_trivial_constructor(_Tp)>
00241     { };
00242 
00243   /// has_trivial_copy_constructor
00244   template<typename _Tp>
00245     struct has_trivial_copy_constructor
00246     : public integral_constant<bool, __has_trivial_copy(_Tp)>
00247     { };
00248 
00249   /// has_trivial_assign
00250   template<typename _Tp>
00251     struct has_trivial_assign
00252     : public integral_constant<bool, __has_trivial_assign(_Tp)>
00253     { };
00254 
00255   /// has_trivial_destructor
00256   template<typename _Tp>
00257     struct has_trivial_destructor
00258     : public integral_constant<bool, __has_trivial_destructor(_Tp)>
00259     { };
00260 
00261   /// has_nothrow_default_constructor
00262   template<typename _Tp>
00263     struct has_nothrow_default_constructor
00264     : public integral_constant<bool, __has_nothrow_constructor(_Tp)>
00265     { };
00266 
00267   /// has_nothrow_copy_constructor
00268   template<typename _Tp>
00269     struct has_nothrow_copy_constructor
00270     : public integral_constant<bool, __has_nothrow_copy(_Tp)>
00271     { };
00272 
00273   /// has_nothrow_assign
00274   template<typename _Tp>
00275     struct has_nothrow_assign
00276     : public integral_constant<bool, __has_nothrow_assign(_Tp)>
00277     { };
00278 
00279   // Relationships between types.
00280 
00281   /// is_base_of
00282   template<typename _Base, typename _Derived>
00283     struct is_base_of
00284     : public integral_constant<bool, __is_base_of(_Base, _Derived)>
00285     { };
00286 
00287   template<typename _From, typename _To,
00288        bool = (is_void<_From>::value || is_void<_To>::value
00289            || is_function<_To>::value || is_array<_To>::value)>
00290     struct __is_convertible_helper
00291     { static const bool __value = (is_void<_From>::value
00292                    && is_void<_To>::value); };
00293 
00294   template<typename _From, typename _To>
00295     class __is_convertible_helper<_From, _To, false>
00296     : public __sfinae_types
00297     {
00298       static __one __test(_To);
00299       static __two __test(...);
00300 
00301     public:
00302       static const bool __value = sizeof(__test(declval<_From>())) == 1;
00303     };
00304 
00305   /// is_convertible
00306   // XXX FIXME
00307   // The C++0x specifications require front-end support, see N2255.
00308   template<typename _From, typename _To>
00309     struct is_convertible
00310     : public integral_constant<bool,
00311                    __is_convertible_helper<_From, _To>::__value>
00312     { };
00313 
00314   /// is_explicitly_convertible
00315   template<typename _From, typename _To>
00316     struct is_explicitly_convertible
00317     : public is_constructible<_To, _From>
00318     { };
00319 
00320   template<std::size_t _Len>
00321     struct __aligned_storage_msa
00322     { 
00323       union __type
00324       {
00325     unsigned char __data[_Len];
00326     struct __attribute__((__aligned__)) { } __align; 
00327       };
00328     };
00329 
00330   /**
00331    *  @brief Alignment type.
00332    *
00333    *  The value of _Align is a default-alignment which shall be the
00334    *  most stringent alignment requirement for any C++ object type
00335    *  whose size is no greater than _Len (3.9). The member typedef
00336    *  type shall be a POD type suitable for use as uninitialized
00337    *  storage for any object whose size is at most _Len and whose
00338    *  alignment is a divisor of _Align.
00339   */
00340   template<std::size_t _Len, std::size_t _Align =
00341        __alignof__(typename __aligned_storage_msa<_Len>::__type)>
00342     struct aligned_storage
00343     { 
00344       union type
00345       {
00346     unsigned char __data[_Len];
00347     struct __attribute__((__aligned__((_Align)))) { } __align; 
00348       };
00349     };
00350 
00351 
00352   // Define a nested type if some predicate holds.
00353   // Primary template.
00354   /// enable_if
00355   template<bool, typename _Tp = void>
00356     struct enable_if 
00357     { };
00358 
00359   // Partial specialization for true.
00360   template<typename _Tp>
00361     struct enable_if<true, _Tp>
00362     { typedef _Tp type; };
00363 
00364 
00365   // A conditional expression, but for types. If true, first, if false, second.
00366   // Primary template.
00367   /// conditional
00368   template<bool _Cond, typename _Iftrue, typename _Iffalse>
00369     struct conditional
00370     { typedef _Iftrue type; };
00371 
00372   // Partial specialization for false.
00373   template<typename _Iftrue, typename _Iffalse>
00374     struct conditional<false, _Iftrue, _Iffalse>
00375     { typedef _Iffalse type; };
00376 
00377 
00378   // Decay trait for arrays and functions, used for perfect forwarding
00379   // in make_pair, make_tuple, etc.
00380   template<typename _Up, 
00381        bool _IsArray = is_array<_Up>::value,
00382        bool _IsFunction = is_function<_Up>::value> 
00383     struct __decay_selector;
00384 
00385   // NB: DR 705.
00386   template<typename _Up> 
00387     struct __decay_selector<_Up, false, false>
00388     { typedef typename remove_cv<_Up>::type __type; };
00389 
00390   template<typename _Up> 
00391     struct __decay_selector<_Up, true, false>
00392     { typedef typename remove_extent<_Up>::type* __type; };
00393 
00394   template<typename _Up> 
00395     struct __decay_selector<_Up, false, true>
00396     { typedef typename add_pointer<_Up>::type __type; };
00397 
00398   /// decay
00399   template<typename _Tp> 
00400     class decay 
00401     { 
00402       typedef typename remove_reference<_Tp>::type __remove_type;
00403 
00404     public:
00405       typedef typename __decay_selector<__remove_type>::__type type;
00406     };
00407 
00408 
00409   // Utility for constructing identically cv-qualified types.
00410   template<typename _Unqualified, bool _IsConst, bool _IsVol>
00411     struct __cv_selector;
00412 
00413   template<typename _Unqualified>
00414     struct __cv_selector<_Unqualified, false, false>
00415     { typedef _Unqualified __type; };
00416 
00417   template<typename _Unqualified>
00418     struct __cv_selector<_Unqualified, false, true>
00419     { typedef volatile _Unqualified __type; };
00420 
00421   template<typename _Unqualified>
00422     struct __cv_selector<_Unqualified, true, false>
00423     { typedef const _Unqualified __type; };
00424 
00425   template<typename _Unqualified>
00426     struct __cv_selector<_Unqualified, true, true>
00427     { typedef const volatile _Unqualified __type; };
00428 
00429   template<typename _Qualified, typename _Unqualified,
00430        bool _IsConst = is_const<_Qualified>::value,
00431        bool _IsVol = is_volatile<_Qualified>::value>
00432     class __match_cv_qualifiers
00433     {
00434       typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match;
00435 
00436     public:
00437       typedef typename __match::__type __type; 
00438     };
00439 
00440 
00441   // Utility for finding the unsigned versions of signed integral types.
00442   template<typename _Tp>
00443     struct __make_unsigned
00444     { typedef _Tp __type; };
00445 
00446   template<>
00447     struct __make_unsigned<char>
00448     { typedef unsigned char __type; };
00449 
00450   template<>
00451     struct __make_unsigned<signed char>
00452     { typedef unsigned char __type; };
00453 
00454   template<>
00455     struct __make_unsigned<short>
00456     { typedef unsigned short __type; };
00457 
00458   template<>
00459     struct __make_unsigned<int>
00460     { typedef unsigned int __type; };
00461 
00462   template<>
00463     struct __make_unsigned<long>
00464     { typedef unsigned long __type; };
00465 
00466   template<>
00467     struct __make_unsigned<long long>
00468     { typedef unsigned long long __type; };
00469 
00470 
00471   // Select between integral and enum: not possible to be both.
00472   template<typename _Tp, 
00473        bool _IsInt = is_integral<_Tp>::value,
00474        bool _IsEnum = is_enum<_Tp>::value>
00475     class __make_unsigned_selector;
00476 
00477   template<typename _Tp>
00478     class __make_unsigned_selector<_Tp, true, false>
00479     {
00480       typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt;
00481       typedef typename __unsignedt::__type __unsigned_type;
00482       typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned;
00483 
00484     public:
00485       typedef typename __cv_unsigned::__type __type;
00486     };
00487 
00488   template<typename _Tp>
00489     class __make_unsigned_selector<_Tp, false, true>
00490     {
00491       // With -fshort-enums, an enum may be as small as a char.
00492       typedef unsigned char __smallest;
00493       static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
00494       static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short);
00495       static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int);
00496       typedef conditional<__b2, unsigned int, unsigned long> __cond2;
00497       typedef typename __cond2::type __cond2_type;
00498       typedef conditional<__b1, unsigned short, __cond2_type> __cond1;
00499       typedef typename __cond1::type __cond1_type;
00500 
00501     public:
00502       typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
00503     };
00504 
00505   // Given an integral/enum type, return the corresponding unsigned
00506   // integer type.
00507   // Primary template.
00508   /// make_unsigned
00509   template<typename _Tp>
00510     struct make_unsigned 
00511     { typedef typename __make_unsigned_selector<_Tp>::__type type; };
00512 
00513   // Integral, but don't define.
00514   template<>
00515     struct make_unsigned<bool>;
00516 
00517 
00518   // Utility for finding the signed versions of unsigned integral types.
00519   template<typename _Tp>
00520     struct __make_signed
00521     { typedef _Tp __type; };
00522 
00523   template<>
00524     struct __make_signed<char>
00525     { typedef signed char __type; };
00526 
00527   template<>
00528     struct __make_signed<unsigned char>
00529     { typedef signed char __type; };
00530 
00531   template<>
00532     struct __make_signed<unsigned short>
00533     { typedef signed short __type; };
00534 
00535   template<>
00536     struct __make_signed<unsigned int>
00537     { typedef signed int __type; };
00538 
00539   template<>
00540     struct __make_signed<unsigned long>
00541     { typedef signed long __type; };
00542 
00543   template<>
00544     struct __make_signed<unsigned long long>
00545     { typedef signed long long __type; };
00546 
00547 
00548   // Select between integral and enum: not possible to be both.
00549   template<typename _Tp, 
00550        bool _IsInt = is_integral<_Tp>::value,
00551        bool _IsEnum = is_enum<_Tp>::value>
00552     class __make_signed_selector;
00553 
00554   template<typename _Tp>
00555     class __make_signed_selector<_Tp, true, false>
00556     {
00557       typedef __make_signed<typename remove_cv<_Tp>::type> __signedt;
00558       typedef typename __signedt::__type __signed_type;
00559       typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed;
00560 
00561     public:
00562       typedef typename __cv_signed::__type __type;
00563     };
00564 
00565   template<typename _Tp>
00566     class __make_signed_selector<_Tp, false, true>
00567     {
00568       // With -fshort-enums, an enum may be as small as a char.
00569       typedef signed char __smallest;
00570       static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
00571       static const bool __b1 = sizeof(_Tp) <= sizeof(signed short);
00572       static const bool __b2 = sizeof(_Tp) <= sizeof(signed int);
00573       typedef conditional<__b2, signed int, signed long> __cond2;
00574       typedef typename __cond2::type __cond2_type;
00575       typedef conditional<__b1, signed short, __cond2_type> __cond1;
00576       typedef typename __cond1::type __cond1_type;
00577 
00578     public:
00579       typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
00580     };
00581 
00582   // Given an integral/enum type, return the corresponding signed
00583   // integer type.
00584   // Primary template.
00585   /// make_signed
00586   template<typename _Tp>
00587     struct make_signed 
00588     { typedef typename __make_signed_selector<_Tp>::__type type; };
00589 
00590   // Integral, but don't define.
00591   template<>
00592     struct make_signed<bool>;
00593 
00594   /// common_type
00595   template<typename... _Tp>
00596     struct common_type;
00597 
00598   template<typename _Tp>
00599     struct common_type<_Tp>
00600     { typedef _Tp type; };
00601 
00602   template<typename _Tp, typename _Up>
00603     struct common_type<_Tp, _Up>
00604     { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; };
00605 
00606   template<typename _Tp, typename _Up, typename... _Vp>
00607     struct common_type<_Tp, _Up, _Vp...>
00608     {
00609       typedef typename
00610         common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
00611     };
00612   // @} group metaprogramming
00613 
00614   /// declval
00615   template<typename _Tp>
00616     struct __declval_protector
00617     {
00618       static const bool __stop = false;
00619       static typename add_rvalue_reference<_Tp>::type __delegate();
00620     };
00621 
00622   template<typename _Tp>
00623     inline typename add_rvalue_reference<_Tp>::type
00624     declval()
00625     {
00626       static_assert(__declval_protector<_Tp>::__stop,
00627             "declval() must not be used!");
00628       return __declval_protector<_Tp>::__delegate();
00629     }
00630 }
00631 
00632 #endif  // __GXX_EXPERIMENTAL_CXX0X__
00633 
00634 #endif  // _GLIBCXX_TYPE_TRAITS