1193323Sed//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file provides a template class that determines if a type is a class or 11193323Sed// not. The basic mechanism, based on using the pointer to member function of 12193323Sed// a zero argument to a function was "boosted" from the boost type_traits 13193323Sed// library. See http://www.boost.org/ for all the gory details. 14193323Sed// 15193323Sed//===----------------------------------------------------------------------===// 16193323Sed 17193323Sed#ifndef LLVM_SUPPORT_TYPE_TRAITS_H 18193323Sed#define LLVM_SUPPORT_TYPE_TRAITS_H 19193323Sed 20234353Sdim#include "llvm/Support/DataTypes.h" 21234353Sdim#include <cstddef> 22200581Srdivacky#include <utility> 23200581Srdivacky 24239462Sdim#ifndef __has_feature 25239462Sdim#define LLVM_DEFINED_HAS_FEATURE 26239462Sdim#define __has_feature(x) 0 27239462Sdim#endif 28239462Sdim 29193323Sed// This is actually the conforming implementation which works with abstract 30193323Sed// classes. However, enough compilers have trouble with it that most will use 31193323Sed// the one in boost/type_traits/object_traits.hpp. This implementation actually 32193323Sed// works with VC7.0, but other interactions seem to fail when we use it. 33193323Sed 34193323Sednamespace llvm { 35200581Srdivacky 36193323Sednamespace dont_use 37193323Sed{ 38193323Sed // These two functions should never be used. They are helpers to 39193323Sed // the is_class template below. They cannot be located inside 40193323Sed // is_class because doing so causes at least GCC to think that 41193323Sed // the value of the "value" enumerator is not constant. Placing 42193323Sed // them out here (for some strange reason) allows the sizeof 43193323Sed // operator against them to magically be constant. This is 44193323Sed // important to make the is_class<T>::value idiom zero cost. it 45193323Sed // evaluates to a constant 1 or 0 depending on whether the 46193323Sed // parameter T is a class or not (respectively). 47198090Srdivacky template<typename T> char is_class_helper(void(T::*)()); 48193323Sed template<typename T> double is_class_helper(...); 49193323Sed} 50193323Sed 51193323Sedtemplate <typename T> 52193323Sedstruct is_class 53193323Sed{ 54193323Sed // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For 55193323Sed // more details: 56193323Sed // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 57243830Sdimpublic: 58243830Sdim static const bool value = 59243830Sdim sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)); 60193323Sed}; 61200581Srdivacky 62200581Srdivacky 63200581Srdivacky/// isPodLike - This is a type trait that is used to determine whether a given 64200581Srdivacky/// type can be copied around with memcpy instead of running ctors etc. 65200581Srdivackytemplate <typename T> 66200581Srdivackystruct isPodLike { 67239462Sdim#if __has_feature(is_trivially_copyable) 68239462Sdim // If the compiler supports the is_trivially_copyable trait use it, as it 69239462Sdim // matches the definition of isPodLike closely. 70239462Sdim static const bool value = __is_trivially_copyable(T); 71239462Sdim#else 72200581Srdivacky // If we don't know anything else, we can (at least) assume that all non-class 73200581Srdivacky // types are PODs. 74200581Srdivacky static const bool value = !is_class<T>::value; 75239462Sdim#endif 76200581Srdivacky}; 77193323Sed 78200581Srdivacky// std::pair's are pod-like if their elements are. 79200581Srdivackytemplate<typename T, typename U> 80200581Srdivackystruct isPodLike<std::pair<T, U> > { 81234353Sdim static const bool value = isPodLike<T>::value && isPodLike<U>::value; 82200581Srdivacky}; 83200581Srdivacky 84200581Srdivacky 85234353Sdimtemplate <class T, T v> 86234353Sdimstruct integral_constant { 87234353Sdim typedef T value_type; 88234353Sdim static const value_type value = v; 89234353Sdim typedef integral_constant<T,v> type; 90234353Sdim operator value_type() { return value; } 91234353Sdim}; 92234353Sdim 93234353Sdimtypedef integral_constant<bool, true> true_type; 94234353Sdimtypedef integral_constant<bool, false> false_type; 95234353Sdim 96198090Srdivacky/// \brief Metafunction that determines whether the two given types are 97198090Srdivacky/// equivalent. 98234353Sdimtemplate<typename T, typename U> struct is_same : public false_type {}; 99234353Sdimtemplate<typename T> struct is_same<T, T> : public true_type {}; 100234353Sdim 101234353Sdim/// \brief Metafunction that removes const qualification from a type. 102234353Sdimtemplate <typename T> struct remove_const { typedef T type; }; 103234353Sdimtemplate <typename T> struct remove_const<const T> { typedef T type; }; 104234353Sdim 105234353Sdim/// \brief Metafunction that removes volatile qualification from a type. 106234353Sdimtemplate <typename T> struct remove_volatile { typedef T type; }; 107234353Sdimtemplate <typename T> struct remove_volatile<volatile T> { typedef T type; }; 108234353Sdim 109234353Sdim/// \brief Metafunction that removes both const and volatile qualification from 110234353Sdim/// a type. 111234353Sdimtemplate <typename T> struct remove_cv { 112234353Sdim typedef typename remove_const<typename remove_volatile<T>::type>::type type; 113198090Srdivacky}; 114198090Srdivacky 115234353Sdim/// \brief Helper to implement is_integral metafunction. 116234353Sdimtemplate <typename T> struct is_integral_impl : false_type {}; 117234353Sdimtemplate <> struct is_integral_impl< bool> : true_type {}; 118234353Sdimtemplate <> struct is_integral_impl< char> : true_type {}; 119234353Sdimtemplate <> struct is_integral_impl< signed char> : true_type {}; 120234353Sdimtemplate <> struct is_integral_impl<unsigned char> : true_type {}; 121234353Sdimtemplate <> struct is_integral_impl< wchar_t> : true_type {}; 122234353Sdimtemplate <> struct is_integral_impl< short> : true_type {}; 123234353Sdimtemplate <> struct is_integral_impl<unsigned short> : true_type {}; 124234353Sdimtemplate <> struct is_integral_impl< int> : true_type {}; 125234353Sdimtemplate <> struct is_integral_impl<unsigned int> : true_type {}; 126234353Sdimtemplate <> struct is_integral_impl< long> : true_type {}; 127234353Sdimtemplate <> struct is_integral_impl<unsigned long> : true_type {}; 128234353Sdimtemplate <> struct is_integral_impl< long long> : true_type {}; 129234353Sdimtemplate <> struct is_integral_impl<unsigned long long> : true_type {}; 130234353Sdim 131234353Sdim/// \brief Metafunction that determines whether the given type is an integral 132234353Sdim/// type. 133234353Sdimtemplate <typename T> 134234353Sdimstruct is_integral : is_integral_impl<T> {}; 135234353Sdim 136234353Sdim/// \brief Metafunction to remove reference from a type. 137234353Sdimtemplate <typename T> struct remove_reference { typedef T type; }; 138234353Sdimtemplate <typename T> struct remove_reference<T&> { typedef T type; }; 139234353Sdim 140234353Sdim/// \brief Metafunction that determines whether the given type is a pointer 141234353Sdim/// type. 142234353Sdimtemplate <typename T> struct is_pointer : false_type {}; 143234353Sdimtemplate <typename T> struct is_pointer<T*> : true_type {}; 144234353Sdimtemplate <typename T> struct is_pointer<T* const> : true_type {}; 145234353Sdimtemplate <typename T> struct is_pointer<T* volatile> : true_type {}; 146234353Sdimtemplate <typename T> struct is_pointer<T* const volatile> : true_type {}; 147234353Sdim 148249423Sdim/// \brief Metafunction that determines wheather the given type is a reference. 149249423Sdimtemplate <typename T> struct is_reference : false_type {}; 150249423Sdimtemplate <typename T> struct is_reference<T&> : true_type {}; 151249423Sdim 152234353Sdim/// \brief Metafunction that determines whether the given type is either an 153234353Sdim/// integral type or an enumeration type. 154234353Sdim/// 155234353Sdim/// Note that this accepts potentially more integral types than we whitelist 156234353Sdim/// above for is_integral because it is based on merely being convertible 157234353Sdim/// implicitly to an integral type. 158234353Sdimtemplate <typename T> class is_integral_or_enum { 159234353Sdim // Provide an overload which can be called with anything implicitly 160234353Sdim // convertible to an unsigned long long. This should catch integer types and 161234353Sdim // enumeration types at least. We blacklist classes with conversion operators 162234353Sdim // below. 163234353Sdim static double check_int_convertible(unsigned long long); 164234353Sdim static char check_int_convertible(...); 165234353Sdim 166234353Sdim typedef typename remove_reference<T>::type UnderlyingT; 167234353Sdim static UnderlyingT &nonce_instance; 168234353Sdim 169234353Sdimpublic: 170243830Sdim static const bool 171234353Sdim value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value && 172234353Sdim !is_same<UnderlyingT, float>::value && 173234353Sdim !is_same<UnderlyingT, double>::value && 174243830Sdim sizeof(char) != sizeof(check_int_convertible(nonce_instance))); 175198090Srdivacky}; 176234353Sdim 177198090Srdivacky// enable_if_c - Enable/disable a template based on a metafunction 178198090Srdivackytemplate<bool Cond, typename T = void> 179198090Srdivackystruct enable_if_c { 180198090Srdivacky typedef T type; 181198090Srdivacky}; 182198090Srdivacky 183198090Srdivackytemplate<typename T> struct enable_if_c<false, T> { }; 184198090Srdivacky 185198090Srdivacky// enable_if - Enable/disable a template based on a metafunction 186198090Srdivackytemplate<typename Cond, typename T = void> 187198090Srdivackystruct enable_if : public enable_if_c<Cond::value, T> { }; 188198090Srdivacky 189198090Srdivackynamespace dont_use { 190198090Srdivacky template<typename Base> char base_of_helper(const volatile Base*); 191198090Srdivacky template<typename Base> double base_of_helper(...); 192193323Sed} 193193323Sed 194198090Srdivacky/// is_base_of - Metafunction to determine whether one type is a base class of 195198090Srdivacky/// (or identical to) another type. 196198090Srdivackytemplate<typename Base, typename Derived> 197198090Srdivackystruct is_base_of { 198198090Srdivacky static const bool value 199198090Srdivacky = is_class<Base>::value && is_class<Derived>::value && 200198090Srdivacky sizeof(char) == sizeof(dont_use::base_of_helper<Base>((Derived*)0)); 201198090Srdivacky}; 202198090Srdivacky 203198396Srdivacky// remove_pointer - Metafunction to turn Foo* into Foo. Defined in 204198396Srdivacky// C++0x [meta.trans.ptr]. 205198396Srdivackytemplate <typename T> struct remove_pointer { typedef T type; }; 206198396Srdivackytemplate <typename T> struct remove_pointer<T*> { typedef T type; }; 207198396Srdivackytemplate <typename T> struct remove_pointer<T*const> { typedef T type; }; 208198396Srdivackytemplate <typename T> struct remove_pointer<T*volatile> { typedef T type; }; 209198396Srdivackytemplate <typename T> struct remove_pointer<T*const volatile> { 210198396Srdivacky typedef T type; }; 211198396Srdivacky 212249423Sdim// If T is a pointer, just return it. If it is not, return T&. 213249423Sdimtemplate<typename T, typename Enable = void> 214249423Sdimstruct add_lvalue_reference_if_not_pointer { typedef T &type; }; 215249423Sdim 216249423Sdimtemplate<typename T> 217249423Sdimstruct add_lvalue_reference_if_not_pointer<T, 218249423Sdim typename enable_if<is_pointer<T> >::type> { 219249423Sdim typedef T type; 220249423Sdim}; 221249423Sdim 222249423Sdim// If T is a pointer to X, return a pointer to const X. If it is not, return 223249423Sdim// const T. 224249423Sdimtemplate<typename T, typename Enable = void> 225249423Sdimstruct add_const_past_pointer { typedef const T type; }; 226249423Sdim 227249423Sdimtemplate<typename T> 228249423Sdimstruct add_const_past_pointer<T, typename enable_if<is_pointer<T> >::type> { 229249423Sdim typedef const typename remove_pointer<T>::type *type; 230249423Sdim}; 231249423Sdim 232199481Srdivackytemplate <bool, typename T, typename F> 233199481Srdivackystruct conditional { typedef T type; }; 234199481Srdivacky 235199481Srdivackytemplate <typename T, typename F> 236199481Srdivackystruct conditional<false, T, F> { typedef F type; }; 237199481Srdivacky 238198090Srdivacky} 239198090Srdivacky 240239462Sdim#ifdef LLVM_DEFINED_HAS_FEATURE 241239462Sdim#undef __has_feature 242193323Sed#endif 243239462Sdim 244239462Sdim#endif 245