type_traits.h

Go to the documentation of this file.
00001 00004 /* 00005 * Copyright © 2000, 2001 Sofus Mortensen, Paul Hollingsworth 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 /* 00020 * Partial copyright for is_const, is_volatile and is_reference. 00021 * 00022 * (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. 00023 * Permission to copy, use, modify, sell and 00024 * distribute this software is granted provided this copyright notice appears 00025 * in all copies. This software is provided "as is" without express or implied 00026 * warranty, and with no claim as to its suitability for any purpose. 00027 */ 00028 00029 #ifndef COMET_TYPE_TRAITS_H 00030 #define COMET_TYPE_TRAITS_H 00031 00032 namespace comet { 00033 00036 namespace type_traits { 00037 00039 // From www.boost.org 00040 00041 //* is a type T declared const - is_const<T> 00042 namespace detail{ 00043 typedef char yes_result; 00044 typedef char (&no_result)[8]; 00045 yes_result is_const_helper(const volatile void*); 00046 no_result is_const_helper(volatile void *); 00047 yes_result is_volatile_helper(const volatile void*); 00048 no_result is_volatile_helper(const void *); 00049 00050 template <typename T> struct helper { T t; }; 00051 } 00052 00053 template <typename T> struct is_const 00054 { 00055 enum{ result = (sizeof(detail::yes_result) == sizeof( detail::is_const_helper( 00056 & ((reinterpret_cast<detail::helper<T> *>(0))->t)) 00057 )) 00058 }; 00059 }; 00060 00061 template <typename T> struct is_volatile 00062 { 00063 enum{ result = (sizeof(detail::yes_result) == sizeof(detail::is_volatile_helper( 00064 & ((reinterpret_cast<detail::helper<T> *>(0))->t)) 00065 )) 00066 }; 00067 }; 00068 00069 # pragma warning(push) 00070 # pragma warning(disable: 4181) 00071 00072 //* is a type T a reference type - is_reference<T> 00073 template <typename T> struct is_reference 00074 { 00075 private: 00076 typedef T const volatile cv_t; 00077 public: 00078 enum // dwa 10/27/00 - VC6.4 seems to choke on short-circuit (&&,||) 00079 { // evaluations in constant expressions 00080 value = !is_const<cv_t>::result | !is_volatile<cv_t>::result 00081 }; 00082 }; 00083 00084 template <> struct is_reference<void> 00085 { 00086 enum{ value = false }; 00087 }; 00088 00089 # pragma warning(pop) 00090 00091 00093 00094 template<typename T> struct is_integer { enum { result = false }; }; 00095 template<> struct is_integer<bool> { enum { result = true }; }; 00096 template<> struct is_integer<char> { enum { result = true }; }; 00097 template<> struct is_integer<signed char> { enum { result = true }; }; 00098 template<> struct is_integer<unsigned char> { enum { result = true }; }; 00099 // template<> struct is_integer<wchar_t> { enum { result = true }; }; 00100 template<> struct is_integer<short> { enum { result = true }; }; 00101 template<> struct is_integer<unsigned short> { enum { result = true }; }; 00102 template<> struct is_integer<int> { enum { result = true }; }; 00103 template<> struct is_integer<unsigned int> { enum { result = true }; }; 00104 template<> struct is_integer<long> { enum { result = true }; }; 00105 template<> struct is_integer<unsigned long> { enum { result = true }; }; 00106 00108 00111 struct _PointerShim { 00112 // Since the compiler only allows at most one non-trivial 00113 // implicit conversion we can make use of a shim class to 00114 // be sure that IsPtr below doesn't accept classes with 00115 // implicit pointer conversion operators 00116 _PointerShim(const volatile void*); // no implementation 00117 }; 00119 00120 // These are the discriminating functions 00121 static char __cdecl _IsP(bool, _PointerShim); // no implementation is required 00122 static char* __cdecl _IsP(bool, ...); // no implementation is required 00123 00124 template <class _Tp> 00125 struct is_pointer { 00126 // This template meta function takes a type T 00127 // and returns true exactly when T is a pointer. 00128 // One can imagine meta-functions discriminating on 00129 // other criteria. 00130 static _Tp& __null_rep(); 00131 enum { result = (sizeof(_IsP(false,__null_rep())) == sizeof(char)) }; 00132 }; 00133 00134 // Work out whether the Type is something we can use operator-> on 00135 // (hopefully). If we fail, the worst we get is a level 3 warinng. 00136 template <class _Tp> 00137 struct is_class_pointer 00138 { 00139 enum { result = (is_pointer<_Tp>::result && ! is_integer<_Tp>::result) }; 00140 }; 00141 00142 template<int x> struct int_holder 00143 { 00144 enum { result = x }; 00145 }; 00146 00147 template<typename T> struct type_holder 00148 { 00149 typedef T result; 00150 }; 00151 00152 /* template<typename T, typename U> class is_static_compatible 00153 { 00154 class yes { }; 00155 class no {char a[10]; }; 00156 00157 static yes test( U * ); 00158 static no test( ... ); 00159 00160 public: 00161 enum { is = sizeof(test(static_cast<T*>(0))) == sizeof(yes) ? true : false }; 00162 };*/ 00163 00164 template<typename T, typename U> class is_cast_operator_compatible 00165 { 00166 protected: 00167 class yes { }; 00168 class no {char a[10]; }; 00169 00170 static yes test( U* ); 00171 static no test( ... ); 00172 00173 public: 00174 enum { is = sizeof(test(*static_cast<T*>(0))) == sizeof(yes) /*? 1 : 0 */}; 00175 }; 00176 00177 #ifndef COMET_PARTIAL_SPECIALISATION 00178 template<typename T> struct conversion_aux 00179 { 00180 template<typename U> class X 00181 { 00182 protected: 00183 class yes { }; 00184 class no {char a[10]; }; 00185 static T makeT(); 00186 00187 static yes test(U); 00188 static no test(...); 00189 public: 00190 enum { exists = sizeof(test(makeT())) == sizeof(yes) }; 00191 enum { same_type = false }; 00192 }; 00193 00194 00195 template<> class X<T> 00196 { 00197 public: 00198 enum { exists = true }; 00199 enum { same_type = true }; 00200 }; 00201 00202 }; 00203 template<typename T, typename U> struct conversion 00204 { 00205 enum { exists = conversion_aux<T>::X<U>::exists }; 00206 enum { same_type = conversion_aux<T>::X<U>::same_type }; 00207 enum { exists_two_way = exists && conversion_aux<U>::X<T>::exists }; 00208 }; 00209 #else 00210 template<typename T, typename U> struct conversion 00211 { 00212 protected: 00213 class yes { }; 00214 class no {char a[10]; }; 00215 static T makeT(); 00216 00217 static yes test(U); 00218 static no test(...); 00219 public: 00220 enum { exists = sizeof(test(makeT())) == sizeof(yes) }; 00221 enum { same_type = false }; 00222 enum { exists_two_way = conversion<U,T>::exists}; 00223 00224 }; 00225 template<typename T> struct conversion<T,T> 00226 { 00227 00228 enum { exists = true }; 00229 enum { same_type = true }; 00230 enum { exists_two_way = true}; 00231 }; 00232 00233 #endif // COMET_PARTIAL_SPECIALISATION 00234 00235 template<typename T, typename U> struct super_sub_class 00236 { 00237 enum { result = conversion<const U*, const T*>::exists && !conversion<const T*, const void*>::same_type }; 00238 }; 00239 00240 inline bool is_null_vtable_entry(void *p,short n) 00241 { 00242 return ((n<0)?true:(0==(*reinterpret_cast<long *>(reinterpret_cast<char *>(*(reinterpret_cast<long *>(p)))+n)))); 00243 } 00244 00245 } 00246 00247 namespace impl { 00248 00249 // used by NutshellImpl's 00250 struct false_type {}; 00251 struct true_type {}; 00252 00253 template<int T> struct is_one { typedef false_type val; }; 00254 template<> struct is_one<1> { typedef true_type val; }; 00255 00256 } 00257 00258 00259 } 00260 00261 00262 #endif