type_traits.h revision 4e58263459d7f9ae862b52adafe585b66411272f
1551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===//
263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman//
35c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner//                     The LLVM Compiler Infrastructure
45c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman//
85c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner//===----------------------------------------------------------------------===//
95c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner//
105c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner// This file provides a template class that determines if a type is a class or
115c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner// not. The basic mechanism, based on using the pointer to member function of
1263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman// a zero argument to a function was "boosted" from the boost type_traits
1363b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman// library. See http://www.boost.org/ for all the gory details.
145c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner//
155c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner//===----------------------------------------------------------------------===//
165c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner
175c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner#ifndef LLVM_SUPPORT_TYPE_TRAITS_H
185c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner#define LLVM_SUPPORT_TYPE_TRAITS_H
195c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner
200b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth#include "llvm/Support/DataTypes.h"
2188c48fae6956f17273704da53a2b3ab2981529c1Chandler Carruth#include <cstddef>
224bbf4ee1491637c247e195e19e3e4a8ee5ad72faChris Lattner#include <utility>
234bbf4ee1491637c247e195e19e3e4a8ee5ad72faChris Lattner
245c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner// This is actually the conforming implementation which works with abstract
255c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner// classes.  However, enough compilers have trouble with it that most will use
265c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner// the one in boost/type_traits/object_traits.hpp. This implementation actually
275c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner// works with VC7.0, but other interactions seem to fail when we use it.
285c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner
295c4d53a4d1bce60051fd71af1791791acb2000daChris Lattnernamespace llvm {
304bbf4ee1491637c247e195e19e3e4a8ee5ad72faChris Lattner
315c4d53a4d1bce60051fd71af1791791acb2000daChris Lattnernamespace dont_use
325c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner{
335c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    // These two functions should never be used. They are helpers to
3463b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman    // the is_class template below. They cannot be located inside
355c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    // is_class because doing so causes at least GCC to think that
365c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    // the value of the "value" enumerator is not constant. Placing
3763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman    // them out here (for some strange reason) allows the sizeof
385c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    // operator against them to magically be constant. This is
395c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    // important to make the is_class<T>::value idiom zero cost. it
4063b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman    // evaluates to a constant 1 or 0 depending on whether the
415c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    // parameter T is a class or not (respectively).
42a9ad04191cb56c42944b17980b8b2bb2afe11ab2Dan Gohman    template<typename T> char is_class_helper(void(T::*)());
435c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    template<typename T> double is_class_helper(...);
445c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner}
455c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner
465c4d53a4d1bce60051fd71af1791791acb2000daChris Lattnertemplate <typename T>
475c4d53a4d1bce60051fd71af1791791acb2000daChris Lattnerstruct is_class
485c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner{
495c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner  // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For
505c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner  // more details:
515c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner  // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1
525c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner public:
535c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner    enum { value = sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)) };
545c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner};
55dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner
56dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner
57dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner/// isPodLike - This is a type trait that is used to determine whether a given
58dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner/// type can be copied around with memcpy instead of running ctors etc.
59dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattnertemplate <typename T>
60dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattnerstruct isPodLike {
61dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner  // If we don't know anything else, we can (at least) assume that all non-class
62dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner  // types are PODs.
63dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner  static const bool value = !is_class<T>::value;
64dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner};
65dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner
66dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner// std::pair's are pod-like if their elements are.
67dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattnertemplate<typename T, typename U>
68dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattnerstruct isPodLike<std::pair<T, U> > {
694e58263459d7f9ae862b52adafe585b66411272fBenjamin Kramer  static const bool value = isPodLike<T>::value && isPodLike<U>::value;
70dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner};
71dc2e570411bb1b1345a6b9840050aca823835a81Chris Lattner
725c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner
730b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <class T, T v>
740b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthstruct integral_constant {
750b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth  typedef T value_type;
760b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth  static const value_type value = v;
770b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth  typedef integral_constant<T,v> type;
780b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth  operator value_type() { return value; }
790b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth};
800b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth
810b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtypedef integral_constant<bool, true> true_type;
820b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtypedef integral_constant<bool, false> false_type;
830b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth
84404aa26b26eb62c57daac8246159220eb173ae94Douglas Gregor/// \brief Metafunction that determines whether the two given types are
85404aa26b26eb62c57daac8246159220eb173ae94Douglas Gregor/// equivalent.
860b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate<typename T, typename U> struct is_same       : public false_type {};
870b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate<typename T>             struct is_same<T, T> : public true_type {};
880b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth
890b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth/// \brief Metafunction that removes const qualification from a type.
900b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <typename T> struct remove_const          { typedef T type; };
910b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <typename T> struct remove_const<const T> { typedef T type; };
92404aa26b26eb62c57daac8246159220eb173ae94Douglas Gregor
930b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth/// \brief Metafunction that removes volatile qualification from a type.
940b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <typename T> struct remove_volatile             { typedef T type; };
950b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <typename T> struct remove_volatile<volatile T> { typedef T type; };
960b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth
970b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth/// \brief Metafunction that removes both const and volatile qualification from
980b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth/// a type.
990b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <typename T> struct remove_cv {
1000b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth  typedef typename remove_const<typename remove_volatile<T>::type>::type type;
101404aa26b26eb62c57daac8246159220eb173ae94Douglas Gregor};
1020b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth
1030b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth/// \brief Helper to implement is_integral metafunction.
1040b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <typename T> struct is_integral_impl           : false_type {};
1050b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<         bool>      : true_type {};
1060b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<         char>      : true_type {};
1070b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<  signed char>      : true_type {};
1080b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<unsigned char>      : true_type {};
1090b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<         wchar_t>   : true_type {};
1100b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<         short>     : true_type {};
1110b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<unsigned short>     : true_type {};
1120b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<         int>       : true_type {};
1130b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<unsigned int>       : true_type {};
1140b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<         long>      : true_type {};
1150b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<unsigned long>      : true_type {};
1160b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<         long long> : true_type {};
1170b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <> struct is_integral_impl<unsigned long long> : true_type {};
1180b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth
1190b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth/// \brief Metafunction that determines whether the given type is an integral
1200b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth/// type.
1210b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthtemplate <typename T>
1220b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruthstruct is_integral : is_integral_impl<T> {};
1230b66c6fca22e85f732cf58f459a06c06833d1882Chandler Carruth
124cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth/// \brief Metafunction to remove reference from a type.
125cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> struct remove_reference { typedef T type; };
126cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> struct remove_reference<T&> { typedef T type; };
127cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth
128cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth/// \brief Metafunction that determines whether the given type is a pointer
129cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth/// type.
130cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> struct is_pointer : false_type {};
131cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> struct is_pointer<T*> : true_type {};
132cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> struct is_pointer<T* const> : true_type {};
133cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> struct is_pointer<T* volatile> : true_type {};
134cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> struct is_pointer<T* const volatile> : true_type {};
135d4d8b2a7f6d29b44cbc084b49042f44ef109da0cChandler Carruth
136ff12877a6f4db734cf0a156dc2ef815a839a79ecChandler Carruth/// \brief Metafunction that determines whether the given type is either an
137ff12877a6f4db734cf0a156dc2ef815a839a79ecChandler Carruth/// integral type or an enumeration type.
138ff12877a6f4db734cf0a156dc2ef815a839a79ecChandler Carruth///
139ff12877a6f4db734cf0a156dc2ef815a839a79ecChandler Carruth/// Note that this accepts potentially more integral types than we whitelist
140cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth/// above for is_integral because it is based on merely being convertible
141cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth/// implicitly to an integral type.
142cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthtemplate <typename T> class is_integral_or_enum {
143cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  // Provide an overload which can be called with anything implicitly
144cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  // convertible to an unsigned long long. This should catch integer types and
145cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  // enumeration types at least. We blacklist classes with conversion operators
146cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  // below.
147cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  static double check_int_convertible(unsigned long long);
148cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  static char check_int_convertible(...);
149cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth
150cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  typedef typename remove_reference<T>::type UnderlyingT;
151cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth  static UnderlyingT &nonce_instance;
152cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth
153cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruthpublic:
154d4d8b2a7f6d29b44cbc084b49042f44ef109da0cChandler Carruth  enum {
155cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth    value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value &&
156cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth             !is_same<UnderlyingT, float>::value &&
157cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth             !is_same<UnderlyingT, double>::value &&
158cbfc117674be7ff70b4682c525d6fcb4827a74edChandler Carruth             sizeof(char) != sizeof(check_int_convertible(nonce_instance)))
159d4d8b2a7f6d29b44cbc084b49042f44ef109da0cChandler Carruth  };
160d4d8b2a7f6d29b44cbc084b49042f44ef109da0cChandler Carruth};
161d4d8b2a7f6d29b44cbc084b49042f44ef109da0cChandler Carruth
162c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor// enable_if_c - Enable/disable a template based on a metafunction
163c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregortemplate<bool Cond, typename T = void>
164c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregorstruct enable_if_c {
165c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor  typedef T type;
166c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor};
167c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor
168c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregortemplate<typename T> struct enable_if_c<false, T> { };
169c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor
170c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor// enable_if - Enable/disable a template based on a metafunction
171c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregortemplate<typename Cond, typename T = void>
172c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregorstruct enable_if : public enable_if_c<Cond::value, T> { };
173c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor
174c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregornamespace dont_use {
175c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor  template<typename Base> char base_of_helper(const volatile Base*);
176c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor  template<typename Base> double base_of_helper(...);
177c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor}
178c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor
179c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor/// is_base_of - Metafunction to determine whether one type is a base class of
180c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor/// (or identical to) another type.
181c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregortemplate<typename Base, typename Derived>
182c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregorstruct is_base_of {
183c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor  static const bool value
184c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor    = is_class<Base>::value && is_class<Derived>::value &&
185c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor      sizeof(char) == sizeof(dont_use::base_of_helper<Base>((Derived*)0));
186c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor};
187c7a6da6e1469100937851cc3741a36b5850e54daDouglas Gregor
18871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin// remove_pointer - Metafunction to turn Foo* into Foo.  Defined in
18971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin// C++0x [meta.trans.ptr].
19071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate <typename T> struct remove_pointer { typedef T type; };
19171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate <typename T> struct remove_pointer<T*> { typedef T type; };
19271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate <typename T> struct remove_pointer<T*const> { typedef T type; };
19371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate <typename T> struct remove_pointer<T*volatile> { typedef T type; };
19471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate <typename T> struct remove_pointer<T*const volatile> {
19571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    typedef T type; };
19671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
19781cf4325698b48b02eddab921ac333c7f25005c3Jeffrey Yasskintemplate <bool, typename T, typename F>
19881cf4325698b48b02eddab921ac333c7f25005c3Jeffrey Yasskinstruct conditional { typedef T type; };
19981cf4325698b48b02eddab921ac333c7f25005c3Jeffrey Yasskin
20081cf4325698b48b02eddab921ac333c7f25005c3Jeffrey Yasskintemplate <typename T, typename F>
20181cf4325698b48b02eddab921ac333c7f25005c3Jeffrey Yasskinstruct conditional<false, T, F> { typedef F type; };
20281cf4325698b48b02eddab921ac333c7f25005c3Jeffrey Yasskin
2035c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner}
2045c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner
2055c4d53a4d1bce60051fd71af1791791acb2000daChris Lattner#endif
206