LLVM API Documentation
00001 //===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file provides a template class that determines if a type is a class or 00011 // not. The basic mechanism, based on using the pointer to member function of 00012 // a zero argument to a function was "boosted" from the boost type_traits 00013 // library. See http://www.boost.org/ for all the gory details. 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 #ifndef LLVM_SUPPORT_TYPE_TRAITS_H 00018 #define LLVM_SUPPORT_TYPE_TRAITS_H 00019 00020 #include "llvm/Support/DataTypes.h" 00021 #include <cstddef> 00022 #include <utility> 00023 00024 #ifndef __has_feature 00025 #define LLVM_DEFINED_HAS_FEATURE 00026 #define __has_feature(x) 0 00027 #endif 00028 00029 // This is actually the conforming implementation which works with abstract 00030 // classes. However, enough compilers have trouble with it that most will use 00031 // the one in boost/type_traits/object_traits.hpp. This implementation actually 00032 // works with VC7.0, but other interactions seem to fail when we use it. 00033 00034 namespace llvm { 00035 00036 namespace dont_use 00037 { 00038 // These two functions should never be used. They are helpers to 00039 // the is_class template below. They cannot be located inside 00040 // is_class because doing so causes at least GCC to think that 00041 // the value of the "value" enumerator is not constant. Placing 00042 // them out here (for some strange reason) allows the sizeof 00043 // operator against them to magically be constant. This is 00044 // important to make the is_class<T>::value idiom zero cost. it 00045 // evaluates to a constant 1 or 0 depending on whether the 00046 // parameter T is a class or not (respectively). 00047 template<typename T> char is_class_helper(void(T::*)()); 00048 template<typename T> double is_class_helper(...); 00049 } 00050 00051 template <typename T> 00052 struct is_class 00053 { 00054 // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For 00055 // more details: 00056 // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 00057 public: 00058 static const bool value = 00059 sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)); 00060 }; 00061 00062 00063 /// isPodLike - This is a type trait that is used to determine whether a given 00064 /// type can be copied around with memcpy instead of running ctors etc. 00065 template <typename T> 00066 struct isPodLike { 00067 #if __has_feature(is_trivially_copyable) 00068 // If the compiler supports the is_trivially_copyable trait use it, as it 00069 // matches the definition of isPodLike closely. 00070 static const bool value = __is_trivially_copyable(T); 00071 #else 00072 // If we don't know anything else, we can (at least) assume that all non-class 00073 // types are PODs. 00074 static const bool value = !is_class<T>::value; 00075 #endif 00076 }; 00077 00078 // std::pair's are pod-like if their elements are. 00079 template<typename T, typename U> 00080 struct isPodLike<std::pair<T, U> > { 00081 static const bool value = isPodLike<T>::value && isPodLike<U>::value; 00082 }; 00083 00084 00085 template <class T, T v> 00086 struct integral_constant { 00087 typedef T value_type; 00088 static const value_type value = v; 00089 typedef integral_constant<T,v> type; 00090 operator value_type() { return value; } 00091 }; 00092 00093 typedef integral_constant<bool, true> true_type; 00094 typedef integral_constant<bool, false> false_type; 00095 00096 /// \brief Metafunction that determines whether the two given types are 00097 /// equivalent. 00098 template<typename T, typename U> struct is_same : public false_type {}; 00099 template<typename T> struct is_same<T, T> : public true_type {}; 00100 00101 /// \brief Metafunction that removes const qualification from a type. 00102 template <typename T> struct remove_const { typedef T type; }; 00103 template <typename T> struct remove_const<const T> { typedef T type; }; 00104 00105 /// \brief Metafunction that removes volatile qualification from a type. 00106 template <typename T> struct remove_volatile { typedef T type; }; 00107 template <typename T> struct remove_volatile<volatile T> { typedef T type; }; 00108 00109 /// \brief Metafunction that removes both const and volatile qualification from 00110 /// a type. 00111 template <typename T> struct remove_cv { 00112 typedef typename remove_const<typename remove_volatile<T>::type>::type type; 00113 }; 00114 00115 /// \brief Helper to implement is_integral metafunction. 00116 template <typename T> struct is_integral_impl : false_type {}; 00117 template <> struct is_integral_impl< bool> : true_type {}; 00118 template <> struct is_integral_impl< char> : true_type {}; 00119 template <> struct is_integral_impl< signed char> : true_type {}; 00120 template <> struct is_integral_impl<unsigned char> : true_type {}; 00121 template <> struct is_integral_impl< wchar_t> : true_type {}; 00122 template <> struct is_integral_impl< short> : true_type {}; 00123 template <> struct is_integral_impl<unsigned short> : true_type {}; 00124 template <> struct is_integral_impl< int> : true_type {}; 00125 template <> struct is_integral_impl<unsigned int> : true_type {}; 00126 template <> struct is_integral_impl< long> : true_type {}; 00127 template <> struct is_integral_impl<unsigned long> : true_type {}; 00128 template <> struct is_integral_impl< long long> : true_type {}; 00129 template <> struct is_integral_impl<unsigned long long> : true_type {}; 00130 00131 /// \brief Metafunction that determines whether the given type is an integral 00132 /// type. 00133 template <typename T> 00134 struct is_integral : is_integral_impl<T> {}; 00135 00136 /// \brief Metafunction to remove reference from a type. 00137 template <typename T> struct remove_reference { typedef T type; }; 00138 template <typename T> struct remove_reference<T&> { typedef T type; }; 00139 00140 /// \brief Metafunction that determines whether the given type is a pointer 00141 /// type. 00142 template <typename T> struct is_pointer : false_type {}; 00143 template <typename T> struct is_pointer<T*> : true_type {}; 00144 template <typename T> struct is_pointer<T* const> : true_type {}; 00145 template <typename T> struct is_pointer<T* volatile> : true_type {}; 00146 template <typename T> struct is_pointer<T* const volatile> : true_type {}; 00147 00148 /// \brief Metafunction that determines wheather the given type is a reference. 00149 template <typename T> struct is_reference : false_type {}; 00150 template <typename T> struct is_reference<T&> : true_type {}; 00151 00152 /// \brief Metafunction that determines whether the given type is either an 00153 /// integral type or an enumeration type. 00154 /// 00155 /// Note that this accepts potentially more integral types than we whitelist 00156 /// above for is_integral because it is based on merely being convertible 00157 /// implicitly to an integral type. 00158 template <typename T> class is_integral_or_enum { 00159 // Provide an overload which can be called with anything implicitly 00160 // convertible to an unsigned long long. This should catch integer types and 00161 // enumeration types at least. We blacklist classes with conversion operators 00162 // below. 00163 static double check_int_convertible(unsigned long long); 00164 static char check_int_convertible(...); 00165 00166 typedef typename remove_reference<T>::type UnderlyingT; 00167 static UnderlyingT &nonce_instance; 00168 00169 public: 00170 static const bool 00171 value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value && 00172 !is_same<UnderlyingT, float>::value && 00173 !is_same<UnderlyingT, double>::value && 00174 sizeof(char) != sizeof(check_int_convertible(nonce_instance))); 00175 }; 00176 00177 // enable_if_c - Enable/disable a template based on a metafunction 00178 template<bool Cond, typename T = void> 00179 struct enable_if_c { 00180 typedef T type; 00181 }; 00182 00183 template<typename T> struct enable_if_c<false, T> { }; 00184 00185 // enable_if - Enable/disable a template based on a metafunction 00186 template<typename Cond, typename T = void> 00187 struct enable_if : public enable_if_c<Cond::value, T> { }; 00188 00189 namespace dont_use { 00190 template<typename Base> char base_of_helper(const volatile Base*); 00191 template<typename Base> double base_of_helper(...); 00192 } 00193 00194 /// is_base_of - Metafunction to determine whether one type is a base class of 00195 /// (or identical to) another type. 00196 template<typename Base, typename Derived> 00197 struct is_base_of { 00198 static const bool value 00199 = is_class<Base>::value && is_class<Derived>::value && 00200 sizeof(char) == sizeof(dont_use::base_of_helper<Base>((Derived*)0)); 00201 }; 00202 00203 // remove_pointer - Metafunction to turn Foo* into Foo. Defined in 00204 // C++0x [meta.trans.ptr]. 00205 template <typename T> struct remove_pointer { typedef T type; }; 00206 template <typename T> struct remove_pointer<T*> { typedef T type; }; 00207 template <typename T> struct remove_pointer<T*const> { typedef T type; }; 00208 template <typename T> struct remove_pointer<T*volatile> { typedef T type; }; 00209 template <typename T> struct remove_pointer<T*const volatile> { 00210 typedef T type; }; 00211 00212 // If T is a pointer, just return it. If it is not, return T&. 00213 template<typename T, typename Enable = void> 00214 struct add_lvalue_reference_if_not_pointer { typedef T &type; }; 00215 00216 template<typename T> 00217 struct add_lvalue_reference_if_not_pointer<T, 00218 typename enable_if<is_pointer<T> >::type> { 00219 typedef T type; 00220 }; 00221 00222 // If T is a pointer to X, return a pointer to const X. If it is not, return 00223 // const T. 00224 template<typename T, typename Enable = void> 00225 struct add_const_past_pointer { typedef const T type; }; 00226 00227 template<typename T> 00228 struct add_const_past_pointer<T, typename enable_if<is_pointer<T> >::type> { 00229 typedef const typename remove_pointer<T>::type *type; 00230 }; 00231 00232 template <bool, typename T, typename F> 00233 struct conditional { typedef T type; }; 00234 00235 template <typename T, typename F> 00236 struct conditional<false, T, F> { typedef F type; }; 00237 00238 } 00239 00240 #ifdef LLVM_DEFINED_HAS_FEATURE 00241 #undef __has_feature 00242 #endif 00243 00244 #endif