dune-common  2.2.0
typetraits.hh
Go to the documentation of this file.
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002 // vi: set et ts=8 sw=2 sts=2:
00003 #ifndef DUNE_TYPETRAITS_HH
00004 #define DUNE_TYPETRAITS_HH
00005 
00006 #if defined HAVE_TYPE_TRAITS
00007 #include <type_traits>
00008 #elif defined HAVE_TR1_TYPE_TRAITS
00009 #include <tr1/type_traits>
00010 #endif
00011 
00012 namespace Dune
00013 {
00014   
00028   struct Empty {};
00029 
00034   template <typename T>
00035   class TypeTraits
00036   {
00037   private:
00038     template <class U> 
00039     struct PointerTraits {
00040       enum { result = false };
00041       typedef Empty PointeeType;
00042     };
00043 
00044     template <class U>
00045     struct PointerTraits<U*> {
00046       enum { result = true };
00047       typedef U PointeeType;
00048     };
00049   
00050     template <class U> struct ReferenceTraits
00051     {
00052       enum { result = false };
00053       typedef U ReferredType;
00054     };
00055     
00056     template <class U> struct ReferenceTraits<U&>
00057     {
00058       enum { result = true };
00059       typedef U ReferredType;
00060     };
00061     
00062   public:
00063     enum { isPointer = PointerTraits<T>::result };
00064     typedef typename PointerTraits<T>::PointeeType PointeeType;
00065 
00066     enum { isReference = ReferenceTraits<T>::result };
00067     typedef typename ReferenceTraits<T>::ReferredType ReferredType;
00068  };
00069 
00074   template<typename T>
00075   struct ConstantVolatileTraits
00076   {
00077     enum{
00079       isVolatile=false,
00081         isConst=false
00082         };
00083     
00085     typedef T UnqualifiedType;
00087     typedef const T ConstType;
00089     typedef const volatile T ConstVolatileType;
00090   };
00091 
00092   template<typename T>
00093   struct ConstantVolatileTraits<const T>
00094   {
00095     enum{
00096       isVolatile=false, isConst=true
00097         };
00098     typedef T UnqualifiedType;
00099     typedef const UnqualifiedType ConstType;
00100     typedef const volatile UnqualifiedType ConstVolatileType;
00101   };
00102 
00103 
00104   template<typename T>
00105   struct ConstantVolatileTraits<volatile T>
00106   {
00107     enum{
00108       isVolatile=true, isConst=false
00109         };
00110     typedef T UnqualifiedType;
00111     typedef const UnqualifiedType ConstType;
00112     typedef const volatile UnqualifiedType ConstVolatileType;
00113   };
00114 
00115   template<typename T>
00116   struct ConstantVolatileTraits<const volatile T>
00117   {
00118     enum{
00119       isVolatile=true, isConst=true
00120         };
00121     typedef T UnqualifiedType;
00122     typedef const UnqualifiedType ConstType;
00123     typedef const volatile UnqualifiedType ConstVolatileType;
00124   };
00125 
00127   template<typename T>
00128   struct IsVolatile
00129   {
00130     enum{
00132       value=ConstantVolatileTraits<T>::isVolatile
00133         };
00134   };
00135 
00137   template<typename T>
00138   struct IsConst
00139   {
00140     enum{
00142       value=ConstantVolatileTraits<T>::isConst
00143         };
00144   };
00145 
00146   template<typename T, bool isVolatile>
00147   struct RemoveConstHelper
00148   {
00149     typedef typename ConstantVolatileTraits<T>::UnqualifiedType Type;
00150   };
00151 
00152   template<typename T>
00153   struct RemoveConstHelper<T,true>
00154   {
00155     typedef volatile typename ConstantVolatileTraits<T>::UnqualifiedType Type;
00156   };
00157 
00158 #if defined HAVE_TYPE_TRAITS
00159   using std::remove_const;
00160 #elif defined HAVE_TR1_TYPE_TRAITS
00161     using std::tr1::remove_const;
00162 #else
00163 
00166   template<typename T>
00167   struct remove_const
00168   {
00169       typedef typename RemoveConstHelper<T, IsVolatile<T>::value>::Type type;
00170   };
00171 #endif
00172 
00173 #if defined HAVE_TYPE_TRAITS
00174   using std::remove_reference;
00175 #elif defined HAVE_TR1_TYPE_TRAITS
00176   using std::tr1::remove_reference;
00177 #else
00178 
00179 
00183   template<typename T> struct remove_reference {
00185     typedef T type;
00186   };
00187 #  ifndef DOXYGEN
00188   template<typename T> struct remove_reference<T&> {
00189     typedef T type;
00190   };
00191 #  endif // ! defined(DOXYGEN)
00192 #endif
00193 
00203   template<class From, class To>
00204   class Conversion
00205   {
00206     typedef char Small;
00207     struct Big{char dummy[2];};
00208     static Small test(To);
00209     static Big test(...);
00210     static typename TypeTraits< From >::ReferredType &makeFrom ();
00211 
00212   public:
00213     enum {
00215       exists =  sizeof(test(makeFrom())) == sizeof(Small),
00217       isTwoWay = exists && Conversion<To,From>::exists,
00219       sameType = false
00220     };
00221     Conversion(){}
00222     
00223   };
00224 
00225   template <class From>
00226   class Conversion<From, void>
00227   {
00228   public:
00229     enum {
00230       exists = false,
00231       isTwoWay = false,
00232       sameType = false
00233     };
00234   };
00235 
00236   template <class To>
00237   class Conversion<void, To>
00238   {
00239   public:
00240     enum {
00241       exists = false,
00242       isTwoWay = false,
00243       sameType = false
00244     };
00245   };
00246 
00247   template<>
00248   class Conversion< int, double >
00249   {
00250   public:
00251     enum {
00252       exists = true,
00253       isTwoWay = false,
00254       sameType = false
00255     };
00256   };
00257 
00258   template<class T>
00259   class Conversion<T,T>{
00260   public:
00261     enum{ exists=true, isTwoWay=true, sameType=true};
00262   };
00263 
00273   template <class Base, class Derived>
00274   class IsBaseOf
00275   {
00276     typedef typename ConstantVolatileTraits< typename TypeTraits< Base >::ReferredType >::UnqualifiedType RawBase;
00277     typedef typename ConstantVolatileTraits< typename TypeTraits< Derived >::ReferredType >::UnqualifiedType RawDerived;
00278     typedef char Small;
00279     struct Big{char dummy[2];};
00280     static Small test(RawBase*);
00281     static Big test(...);
00282     static RawDerived* &makePtr ();
00283   public:
00284     enum {
00286       value = sizeof(test(makePtr())) == sizeof(Small)
00287     };
00288     IsBaseOf(){}
00289     
00290   };
00291 
00298   template<class T1, class T2>
00299   struct IsInteroperable
00300   {
00301     enum{
00306       value = Conversion<T1,T2>::exists || Conversion<T2,T1>::exists
00307         };
00308   };
00309 
00310 #ifdef HAVE_TYPE_TRAITS
00311   using std::enable_if;
00312 #else
00313 
00319   template<bool b, typename T=void>
00320   struct enable_if
00321   {
00322     typedef T type;
00323   };
00324 
00325   template<typename T>
00326   struct enable_if<false,T>
00327   {};
00328 #endif
00329 
00330 
00336   template<class T1, class T2, class Type>
00337   struct EnableIfInterOperable 
00338     : public enable_if<IsInteroperable<T1,T2>::value, Type>
00339   {};
00340   
00341 #if defined HAVE_TYPE_TRAITS
00342   using std::is_same;
00343 #elif defined HAVE_TR1_TYPE_TRAITS
00344   using std::tr1::is_same;
00345 #else
00346 
00350   template<typename T1, typename T2>
00351   struct is_same
00352   {
00354     enum{ 
00355       /* @brief Whether T1 is the same type as T2. */
00356       value=false
00357         };
00358   };
00359   
00360   
00361   template<typename T>
00362   struct is_same<T,T>
00363   {
00364     enum{ value=true};
00365   };
00366 #endif
00367 
00376   template<bool first, class T1, class T2>
00377   struct SelectType
00378   {
00385     typedef T1 Type;
00386   };
00387 
00388   template<class T1, class T2>
00389   struct SelectType<false,T1,T2>
00390   {
00391     typedef T2 Type;
00392   };
00393 
00395   //
00396   // integral_constant (C++0x 20.7.3 "Helper classes")
00397   //
00398 #if defined HAVE_TYPE_TRAITS
00399   using std::integral_constant;
00400   using std::true_type;
00401   using std::false_type;
00402 #elif defined HAVE_TR1_TYPE_TRAITS
00403   using std::tr1::integral_constant;
00404   using std::tr1::true_type;
00405   using std::tr1::false_type;
00406 #else
00407 
00408 
00412   template <class T, T v>
00413   struct integral_constant {
00415     static const T value = v;
00417     typedef T value_type;
00419     typedef integral_constant<T,v> type;
00421     operator value_type() { return value; }
00422   };
00423 
00425   typedef integral_constant<bool, true> true_type;
00427   typedef integral_constant<bool, false> false_type;
00428 #endif
00429 
00431 }
00432 #endif