LLVM API Documentation

type_traits.h
Go to the documentation of this file.
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