1// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This code is compiled directly on many platforms, including client
6// platforms like Windows, Mac, and embedded systems.  Before making
7// any changes here, make sure that you're not breaking any platforms.
8//
9//
10// Define a small subset of tr1 type traits. The traits we define are:
11//   is_integral
12//   is_floating_point
13//   is_pointer
14//   is_reference
15//   is_pod
16//   has_trivial_constructor
17//   has_trivial_copy
18//   has_trivial_assign
19//   has_trivial_destructor
20//   remove_const
21//   remove_volatile
22//   remove_cv
23//   remove_reference
24//   remove_pointer
25//   is_convertible
26// We can add more type traits as required.
27
28#ifndef BASE_TYPE_TRAITS_H_
29#define BASE_TYPE_TRAITS_H_
30
31#include "base/template_util.h"     // For true_type and false_type
32#include <utility>                  // For pair
33
34namespace base {
35
36// is_integral is false except for the built-in integer types.
37template <class T> struct is_integral : false_type { };
38template<> struct is_integral<bool> : true_type { };
39template<> struct is_integral<char> : true_type { };
40template<> struct is_integral<unsigned char> : true_type { };
41template<> struct is_integral<signed char> : true_type { };
42#if defined(_MSC_VER)
43// wchar_t is not by default a distinct type from unsigned short in
44// Microsoft C.
45// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
46template<> struct is_integral<__wchar_t> : true_type { };
47#else
48template<> struct is_integral<wchar_t> : true_type { };
49#endif
50template<> struct is_integral<short> : true_type { };
51template<> struct is_integral<unsigned short> : true_type { };
52template<> struct is_integral<int> : true_type { };
53template<> struct is_integral<unsigned int> : true_type { };
54template<> struct is_integral<long> : true_type { };
55template<> struct is_integral<unsigned long> : true_type { };
56template<> struct is_integral<long long> : true_type { };
57template<> struct is_integral<unsigned long long> : true_type { };
58
59
60// is_floating_point is false except for the built-in floating-point types.
61template <class T> struct is_floating_point : false_type { };
62template<> struct is_floating_point<float> : true_type { };
63template<> struct is_floating_point<double> : true_type { };
64template<> struct is_floating_point<long double> : true_type { };
65
66
67// is_pointer is false except for pointer types.
68template <class T> struct is_pointer : false_type { };
69template <class T> struct is_pointer<T*> : true_type { };
70
71
72// is_reference is false except for reference types.
73template<typename T> struct is_reference : false_type {};
74template<typename T> struct is_reference<T&> : true_type {};
75
76
77// We can't get is_pod right without compiler help, so fail conservatively.
78// We will assume it's false except for arithmetic types and pointers,
79// and const versions thereof. Note that std::pair is not a POD.
80template <class T> struct is_pod
81 : integral_constant<bool, (is_integral<T>::value ||
82                            is_floating_point<T>::value ||
83                            is_pointer<T>::value)> { };
84template <class T> struct is_pod<const T> : is_pod<T> { };
85
86
87// We can't get has_trivial_constructor right without compiler help, so
88// fail conservatively. We will assume it's false except for: (1) types
89// for which is_pod is true. (2) std::pair of types with trivial
90// constructors. (3) array of a type with a trivial constructor.
91// (4) const versions thereof.
92template <class T> struct has_trivial_constructor : is_pod<T> { };
93template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
94  : integral_constant<bool,
95                      (has_trivial_constructor<T>::value &&
96                       has_trivial_constructor<U>::value)> { };
97template <class A, int N> struct has_trivial_constructor<A[N]>
98  : has_trivial_constructor<A> { };
99template <class T> struct has_trivial_constructor<const T>
100  : has_trivial_constructor<T> { };
101
102// We can't get has_trivial_copy right without compiler help, so fail
103// conservatively. We will assume it's false except for: (1) types
104// for which is_pod is true. (2) std::pair of types with trivial copy
105// constructors. (3) array of a type with a trivial copy constructor.
106// (4) const versions thereof.
107template <class T> struct has_trivial_copy : is_pod<T> { };
108template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
109  : integral_constant<bool,
110                      (has_trivial_copy<T>::value &&
111                       has_trivial_copy<U>::value)> { };
112template <class A, int N> struct has_trivial_copy<A[N]>
113  : has_trivial_copy<A> { };
114template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
115
116// We can't get has_trivial_assign right without compiler help, so fail
117// conservatively. We will assume it's false except for: (1) types
118// for which is_pod is true. (2) std::pair of types with trivial copy
119// constructors. (3) array of a type with a trivial assign constructor.
120template <class T> struct has_trivial_assign : is_pod<T> { };
121template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
122  : integral_constant<bool,
123                      (has_trivial_assign<T>::value &&
124                       has_trivial_assign<U>::value)> { };
125template <class A, int N> struct has_trivial_assign<A[N]>
126  : has_trivial_assign<A> { };
127
128// We can't get has_trivial_destructor right without compiler help, so
129// fail conservatively. We will assume it's false except for: (1) types
130// for which is_pod is true. (2) std::pair of types with trivial
131// destructors. (3) array of a type with a trivial destructor.
132// (4) const versions thereof.
133template <class T> struct has_trivial_destructor : is_pod<T> { };
134template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
135  : integral_constant<bool,
136                      (has_trivial_destructor<T>::value &&
137                       has_trivial_destructor<U>::value)> { };
138template <class A, int N> struct has_trivial_destructor<A[N]>
139  : has_trivial_destructor<A> { };
140template <class T> struct has_trivial_destructor<const T>
141  : has_trivial_destructor<T> { };
142
143// Specified by TR1 [4.7.1]
144template<typename T> struct remove_const { typedef T type; };
145template<typename T> struct remove_const<T const> { typedef T type; };
146template<typename T> struct remove_volatile { typedef T type; };
147template<typename T> struct remove_volatile<T volatile> { typedef T type; };
148template<typename T> struct remove_cv {
149  typedef typename remove_const<typename remove_volatile<T>::type>::type type;
150};
151
152
153// Specified by TR1 [4.7.2]
154template<typename T> struct remove_reference { typedef T type; };
155template<typename T> struct remove_reference<T&> { typedef T type; };
156
157// Specified by TR1 [4.7.4] Pointer modifications.
158template<typename T> struct remove_pointer { typedef T type; };
159template<typename T> struct remove_pointer<T*> { typedef T type; };
160template<typename T> struct remove_pointer<T* const> { typedef T type; };
161template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
162template<typename T> struct remove_pointer<T* const volatile> {
163  typedef T type; };
164
165// Specified by TR1 [4.6] Relationships between types
166#ifndef _MSC_VER
167namespace internal {
168
169// This class is an implementation detail for is_convertible, and you
170// don't need to know how it works to use is_convertible. For those
171// who care: we declare two different functions, one whose argument is
172// of type To and one with a variadic argument list. We give them
173// return types of different size, so we can use sizeof to trick the
174// compiler into telling us which function it would have chosen if we
175// had called it with an argument of type From.  See Alexandrescu's
176// _Modern C++ Design_ for more details on this sort of trick.
177
178template <typename From, typename To>
179struct ConvertHelper {
180  static small_ Test(To);
181  static big_ Test(...);
182  static From Create();
183};
184}  // namespace internal
185
186// Inherits from true_type if From is convertible to To, false_type otherwise.
187template <typename From, typename To>
188struct is_convertible
189    : integral_constant<bool,
190                        sizeof(internal::ConvertHelper<From, To>::Test(
191                                  internal::ConvertHelper<From, To>::Create()))
192                        == sizeof(small_)> {
193};
194#endif
195
196} // Close namespace base
197
198#endif  // BASE_TYPE_TRAITS_H_
199