dune-common
2.2.0
|
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