1 |
// Copyright (c) 2006, Google Inc. |
2 |
// All rights reserved. |
3 |
// |
4 |
// Redistribution and use in source and binary forms, with or without |
5 |
// modification, are permitted provided that the following conditions are |
6 |
// met: |
7 |
// |
8 |
// * Redistributions of source code must retain the above copyright |
9 |
// notice, this list of conditions and the following disclaimer. |
10 |
// * Redistributions in binary form must reproduce the above |
11 |
// copyright notice, this list of conditions and the following disclaimer |
12 |
// in the documentation and/or other materials provided with the |
13 |
// distribution. |
14 |
// * Neither the name of Google Inc. nor the names of its |
15 |
// contributors may be used to endorse or promote products derived from |
16 |
// this software without specific prior written permission. |
17 |
// |
18 |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 |
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 |
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 |
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 |
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 |
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 |
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 |
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 |
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 |
|
30 |
// ---- |
31 |
// Author: Matt Austern |
32 |
// |
33 |
// Define a small subset of tr1 type traits. The traits we define are: |
34 |
// is_integral |
35 |
// is_floating_point |
36 |
// is_pointer |
37 |
// is_reference |
38 |
// is_pod |
39 |
// has_trivial_constructor |
40 |
// has_trivial_copy |
41 |
// has_trivial_assign |
42 |
// has_trivial_destructor |
43 |
// remove_const |
44 |
// remove_volatile |
45 |
// remove_cv |
46 |
// remove_reference |
47 |
// remove_pointer |
48 |
// is_convertible |
49 |
// We can add more type traits as required. |
50 |
|
51 |
#ifndef BASE_TYPE_TRAITS_H_ |
52 |
#define BASE_TYPE_TRAITS_H_ |
53 |
|
54 |
#include <google/sparsehash/sparseconfig.h> |
55 |
#include <utility> // For pair |
56 |
|
57 |
_START_GOOGLE_NAMESPACE_ |
58 |
|
59 |
// integral_constant, defined in tr1, is a wrapper for an integer |
60 |
// value. We don't really need this generality; we could get away |
61 |
// with hardcoding the integer type to bool. We use the fully |
62 |
// general integer_constant for compatibility with tr1. |
63 |
|
64 |
template<class T, T v> |
65 |
struct integral_constant { |
66 |
static const T value = v; |
67 |
typedef T value_type; |
68 |
typedef integral_constant<T, v> type; |
69 |
}; |
70 |
|
71 |
template <class T, T v> const T integral_constant<T, v>::value; |
72 |
|
73 |
// Abbreviations: true_type and false_type are structs that represent |
74 |
// boolean true and false values. |
75 |
typedef integral_constant<bool, true> true_type; |
76 |
typedef integral_constant<bool, false> false_type; |
77 |
|
78 |
// Types small_ and big_ are guaranteed such that sizeof(small_) < |
79 |
// sizeof(big_) |
80 |
typedef char small_; |
81 |
|
82 |
struct big_ { |
83 |
char dummy[2]; |
84 |
}; |
85 |
|
86 |
// is_integral is false except for the built-in integer types. |
87 |
template <class T> struct is_integral : false_type { }; |
88 |
template<> struct is_integral<bool> : true_type { }; |
89 |
template<> struct is_integral<char> : true_type { }; |
90 |
template<> struct is_integral<unsigned char> : true_type { }; |
91 |
template<> struct is_integral<signed char> : true_type { }; |
92 |
#if defined(_MSC_VER) |
93 |
// wchar_t is not by default a distinct type from unsigned short in |
94 |
// Microsoft C. |
95 |
// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx |
96 |
template<> struct is_integral<__wchar_t> : true_type { }; |
97 |
#else |
98 |
template<> struct is_integral<wchar_t> : true_type { }; |
99 |
#endif |
100 |
template<> struct is_integral<short> : true_type { }; |
101 |
template<> struct is_integral<unsigned short> : true_type { }; |
102 |
template<> struct is_integral<int> : true_type { }; |
103 |
template<> struct is_integral<unsigned int> : true_type { }; |
104 |
template<> struct is_integral<long> : true_type { }; |
105 |
template<> struct is_integral<unsigned long> : true_type { }; |
106 |
#ifdef HAVE_LONG_LONG |
107 |
template<> struct is_integral<long long> : true_type { }; |
108 |
template<> struct is_integral<unsigned long long> : true_type { }; |
109 |
#endif |
110 |
|
111 |
|
112 |
// is_floating_point is false except for the built-in floating-point types. |
113 |
template <class T> struct is_floating_point : false_type { }; |
114 |
template<> struct is_floating_point<float> : true_type { }; |
115 |
template<> struct is_floating_point<double> : true_type { }; |
116 |
template<> struct is_floating_point<long double> : true_type { }; |
117 |
|
118 |
|
119 |
// is_pointer is false except for pointer types. |
120 |
template <class T> struct is_pointer : false_type { }; |
121 |
template <class T> struct is_pointer<T*> : true_type { }; |
122 |
|
123 |
|
124 |
// is_reference is false except for reference types. |
125 |
template<typename T> struct is_reference : false_type {}; |
126 |
template<typename T> struct is_reference<T&> : true_type {}; |
127 |
|
128 |
|
129 |
// We can't get is_pod right without compiler help, so fail conservatively. |
130 |
// We will assume it's false except for arithmetic types and pointers, |
131 |
// and const versions thereof. Note that std::pair is not a POD. |
132 |
template <class T> struct is_pod |
133 |
: integral_constant<bool, (is_integral<T>::value || |
134 |
is_floating_point<T>::value || |
135 |
is_pointer<T>::value)> { }; |
136 |
template <class T> struct is_pod<const T> : is_pod<T> { }; |
137 |
|
138 |
|
139 |
// We can't get has_trivial_constructor right without compiler help, so |
140 |
// fail conservatively. We will assume it's false except for: (1) types |
141 |
// for which is_pod is true. (2) std::pair of types with trivial |
142 |
// constructors. (3) array of a type with a trivial constructor. |
143 |
// (4) const versions thereof. |
144 |
template <class T> struct has_trivial_constructor : is_pod<T> { }; |
145 |
template <class T, class U> struct has_trivial_constructor<std::pair<T, U> > |
146 |
: integral_constant<bool, |
147 |
(has_trivial_constructor<T>::value && |
148 |
has_trivial_constructor<U>::value)> { }; |
149 |
template <class A, int N> struct has_trivial_constructor<A[N]> |
150 |
: has_trivial_constructor<A> { }; |
151 |
template <class T> struct has_trivial_constructor<const T> |
152 |
: has_trivial_constructor<T> { }; |
153 |
|
154 |
// We can't get has_trivial_copy right without compiler help, so fail |
155 |
// conservatively. We will assume it's false except for: (1) types |
156 |
// for which is_pod is true. (2) std::pair of types with trivial copy |
157 |
// constructors. (3) array of a type with a trivial copy constructor. |
158 |
// (4) const versions thereof. |
159 |
template <class T> struct has_trivial_copy : is_pod<T> { }; |
160 |
template <class T, class U> struct has_trivial_copy<std::pair<T, U> > |
161 |
: integral_constant<bool, |
162 |
(has_trivial_copy<T>::value && |
163 |
has_trivial_copy<U>::value)> { }; |
164 |
template <class A, int N> struct has_trivial_copy<A[N]> |
165 |
: has_trivial_copy<A> { }; |
166 |
template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { }; |
167 |
|
168 |
// We can't get has_trivial_assign right without compiler help, so fail |
169 |
// conservatively. We will assume it's false except for: (1) types |
170 |
// for which is_pod is true. (2) std::pair of types with trivial copy |
171 |
// constructors. (3) array of a type with a trivial assign constructor. |
172 |
template <class T> struct has_trivial_assign : is_pod<T> { }; |
173 |
template <class T, class U> struct has_trivial_assign<std::pair<T, U> > |
174 |
: integral_constant<bool, |
175 |
(has_trivial_assign<T>::value && |
176 |
has_trivial_assign<U>::value)> { }; |
177 |
template <class A, int N> struct has_trivial_assign<A[N]> |
178 |
: has_trivial_assign<A> { }; |
179 |
|
180 |
// We can't get has_trivial_destructor right without compiler help, so |
181 |
// fail conservatively. We will assume it's false except for: (1) types |
182 |
// for which is_pod is true. (2) std::pair of types with trivial |
183 |
// destructors. (3) array of a type with a trivial destructor. |
184 |
// (4) const versions thereof. |
185 |
template <class T> struct has_trivial_destructor : is_pod<T> { }; |
186 |
template <class T, class U> struct has_trivial_destructor<std::pair<T, U> > |
187 |
: integral_constant<bool, |
188 |
(has_trivial_destructor<T>::value && |
189 |
has_trivial_destructor<U>::value)> { }; |
190 |
template <class A, int N> struct has_trivial_destructor<A[N]> |
191 |
: has_trivial_destructor<A> { }; |
192 |
template <class T> struct has_trivial_destructor<const T> |
193 |
: has_trivial_destructor<T> { }; |
194 |
|
195 |
// Specified by TR1 [4.7.1] |
196 |
template<typename T> struct remove_const { typedef T type; }; |
197 |
template<typename T> struct remove_const<T const> { typedef T type; }; |
198 |
template<typename T> struct remove_volatile { typedef T type; }; |
199 |
template<typename T> struct remove_volatile<T volatile> { typedef T type; }; |
200 |
template<typename T> struct remove_cv { |
201 |
typedef typename remove_const<typename remove_volatile<T>::type>::type type; |
202 |
}; |
203 |
|
204 |
|
205 |
// Specified by TR1 [4.7.2] |
206 |
template<typename T> struct remove_reference { typedef T type; }; |
207 |
template<typename T> struct remove_reference<T&> { typedef T type; }; |
208 |
|
209 |
// Specified by TR1 [4.7.4] Pointer modifications. |
210 |
template<typename T> struct remove_pointer { typedef T type; }; |
211 |
template<typename T> struct remove_pointer<T*> { typedef T type; }; |
212 |
template<typename T> struct remove_pointer<T* const> { typedef T type; }; |
213 |
template<typename T> struct remove_pointer<T* volatile> { typedef T type; }; |
214 |
template<typename T> struct remove_pointer<T* const volatile> { |
215 |
typedef T type; }; |
216 |
|
217 |
// Specified by TR1 [4.6] Relationships between types |
218 |
#ifndef _MSC_VER |
219 |
namespace internal { |
220 |
|
221 |
// This class is an implementation detail for is_convertible, and you |
222 |
// don't need to know how it works to use is_convertible. For those |
223 |
// who care: we declare two different functions, one whose argument is |
224 |
// of type To and one with a variadic argument list. We give them |
225 |
// return types of different size, so we can use sizeof to trick the |
226 |
// compiler into telling us which function it would have chosen if we |
227 |
// had called it with an argument of type From. See Alexandrescu's |
228 |
// _Modern C++ Design_ for more details on this sort of trick. |
229 |
|
230 |
template <typename From, typename To> |
231 |
struct ConvertHelper { |
232 |
static small_ Test(To); |
233 |
static big_ Test(...); |
234 |
static From Create(); |
235 |
}; |
236 |
} // namespace internal |
237 |
|
238 |
// Inherits from true_type if From is convertible to To, false_type otherwise. |
239 |
template <typename From, typename To> |
240 |
struct is_convertible |
241 |
: integral_constant<bool, |
242 |
sizeof(internal::ConvertHelper<From, To>::Test( |
243 |
internal::ConvertHelper<From, To>::Create())) |
244 |
== sizeof(small_)> { |
245 |
}; |
246 |
#endif |
247 |
|
248 |
_END_GOOGLE_NAMESPACE_ |
249 |
|
250 |
#endif // BASE_TYPE_TRAITS_H_ |