typetraits.hh
Go to the documentation of this file.00001 #ifndef DUNE_TYPETRAITS_HH
00002 #define DUNE_TYPETRAITS_HH
00003
00004 #if defined HAVE_TYPE_TRAITS
00005 #include <type_traits>
00006 #elif defined HAVE_TR1_TYPE_TRAITS
00007 #include <tr1/type_traits>
00008 #endif
00009
00010 namespace Dune
00011 {
00012
00026 struct Empty {};
00027
00032 template <typename T>
00033 class TypeTraits
00034 {
00035 private:
00036 template <class U>
00037 struct PointerTraits {
00038 enum { result = false };
00039 typedef Empty PointeeType;
00040 };
00041
00042 template <class U>
00043 struct PointerTraits<U*> {
00044 enum { result = true };
00045 typedef U PointeeType;
00046 };
00047
00048 template <class U> struct ReferenceTraits
00049 {
00050 enum { result = false };
00051 typedef U ReferredType;
00052 };
00053
00054 template <class U> struct ReferenceTraits<U&>
00055 {
00056 enum { result = true };
00057 typedef U ReferredType;
00058 };
00059
00060 public:
00061 enum { isPointer = PointerTraits<T>::result };
00062 typedef typename PointerTraits<T>::PointeeType PointeeType;
00063
00064 enum { isReference = ReferenceTraits<T>::result };
00065 typedef typename ReferenceTraits<T>::ReferredType ReferredType;
00066 };
00067
00072 template<typename T>
00073 struct ConstantVolatileTraits
00074 {
00075 enum{
00077 isVolatile=false,
00079 isConst=false
00080 };
00081
00083 typedef T UnqualifiedType;
00085 typedef const T ConstType;
00087 typedef const volatile T ConstVolatileType;
00088 };
00089
00090 template<typename T>
00091 struct ConstantVolatileTraits<const T>
00092 {
00093 enum{
00094 isVolatile=false, isConst=true
00095 };
00096 typedef T UnqualifiedType;
00097 typedef const UnqualifiedType ConstType;
00098 typedef const volatile UnqualifiedType ConstVolatileType;
00099 };
00100
00101
00102 template<typename T>
00103 struct ConstantVolatileTraits<volatile T>
00104 {
00105 enum{
00106 isVolatile=true, isConst=false
00107 };
00108 typedef T UnqualifiedType;
00109 typedef const UnqualifiedType ConstType;
00110 typedef const volatile UnqualifiedType ConstVolatileType;
00111 };
00112
00113 template<typename T>
00114 struct ConstantVolatileTraits<const volatile T>
00115 {
00116 enum{
00117 isVolatile=true, isConst=true
00118 };
00119 typedef T UnqualifiedType;
00120 typedef const UnqualifiedType ConstType;
00121 typedef const volatile UnqualifiedType ConstVolatileType;
00122 };
00123
00125 template<typename T>
00126 struct IsVolatile
00127 {
00128 enum{
00130 value=ConstantVolatileTraits<T>::isVolatile
00131 };
00132 };
00133
00135 template<typename T>
00136 struct IsConst
00137 {
00138 enum{
00140 value=ConstantVolatileTraits<T>::isConst
00141 };
00142 };
00143
00144 template<typename T, bool isVolatile>
00145 struct RemoveConstHelper
00146 {
00147 typedef typename ConstantVolatileTraits<T>::UnqualifiedType Type;
00148 };
00149
00150 template<typename T>
00151 struct RemoveConstHelper<T,true>
00152 {
00153 typedef volatile typename ConstantVolatileTraits<T>::UnqualifiedType Type;
00154 };
00155
00156 #if defined HAVE_TYPE_TRAITS
00157 using std::remove_const;
00158 #elif defined HAVE_TR1_TYPE_TRAITS
00159 using std::tr1::remove_const;
00160 #else
00161
00164 template<typename T>
00165 struct remove_const
00166 {
00167 typedef typename RemoveConstHelper<T, IsVolatile<T>::value>::Type type;
00168 };
00169 #endif
00170
00180 template<class From, class To>
00181 class Conversion
00182 {
00183 typedef char Small;
00184 struct Big{char dummy[2];};
00185 static Small test(To);
00186 static Big test(...);
00187 static typename TypeTraits< From >::ReferredType &makeFrom ();
00188
00189 public:
00190 enum {
00192 exists = sizeof(test(makeFrom())) == sizeof(Small),
00194 isTwoWay = exists && Conversion<To,From>::exists,
00196 sameType = false
00197 };
00198 Conversion(){}
00199
00200 };
00201
00202 template <class From>
00203 class Conversion<From, void>
00204 {
00205 public:
00206 enum {
00207 exists = false,
00208 isTwoWay = false,
00209 sameType = false
00210 };
00211 };
00212
00213 template <class To>
00214 class Conversion<void, To>
00215 {
00216 public:
00217 enum {
00218 exists = false,
00219 isTwoWay = false,
00220 sameType = false
00221 };
00222 };
00223
00224 template<>
00225 class Conversion< int, double >
00226 {
00227 public:
00228 enum {
00229 exists = true,
00230 isTwoWay = false,
00231 sameType = false
00232 };
00233 };
00234
00235 template<class T>
00236 class Conversion<T,T>{
00237 public:
00238 enum{ exists=true, isTwoWay=true, sameType=true};
00239 };
00240
00250 template <class Base, class Derived>
00251 class IsBaseOf
00252 {
00253 typedef typename ConstantVolatileTraits< typename TypeTraits< Base >::ReferredType >::UnqualifiedType RawBase;
00254 typedef typename ConstantVolatileTraits< typename TypeTraits< Derived >::ReferredType >::UnqualifiedType RawDerived;
00255 typedef char Small;
00256 struct Big{char dummy[2];};
00257 static Small test(RawBase*);
00258 static Big test(...);
00259 static RawDerived* &makePtr ();
00260 public:
00261 enum {
00263 value = sizeof(test(makePtr())) == sizeof(Small)
00264 };
00265 IsBaseOf(){}
00266
00267 };
00268
00275 template<class T1, class T2>
00276 struct IsInteroperable
00277 {
00278 enum{
00283 value = Conversion<T1,T2>::exists || Conversion<T2,T1>::exists
00284 };
00285 };
00286
00287 #ifdef HAVE_TYPE_TRAITS
00288 using std::enable_if;
00289 #else
00290
00296 template<bool b, typename T=void>
00297 struct enable_if
00298 {
00299 typedef T type;
00300 };
00301
00302 template<typename T>
00303 struct enable_if<false,T>
00304 {};
00305 #endif
00306
00307
00313 template<class T1, class T2, class Type>
00314 struct EnableIfInterOperable
00315 : public enable_if<IsInteroperable<T1,T2>::value, Type>
00316 {};
00317
00318 #if defined HAVE_TYPE_TRAITS
00319 using std::is_same;
00320 #elif defined HAVE_TR1_TYPE_TRAITS
00321 using std::tr1::is_same;
00322 #else
00323
00327 template<typename T1, typename T2>
00328 struct is_same
00329 {
00331 enum{
00332
00333 value=false
00334 };
00335 };
00336
00337
00338 template<typename T>
00339 struct is_same<T,T>
00340 {
00341 enum{ value=true};
00342 };
00343 #endif
00344
00353 template<bool first, class T1, class T2>
00354 struct SelectType
00355 {
00362 typedef T1 Type;
00363 };
00364
00365 template<class T1, class T2>
00366 struct SelectType<false,T1,T2>
00367 {
00368 typedef T2 Type;
00369 };
00371 }
00372 #endif