type_traits

Go to the documentation of this file.
00001 // TR1 type_traits -*- C++ -*-
00002 
00003 // Copyright (C) 2004, 2005 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 2, 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 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 /** @file 
00031  *  This is a TR1 C++ Library header. 
00032  */
00033 
00034 #ifndef _TYPE_TRAITS
00035 #define _TYPE_TRAITS 1
00036 
00037 #include <bits/c++config.h>
00038 #include <tr1/type_traits_fwd.h>
00039 
00040 // namespace std::tr1
00041 namespace std
00042 {
00043 namespace tr1
00044 {
00045   // For use in __in_array and elsewhere.
00046   struct __sfinae_types
00047   {
00048     typedef char __one;
00049     typedef struct { char __arr[2]; } __two;
00050   };
00051 
00052   template<typename _Tp>
00053     struct __in_array
00054     : public __sfinae_types
00055     {
00056     private:
00057       template<typename _Up>
00058         static __one __test(_Up(*)[1]);
00059       template<typename>
00060         static __two __test(...);
00061     
00062     public:
00063       static const bool __value = sizeof(__test<_Tp>(0)) == 1;
00064     };
00065 
00066 #define _DEFINE_SPEC_BODY(_Value)                                    \
00067     : public integral_constant<bool, _Value> { };
00068 
00069 #define _DEFINE_SPEC_0_HELPER(_Spec, _Value)                         \
00070   template<>                                                         \
00071     struct _Spec                                                     \
00072     _DEFINE_SPEC_BODY(_Value)
00073 
00074 #define _DEFINE_SPEC_1_HELPER(_Spec, _Value)                         \
00075   template<typename _Tp>                                             \
00076     struct _Spec                                                     \
00077     _DEFINE_SPEC_BODY(_Value)
00078       
00079 #define _DEFINE_SPEC_2_HELPER(_Spec, _Value)                         \
00080   template<typename _Tp, typename _Cp>                               \
00081     struct _Spec                                                     \
00082     _DEFINE_SPEC_BODY(_Value)
00083 
00084 #define _DEFINE_SPEC(_Order, _Trait, _Type, _Value)                  \
00085   _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type>, _Value)              \
00086   _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const>, _Value)        \
00087   _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type volatile>, _Value)     \
00088   _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const volatile>, _Value)
00089 
00090   /// @brief  helper classes [4.3].
00091   template<typename _Tp, _Tp __v>
00092     struct integral_constant
00093     {
00094       static const _Tp                      value = __v;
00095       typedef _Tp                           value_type;
00096       typedef integral_constant<_Tp, __v>   type;
00097     };
00098   typedef integral_constant<bool, true>     true_type;
00099   typedef integral_constant<bool, false>    false_type;
00100 
00101   /// @brief  primary type categories [4.5.1].
00102   template<typename>
00103     struct is_void
00104     : public false_type { };
00105   _DEFINE_SPEC(0, is_void, void, true)
00106 
00107   template<typename>
00108     struct is_integral
00109     : public false_type { };
00110   _DEFINE_SPEC(0, is_integral, bool, true)
00111   _DEFINE_SPEC(0, is_integral, char, true)
00112   _DEFINE_SPEC(0, is_integral, signed char, true)
00113   _DEFINE_SPEC(0, is_integral, unsigned char, true)
00114 #ifdef _GLIBCXX_USE_WCHAR_T
00115   _DEFINE_SPEC(0, is_integral, wchar_t, true)
00116 #endif
00117   _DEFINE_SPEC(0, is_integral, short, true)
00118   _DEFINE_SPEC(0, is_integral, unsigned short, true)
00119   _DEFINE_SPEC(0, is_integral, int, true)
00120   _DEFINE_SPEC(0, is_integral, unsigned int, true)
00121   _DEFINE_SPEC(0, is_integral, long, true)
00122   _DEFINE_SPEC(0, is_integral, unsigned long, true)
00123   _DEFINE_SPEC(0, is_integral, long long, true)
00124   _DEFINE_SPEC(0, is_integral, unsigned long long, true)
00125 
00126   template<typename>
00127     struct is_floating_point
00128     : public false_type { };
00129   _DEFINE_SPEC(0, is_floating_point, float, true)
00130   _DEFINE_SPEC(0, is_floating_point, double, true)
00131   _DEFINE_SPEC(0, is_floating_point, long double, true)
00132 
00133   template<typename>
00134     struct is_array
00135     : public false_type { };
00136 
00137   template<typename _Tp, std::size_t _Size>
00138     struct is_array<_Tp[_Size]>
00139     : public true_type { };
00140 
00141   template<typename _Tp>
00142     struct is_array<_Tp[]>
00143     : public true_type { };
00144 
00145   template<typename>
00146     struct is_pointer
00147     : public false_type { };
00148   _DEFINE_SPEC(1, is_pointer, _Tp*, true)
00149  
00150   template<typename>
00151     struct is_reference
00152     : public false_type { };
00153 
00154   template<typename _Tp>
00155     struct is_reference<_Tp&>
00156     : public true_type { };
00157 
00158   template<typename>
00159     struct is_member_object_pointer
00160     : public false_type { };
00161   _DEFINE_SPEC(2, is_member_object_pointer, _Tp _Cp::*,
00162            !is_function<_Tp>::value)
00163 
00164   template<typename>
00165     struct is_member_function_pointer
00166     : public false_type { };
00167   _DEFINE_SPEC(2, is_member_function_pointer, _Tp _Cp::*,
00168            is_function<_Tp>::value)
00169 
00170   template<typename _Tp>
00171     struct is_enum
00172     : public integral_constant<bool, !(is_fundamental<_Tp>::value
00173                        || is_array<_Tp>::value
00174                        || is_pointer<_Tp>::value
00175                        || is_reference<_Tp>::value
00176                        || is_member_pointer<_Tp>::value
00177                        || is_function<_Tp>::value
00178                        || __is_union_or_class<_Tp>::value)>
00179     { };
00180 
00181   template<typename>
00182     struct is_union { };
00183 
00184   template<typename>
00185     struct is_class { };
00186 
00187   template<typename _Tp>
00188     struct is_function
00189     : public integral_constant<bool, !(__in_array<_Tp>::__value
00190                        || __is_union_or_class<_Tp>::value
00191                        || is_reference<_Tp>::value
00192                        || is_void<_Tp>::value)>
00193     { };
00194 
00195   /// @brief  composite type traits [4.5.2].
00196   template<typename _Tp>
00197     struct is_arithmetic
00198     : public integral_constant<bool, (is_integral<_Tp>::value
00199                       || is_floating_point<_Tp>::value)>
00200     { };
00201 
00202   template<typename _Tp>
00203     struct is_fundamental
00204     : public integral_constant<bool, (is_arithmetic<_Tp>::value
00205                       || is_void<_Tp>::value)>
00206     { };
00207 
00208   template<typename _Tp>
00209     struct is_object
00210     : public integral_constant<bool, !(is_function<_Tp>::value
00211                        || is_reference<_Tp>::value
00212                        || is_void<_Tp>::value)>
00213     { };
00214 
00215   template<typename _Tp>
00216     struct is_scalar
00217     : public integral_constant<bool, (is_arithmetic<_Tp>::value
00218                       || is_enum<_Tp>::value
00219                       || is_pointer<_Tp>::value
00220                       || is_member_pointer<_Tp>::value)>
00221     { };
00222 
00223   template<typename _Tp>
00224     struct is_compound
00225     : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
00226 
00227   template<typename _Tp>
00228     struct is_member_pointer
00229     : public integral_constant<bool,
00230                    (is_member_object_pointer<_Tp>::value
00231                 || is_member_function_pointer<_Tp>::value)>
00232     { };
00233 
00234   template<typename _Tp>
00235     struct __is_union_or_class_helper
00236     : public __sfinae_types
00237     {
00238     private:
00239       template<typename _Up>
00240         static __one __test(int _Up::*);
00241       template<typename>
00242         static __two __test(...);
00243     
00244     public:
00245       static const bool __value = sizeof(__test<_Tp>(0)) == 1;
00246     };
00247 
00248   // Extension.
00249   template<typename _Tp>
00250     struct __is_union_or_class
00251     : public integral_constant<bool, __is_union_or_class_helper<_Tp>::__value>
00252     { };
00253   
00254   /// @brief  type properties [4.5.3].
00255   template<typename>
00256     struct is_const
00257     : public false_type { };
00258 
00259   template<typename _Tp>
00260     struct is_const<_Tp const>
00261     : public true_type { };
00262   
00263   template<typename>
00264     struct is_volatile
00265     : public false_type { };
00266 
00267   template<typename _Tp>
00268     struct is_volatile<_Tp volatile>
00269     : public true_type { };
00270 
00271   template<typename _Tp>
00272     struct is_pod
00273     : public integral_constant<bool, (is_void<_Tp>::value
00274                       || is_scalar<typename
00275                       remove_all_extents<_Tp>::type>::value)>
00276     { };
00277 
00278   // N.B. Without compiler support we cannot tell union from class types,
00279   // and is_empty and is_polymorphic don't work at all with the former. 
00280   template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
00281     struct __is_empty_helper
00282     { 
00283     private:
00284       template<typename>
00285         struct __first { };
00286       template<typename _Up>
00287         struct __second
00288         : public _Up { };
00289            
00290     public:
00291       static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
00292     };
00293 
00294   template<typename _Tp>
00295     struct __is_empty_helper<_Tp, true>
00296     { static const bool __value = false; };
00297 
00298   template<typename _Tp>
00299     struct is_empty
00300     : public integral_constant<bool, __is_empty_helper<_Tp>::__value>
00301     { };
00302 
00303   template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
00304     struct __is_polymorphic_helper
00305     { 
00306     private:
00307       template<typename _Up>
00308         struct __first
00309         : public _Up { };
00310       template<typename _Up>
00311         struct __second
00312         : public _Up
00313     { 
00314       virtual void __dummy();
00315       virtual ~__second() throw();
00316     };
00317 
00318     public:
00319       static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
00320     };
00321 
00322   template<typename _Tp>
00323     struct __is_polymorphic_helper<_Tp, true>
00324     { static const bool __value = false; };
00325 
00326   template<typename _Tp>
00327     struct is_polymorphic
00328     : public integral_constant<bool, __is_polymorphic_helper<_Tp>::__value>
00329     { };
00330 
00331   // Exploit the resolution DR core/337.
00332   template<typename _Tp>
00333     struct is_abstract
00334     : public integral_constant<bool, (!__in_array<_Tp>::__value
00335                       && __is_union_or_class<_Tp>::value)> { };
00336 
00337   template<typename _Tp>
00338     struct has_trivial_constructor
00339     : public integral_constant<bool, is_pod<_Tp>::value> { };
00340 
00341   template<typename _Tp>
00342     struct has_trivial_copy
00343     : public integral_constant<bool, is_pod<_Tp>::value> { };
00344 
00345   template<typename _Tp>
00346     struct has_trivial_assign
00347     : public integral_constant<bool, is_pod<_Tp>::value> { };
00348 
00349   template<typename _Tp>
00350     struct has_trivial_destructor
00351     : public integral_constant<bool, is_pod<_Tp>::value> { };
00352 
00353   template<typename _Tp>
00354     struct has_nothrow_constructor
00355     : public integral_constant<bool, is_pod<_Tp>::value> { };
00356 
00357   template<typename _Tp>
00358     struct has_nothrow_copy
00359     : public integral_constant<bool, is_pod<_Tp>::value> { };
00360 
00361   template<typename _Tp>
00362     struct has_nothrow_assign
00363     : public integral_constant<bool, is_pod<_Tp>::value> { };
00364 
00365   template<typename>
00366     struct has_virtual_destructor
00367     : public false_type { };
00368 
00369   template<typename>
00370     struct is_signed
00371     : public false_type { };
00372   _DEFINE_SPEC(0, is_signed, signed char, true)
00373   _DEFINE_SPEC(0, is_signed, short, true)
00374   _DEFINE_SPEC(0, is_signed, int, true)
00375   _DEFINE_SPEC(0, is_signed, long, true)
00376   _DEFINE_SPEC(0, is_signed, long long, true)
00377 
00378   template<typename>
00379     struct is_unsigned
00380     : public false_type { };
00381   _DEFINE_SPEC(0, is_unsigned, unsigned char, true)
00382   _DEFINE_SPEC(0, is_unsigned, unsigned short, true)
00383   _DEFINE_SPEC(0, is_unsigned, unsigned int, true)
00384   _DEFINE_SPEC(0, is_unsigned, unsigned long, true)
00385   _DEFINE_SPEC(0, is_unsigned, unsigned long long, true)
00386 
00387   template<typename _Tp>
00388     struct alignment_of
00389     : public integral_constant<std::size_t, __alignof__(_Tp)> { };
00390   
00391   template<typename>
00392     struct rank
00393     : public integral_constant<std::size_t, 0> { };
00394    
00395   template<typename _Tp, std::size_t _Size>
00396     struct rank<_Tp[_Size]>
00397     : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
00398 
00399   template<typename _Tp>
00400     struct rank<_Tp[]>
00401     : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
00402    
00403   template<typename, unsigned>
00404     struct extent
00405     : public integral_constant<std::size_t, 0> { };
00406   
00407   template<typename _Tp, unsigned _Uint, std::size_t _Size>
00408     struct extent<_Tp[_Size], _Uint>
00409     : public integral_constant<std::size_t,
00410                    _Uint == 0 ? _Size : extent<_Tp,
00411                                _Uint - 1>::value>
00412     { };
00413 
00414   template<typename _Tp, unsigned _Uint>
00415     struct extent<_Tp[], _Uint>
00416     : public integral_constant<std::size_t,
00417                    _Uint == 0 ? 0 : extent<_Tp,
00418                                _Uint - 1>::value>
00419     { };
00420   
00421   /// @brief  relationships between types [4.6].
00422   template<typename, typename>
00423     struct is_same
00424     : public false_type { };
00425 
00426   template<typename _Tp>
00427     struct is_same<_Tp, _Tp>
00428     : public true_type { };
00429 
00430   // See Daveed Vandevoorde explanation in http://tinyurl.com/502f.
00431   // Also see Rani Sharoni in http://tinyurl.com/6jvyq.
00432   template<typename _Base, typename _Derived,
00433        bool = (!__is_union_or_class<_Base>::value
00434            || !__is_union_or_class<_Derived>::value
00435            || is_same<_Base, _Derived>::value)>
00436     struct __is_base_of_helper
00437     : public __sfinae_types
00438     {
00439     private:
00440       typedef typename remove_cv<_Base>::type     _NoCv_Base;      
00441       typedef typename remove_cv<_Derived>::type  _NoCv_Derived;
00442       
00443       template<typename _Up>
00444         static __one __test(_NoCv_Derived&, _Up);
00445       static __two __test(_NoCv_Base&, int);
00446    
00447       struct _Conv
00448       {
00449     operator _NoCv_Derived&();
00450     operator _NoCv_Base&() const;
00451       };
00452    
00453     public:
00454       static const bool __value = sizeof(__test(_Conv(), 0)) == 1;
00455     };
00456 
00457   template<typename _Base, typename _Derived>
00458     struct __is_base_of_helper<_Base, _Derived, true>
00459     { static const bool __value = is_same<_Base, _Derived>::value; };
00460 
00461   template<typename _Base, typename _Derived>
00462     struct is_base_of
00463     : public integral_constant<bool,
00464                    __is_base_of_helper<_Base, _Derived>::__value>
00465     { };
00466 
00467   template<typename _From, typename _To>
00468     struct __is_convertible_simple
00469     : public __sfinae_types
00470     {
00471     private:
00472       static __one __test(_To);
00473       static __two __test(...);
00474       static _From __makeFrom();
00475     
00476     public:
00477       static const bool __value = sizeof(__test(__makeFrom())) == 1;
00478     };
00479 
00480   template<typename _Tp>
00481     struct __is_int_or_cref
00482     {
00483       typedef typename remove_reference<_Tp>::type __rr_Tp;
00484       static const bool __value = (is_integral<_Tp>::value
00485                    || (is_integral<__rr_Tp>::value
00486                        && is_const<__rr_Tp>::value
00487                        && !is_volatile<__rr_Tp>::value));
00488     };
00489 
00490   template<typename _From, typename _To,
00491        bool = (is_void<_From>::value || is_void<_To>::value
00492            || is_function<_To>::value || is_array<_To>::value
00493            // This special case is here only to avoid warnings.        
00494            || (is_floating_point<typename
00495                remove_reference<_From>::type>::value
00496                && __is_int_or_cref<_To>::__value))>
00497     struct __is_convertible_helper
00498     {
00499       // "An imaginary lvalue of type From...".
00500       static const bool __value = (__is_convertible_simple<typename
00501                    add_reference<_From>::type, _To>::__value);
00502     };
00503 
00504   template<typename _From, typename _To>
00505     struct __is_convertible_helper<_From, _To, true>
00506     { static const bool __value = (is_void<_To>::value
00507                    || (__is_int_or_cref<_To>::__value
00508                        && !is_void<_From>::value)); };
00509 
00510   template<typename _From, typename _To>
00511     struct is_convertible
00512     : public integral_constant<bool,
00513                    __is_convertible_helper<_From, _To>::__value>
00514     { };
00515 
00516   /// @brief  const-volatile modifications [4.7.1].
00517   template<typename _Tp>
00518     struct remove_const
00519     { typedef _Tp     type; };
00520 
00521   template<typename _Tp>
00522     struct remove_const<_Tp const>
00523     { typedef _Tp     type; };
00524   
00525   template<typename _Tp>
00526     struct remove_volatile
00527     { typedef _Tp     type; };
00528 
00529   template<typename _Tp>
00530     struct remove_volatile<_Tp volatile>
00531     { typedef _Tp     type; };
00532   
00533   template<typename _Tp>
00534     struct remove_cv
00535     {
00536       typedef typename
00537       remove_const<typename remove_volatile<_Tp>::type>::type     type;
00538     };
00539   
00540   template<typename _Tp>
00541     struct add_const
00542     { typedef _Tp const     type; };
00543    
00544   template<typename _Tp>
00545     struct add_volatile
00546     { typedef _Tp volatile     type; };
00547   
00548   template<typename _Tp>
00549     struct add_cv
00550     {
00551       typedef typename
00552       add_const<typename add_volatile<_Tp>::type>::type     type;
00553     };
00554 
00555   /// @brief  reference modifications [4.7.2].
00556   template<typename _Tp>
00557     struct remove_reference
00558     { typedef _Tp     type; };
00559 
00560   template<typename _Tp>
00561     struct remove_reference<_Tp&>
00562     { typedef _Tp     type; };
00563   
00564   template<typename _Tp>
00565     struct add_reference
00566     { typedef _Tp&    type; };
00567 
00568   template<typename _Tp>
00569     struct add_reference<_Tp&>
00570     { typedef _Tp&    type; };
00571 
00572   /// @brief  array modififications [4.7.3].
00573   template<typename _Tp>
00574     struct remove_extent
00575     { typedef _Tp     type; };
00576 
00577   template<typename _Tp, std::size_t _Size>
00578     struct remove_extent<_Tp[_Size]>
00579     { typedef _Tp     type; };
00580 
00581   template<typename _Tp>
00582     struct remove_extent<_Tp[]>
00583     { typedef _Tp     type; };
00584 
00585   template<typename _Tp>
00586     struct remove_all_extents
00587     { typedef _Tp     type; };
00588 
00589   template<typename _Tp, std::size_t _Size>
00590     struct remove_all_extents<_Tp[_Size]>
00591     { typedef typename remove_all_extents<_Tp>::type     type; };
00592 
00593   template<typename _Tp>
00594     struct remove_all_extents<_Tp[]>
00595     { typedef typename remove_all_extents<_Tp>::type     type; };
00596 
00597   /// @brief  pointer modifications [4.7.4].
00598 #undef _DEFINE_SPEC_BODY
00599 #define _DEFINE_SPEC_BODY(_Value)      \
00600     { typedef _Tp     type; };
00601 
00602   template<typename _Tp>
00603     struct remove_pointer
00604     { typedef _Tp     type; };
00605   _DEFINE_SPEC(1, remove_pointer, _Tp*, false)
00606   
00607   template<typename _Tp>
00608     struct add_pointer
00609     { typedef typename remove_reference<_Tp>::type*     type; };
00610 
00611   /// @brief  other transformations [4.8].
00612   
00613   // Due to c++/19163 and c++/17743, for the time being we cannot use
00614   // the correct, neat implementation :-(
00615   // 
00616   // template<std::size_t _Len, std::size_t _Align>
00617   //   struct aligned_storage
00618   //   { typedef char type[_Len] __attribute__((__aligned__(_Align))); }
00619   //
00620   // Temporary workaround, useful for Align up to 32:
00621   template<std::size_t, std::size_t>
00622     struct aligned_storage { };
00623 
00624   template<std::size_t _Len>
00625     struct aligned_storage<_Len, 1>
00626     {
00627       union type
00628       {
00629     unsigned char __data[_Len];
00630     char __align __attribute__((__aligned__(1)));
00631       };
00632     };
00633 
00634   template<std::size_t _Len>
00635     struct aligned_storage<_Len, 2>
00636     {
00637       union type
00638       {
00639     unsigned char __data[_Len];
00640     char __align __attribute__((__aligned__(2)));
00641       };
00642     };
00643 
00644   template<std::size_t _Len>
00645     struct aligned_storage<_Len, 4>
00646     {
00647       union type
00648       {
00649     unsigned char __data[_Len];
00650     char __align __attribute__((__aligned__(4)));
00651       };
00652     };
00653 
00654   template<std::size_t _Len>
00655     struct aligned_storage<_Len, 8>
00656     {
00657       union type
00658       {
00659     unsigned char __data[_Len];
00660     char __align __attribute__((__aligned__(8)));
00661       };
00662     };
00663 
00664   template<std::size_t _Len>
00665     struct aligned_storage<_Len, 16>
00666     {
00667       union type
00668       {
00669     unsigned char __data[_Len];
00670     char __align __attribute__((__aligned__(16)));
00671       };
00672     };
00673   
00674   template<std::size_t _Len>
00675     struct aligned_storage<_Len, 32>
00676     {
00677       union type
00678       {
00679     unsigned char __data[_Len];
00680     char __align __attribute__((__aligned__(32)));
00681       };
00682     };
00683 
00684 #undef _DEFINE_SPEC_0_HELPER
00685 #undef _DEFINE_SPEC_1_HELPER
00686 #undef _DEFINE_SPEC_2_HELPER
00687 #undef _DEFINE_SPEC
00688 #undef _DEFINE_SPEC_BODY
00689 
00690 }
00691 }
00692 
00693 #endif

Generated on Thu Apr 20 22:15:04 2006 for libstdc++ source by  doxygen 1.4.6