# cpp_type_traits.h

Go to the documentation of this file.

    00001 // The  -*- C++ -*- type traits classes for internal use in libstdc++
    00002
    00003 // Copyright (C) 2000, 2001, 2002, 2003 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 // Written by Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
    00031
    00032 /** @file cpp_type_traits.h
    00033  *  This is an internal header file, included by other library headers.
    00034  *  You should not attempt to use it directly.
    00035  */
    00036
    00037 #ifndef _CPP_TYPE_TRAITS_H
    00038 #define _CPP_TYPE_TRAITS_H 1
    00039
    00040 #pragma GCC system_header
    00041
    00042 //
    00043 // This file provides some compile-time information about various types.
    00044 // These representations were designed, on purpose, to be constant-expressions
    00045 // and not types as found in <stl/bits/type_traits.h>.  In particular, they
    00046 // can be used in control structures and the optimizer hopefully will do
    00047 // the obvious thing.
    00048 //
    00049 // Why integral expressions, and not functions nor types?
    00050 // Firstly, these compile-time entities are used as template-arguments
    00051 // so function return values won't work:  We need compile-time entities.
    00052 // We're left with types and constant  integral expressions.
    00053 // Secondly, from the point of view of ease of use, type-based compile-time
    00054 // information is -not- *that* convenient.  On has to write lots of
    00055 // overloaded functions and to hope that the compiler will select the right
    00056 // one. As a net effect, the overall structure isn't very clear at first
    00057 // glance.
    00058 // Thirdly, partial ordering and overload resolution (of function templates)
    00059 // is highly costly in terms of compiler-resource.  It is a Good Thing to
    00060 // keep these resource consumption as least as possible.
    00061 //
    00062 // See valarray_array.h for a case use.
    00063 //
    00064 // -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06.
    00065 //
    00066
    00067 namespace std
    00068 {
    00069   // Compare for equality of types.
    00070   template<typename, typename>
    00071     struct __are_same
    00072     {
    00073       enum
    00074       {
    00075         _M_type = 0
    00076       };
    00077     };
    00078
    00079   template<typename _Tp>
    00080     struct __are_same<_Tp, _Tp>
    00081     {
    00082       enum
    00083       {
    00084         _M_type = 1
    00085       };
    00086     };
    00087
    00088   // Define a nested type if some predicate holds.
    00089   template<typename, bool>
    00090     struct __enable_if
    00091     {
    00092     };
    00093
    00094   template<typename _Tp>
    00095   struct __enable_if<_Tp, true>
    00096     {
    00097       typedef _Tp _M_type;
    00098     };
    00099
    00100   // Holds if the template-argument is a void type.
    00101   template<typename _Tp>
    00102     struct __is_void
    00103     {
    00104       enum
    00105       {
    00106         _M_type = 0
    00107       };
    00108     };
    00109
    00110   template<>
    00111     struct __is_void<void>
    00112     {
    00113       enum
    00114       {
    00115         _M_type = 1
    00116       };
    00117     };
    00118
    00119   //
    00120   // Integer types
    00121   //
    00122   template<typename _Tp>
    00123     struct __is_integer
    00124     {
    00125       enum
    00126       {
    00127     _M_type = 0
    00128       };
    00129     };
    00130
    00131   // Thirteen specializations (yes there are eleven standard integer
    00132   // types; 'long long' and 'unsigned long long' are supported as
    00133   // extensions)
    00134   template<>
    00135     struct __is_integer<bool>
    00136     {
    00137       enum
    00138       {
    00139     _M_type = 1
    00140       };
    00141     };
    00142
    00143   template<>
    00144     struct __is_integer<char>
    00145     {
    00146       enum
    00147       {
    00148     _M_type = 1
    00149       };
    00150     };
    00151
    00152   template<>
    00153     struct __is_integer<signed char>
    00154     {
    00155       enum
    00156       {
    00157     _M_type = 1
    00158       };
    00159     };
    00160
    00161   template<>
    00162   struct __is_integer<unsigned char>
    00163   {
    00164     enum
    00165     {
    00166       _M_type = 1
    00167     };
    00168   };
    00169
    00170 # ifdef _GLIBCXX_USE_WCHAR_T
    00171   template<>
    00172   struct __is_integer<wchar_t>
    00173   {
    00174     enum
    00175     {
    00176       _M_type = 1
    00177     };
    00178   };
    00179 # endif
    00180
    00181   template<>
    00182   struct __is_integer<short>
    00183   {
    00184     enum
    00185     {
    00186       _M_type = 1
    00187     };
    00188   };
    00189
    00190   template<>
    00191   struct __is_integer<unsigned short>
    00192   {
    00193     enum
    00194     {
    00195       _M_type = 1
    00196     };
    00197   };
    00198
    00199   template<>
    00200   struct __is_integer<int>
    00201   {
    00202     enum
    00203     {
    00204       _M_type = 1
    00205     };
    00206   };
    00207
    00208   template<>
    00209   struct __is_integer<unsigned int>
    00210   {
    00211     enum
    00212     {
    00213       _M_type = 1
    00214     };
    00215   };
    00216
    00217   template<>
    00218   struct __is_integer<long>
    00219   {
    00220     enum
    00221     {
    00222       _M_type = 1
    00223     };
    00224   };
    00225
    00226   template<>
    00227   struct __is_integer<unsigned long>
    00228   {
    00229     enum
    00230     {
    00231       _M_type = 1
    00232     };
    00233   };
    00234
    00235   template<>
    00236   struct __is_integer<long long>
    00237   {
    00238     enum
    00239     {
    00240       _M_type = 1
    00241     };
    00242   };
    00243
    00244   template<>
    00245   struct __is_integer<unsigned long long>
    00246   {
    00247     enum
    00248     {
    00249       _M_type = 1
    00250     };
    00251   };
    00252
    00253   //
    00254   // Floating point types
    00255   //
    00256   template<typename _Tp>
    00257   struct __is_floating
    00258   {
    00259     enum
    00260     {
    00261       _M_type = 0
    00262     };
    00263   };
    00264
    00265   // three specializations (float, double and 'long double')
    00266   template<>
    00267   struct __is_floating<float>
    00268   {
    00269     enum
    00270     {
    00271       _M_type = 1
    00272     };
    00273   };
    00274
    00275   template<>
    00276   struct __is_floating<double>
    00277   {
    00278     enum
    00279     {
    00280       _M_type = 1
    00281     };
    00282   };
    00283
    00284   template<>
    00285   struct __is_floating<long double>
    00286   {
    00287     enum
    00288     {
    00289       _M_type = 1
    00290     };
    00291   };
    00292
    00293   //
    00294   // An arithmetic type is an integer type or a floating point type
    00295   //
    00296   template<typename _Tp>
    00297   struct __is_arithmetic
    00298   {
    00299     enum
    00300     {
    00301       _M_type = __is_integer<_Tp>::_M_type || __is_floating<_Tp>::_M_type
    00302     };
    00303   };
    00304
    00305   //
    00306   // A fundamental type is `void' or and arithmetic type
    00307   //
    00308   template<typename _Tp>
    00309   struct __is_fundamental
    00310   {
    00311     enum
    00312     {
    00313       _M_type = __is_void<_Tp>::_M_type || __is_arithmetic<_Tp>::_M_type
    00314     };
    00315   };
    00316
    00317   //
    00318   // For the immediate use, the following is a good approximation
    00319   //
    00320
    00321   // NB: g++ can not compile these if declared within the class
    00322   // __is_pod itself.
    00323   namespace __gnu_internal
    00324   {
    00325     typedef char __one;
    00326     typedef char __two[2];
    00327
    00328     template <typename _Tp>
    00329     __one __test_type (int _Tp::*);
    00330     template <typename _Tp>
    00331     __two& __test_type (...);
    00332   }
    00333
    00334
    00335   template<typename _Tp>
    00336   struct __is_pod
    00337   {
    00338     enum
    00339     {
    00340       _M_type = (sizeof(__gnu_internal::__test_type<_Tp>(0)) != sizeof(__gnu_internal::__one))
    00341     };
    00342   };
    00343
    00344 } // namespace std
    00345
    00346
    00347 #endif //_CPP_TYPE_TRAITS_H