]>
Commit | Line | Data |
---|---|---|
5b9daa7e | 1 | // C++0x type_traits -*- C++ -*- |
af13a7a6 | 2 | |
ab65a4c7 | 3 | // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
af13a7a6 BK |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
af13a7a6 BK |
9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
af13a7a6 BK |
24 | |
25 | /** @file include/type_traits | |
26 | * This is a Standard C++ Library header. | |
27 | */ | |
28 | ||
4514bed6 BK |
29 | #ifndef _GLIBCXX_TYPE_TRAITS |
30 | #define _GLIBCXX_TYPE_TRAITS 1 | |
af13a7a6 BK |
31 | |
32 | #pragma GCC system_header | |
33 | ||
57317d2a | 34 | #ifndef __GXX_EXPERIMENTAL_CXX0X__ |
ab65a4c7 | 35 | # include <bits/c++0x_warning.h> |
57317d2a | 36 | #else |
af13a7a6 | 37 | |
e133ace8 PC |
38 | #if defined(_GLIBCXX_INCLUDE_AS_TR1) |
39 | # error C++0x header cannot be included from TR1 header | |
40 | #endif | |
41 | ||
42 | #include <cstddef> | |
43 | ||
44 | #if defined(_GLIBCXX_INCLUDE_AS_CXX0X) | |
45 | # include <tr1_impl/type_traits> | |
46 | #else | |
47 | # define _GLIBCXX_INCLUDE_AS_CXX0X | |
48 | # define _GLIBCXX_BEGIN_NAMESPACE_TR1 | |
49 | # define _GLIBCXX_END_NAMESPACE_TR1 | |
50 | # define _GLIBCXX_TR1 | |
51 | # include <tr1_impl/type_traits> | |
52 | # undef _GLIBCXX_TR1 | |
53 | # undef _GLIBCXX_END_NAMESPACE_TR1 | |
54 | # undef _GLIBCXX_BEGIN_NAMESPACE_TR1 | |
55 | # undef _GLIBCXX_INCLUDE_AS_CXX0X | |
56 | #endif | |
57 | ||
58 | namespace std | |
59 | { | |
8e32aa11 BK |
60 | /** |
61 | * @addtogroup metaprogramming | |
5b9daa7e BK |
62 | * @{ |
63 | */ | |
64 | ||
4a27a739 | 65 | // Primary classification traits. |
939759fc BK |
66 | |
67 | /// is_lvalue_reference | |
4a27a739 PC |
68 | template<typename> |
69 | struct is_lvalue_reference | |
70 | : public false_type { }; | |
71 | ||
72 | template<typename _Tp> | |
73 | struct is_lvalue_reference<_Tp&> | |
74 | : public true_type { }; | |
75 | ||
939759fc | 76 | /// is_rvalue_reference |
4a27a739 PC |
77 | template<typename> |
78 | struct is_rvalue_reference | |
79 | : public false_type { }; | |
80 | ||
81 | template<typename _Tp> | |
82 | struct is_rvalue_reference<_Tp&&> | |
83 | : public true_type { }; | |
84 | ||
85 | // Secondary classification traits. | |
939759fc BK |
86 | |
87 | /// is_reference | |
4a27a739 PC |
88 | template<typename _Tp> |
89 | struct is_reference | |
90 | : public integral_constant<bool, (is_lvalue_reference<_Tp>::value | |
91 | || is_rvalue_reference<_Tp>::value)> | |
92 | { }; | |
93 | ||
94 | // Reference transformations. | |
939759fc BK |
95 | |
96 | /// remove_reference | |
4a27a739 PC |
97 | template<typename _Tp> |
98 | struct remove_reference | |
99 | { typedef _Tp type; }; | |
100 | ||
101 | template<typename _Tp> | |
102 | struct remove_reference<_Tp&> | |
103 | { typedef _Tp type; }; | |
104 | ||
105 | template<typename _Tp> | |
106 | struct remove_reference<_Tp&&> | |
107 | { typedef _Tp type; }; | |
108 | ||
109 | template<typename _Tp, | |
58366b08 | 110 | bool = !is_reference<_Tp>::value && !is_void<_Tp>::value, |
4a27a739 PC |
111 | bool = is_rvalue_reference<_Tp>::value> |
112 | struct __add_lvalue_reference_helper | |
113 | { typedef _Tp type; }; | |
114 | ||
115 | template<typename _Tp> | |
116 | struct __add_lvalue_reference_helper<_Tp, true, false> | |
117 | { typedef _Tp& type; }; | |
118 | ||
119 | template<typename _Tp> | |
120 | struct __add_lvalue_reference_helper<_Tp, false, true> | |
121 | { typedef typename remove_reference<_Tp>::type& type; }; | |
122 | ||
939759fc | 123 | /// add_lvalue_reference |
4a27a739 PC |
124 | template<typename _Tp> |
125 | struct add_lvalue_reference | |
126 | : public __add_lvalue_reference_helper<_Tp> | |
127 | { }; | |
128 | ||
129 | template<typename _Tp, | |
58366b08 | 130 | bool = !is_reference<_Tp>::value && !is_void<_Tp>::value> |
4a27a739 PC |
131 | struct __add_rvalue_reference_helper |
132 | { typedef _Tp type; }; | |
133 | ||
134 | template<typename _Tp> | |
135 | struct __add_rvalue_reference_helper<_Tp, true> | |
136 | { typedef _Tp&& type; }; | |
137 | ||
939759fc | 138 | /// add_rvalue_reference |
4a27a739 PC |
139 | template<typename _Tp> |
140 | struct add_rvalue_reference | |
141 | : public __add_rvalue_reference_helper<_Tp> | |
142 | { }; | |
143 | ||
144 | // Scalar properties and transformations. | |
939759fc | 145 | |
e133ace8 PC |
146 | template<typename _Tp, |
147 | bool = is_integral<_Tp>::value, | |
148 | bool = is_floating_point<_Tp>::value> | |
149 | struct __is_signed_helper | |
150 | : public false_type { }; | |
151 | ||
152 | template<typename _Tp> | |
153 | struct __is_signed_helper<_Tp, false, true> | |
154 | : public true_type { }; | |
155 | ||
156 | template<typename _Tp> | |
157 | struct __is_signed_helper<_Tp, true, false> | |
8e32aa11 | 158 | : public integral_constant<bool, static_cast<bool>(_Tp(-1) < _Tp(0))> |
e133ace8 PC |
159 | { }; |
160 | ||
939759fc | 161 | /// is_signed |
e133ace8 PC |
162 | template<typename _Tp> |
163 | struct is_signed | |
164 | : public integral_constant<bool, __is_signed_helper<_Tp>::value> | |
165 | { }; | |
166 | ||
939759fc | 167 | /// is_unsigned |
e133ace8 PC |
168 | template<typename _Tp> |
169 | struct is_unsigned | |
170 | : public integral_constant<bool, (is_arithmetic<_Tp>::value | |
171 | && !is_signed<_Tp>::value)> | |
172 | { }; | |
173 | ||
4a27a739 | 174 | // Member introspection. |
939759fc | 175 | |
b0302c68 PC |
176 | /// is_trivial |
177 | template<typename _Tp> | |
178 | struct is_trivial | |
179 | : public integral_constant<bool, __is_trivial(_Tp)> | |
180 | { }; | |
181 | ||
182 | /// is_standard_layout | |
183 | template<typename _Tp> | |
184 | struct is_standard_layout | |
185 | : public integral_constant<bool, __is_standard_layout(_Tp)> | |
186 | { }; | |
187 | ||
939759fc | 188 | /// is_pod |
c32097d8 | 189 | // Could use is_standard_layout && is_trivial instead of the builtin. |
e133ace8 PC |
190 | template<typename _Tp> |
191 | struct is_pod | |
192 | : public integral_constant<bool, __is_pod(_Tp)> | |
193 | { }; | |
194 | ||
c32097d8 | 195 | template<typename _Tp> |
b0302c68 PC |
196 | typename add_rvalue_reference<_Tp>::type declval(); |
197 | ||
198 | template<typename _Tp, typename... _Args> | |
199 | class __is_constructible_helper | |
200 | : public __sfinae_types | |
201 | { | |
4b3d7a7e PC |
202 | template<typename _Tp1, typename... _Args1> |
203 | static decltype(_Tp1(declval<_Args1>()...), __one()) __test(int); | |
b0302c68 PC |
204 | |
205 | template<typename, typename...> | |
206 | static __two __test(...); | |
207 | ||
208 | public: | |
209 | static const bool __value = sizeof(__test<_Tp, _Args...>(0)) == 1; | |
210 | }; | |
211 | ||
212 | template<typename _Tp, typename _Arg> | |
213 | class __is_constructible_helper<_Tp, _Arg> | |
214 | : public __sfinae_types | |
215 | { | |
216 | template<typename _Tp1, typename _Arg1> | |
217 | static decltype(static_cast<_Tp1>(declval<_Arg1>()), __one()) | |
218 | __test(int); | |
219 | ||
220 | template<typename, typename> | |
221 | static __two __test(...); | |
222 | ||
223 | public: | |
224 | static const bool __value = sizeof(__test<_Tp, _Arg>(0)) == 1; | |
225 | }; | |
226 | ||
227 | /// is_constructible | |
228 | // XXX FIXME | |
229 | // The C++0x specifications require front-end support, see N2255. | |
230 | template<typename _Tp, typename... _Args> | |
231 | struct is_constructible | |
232 | : public integral_constant<bool, | |
233 | __is_constructible_helper<_Tp, | |
234 | _Args...>::__value> | |
c32097d8 JM |
235 | { }; |
236 | ||
939759fc | 237 | /// has_trivial_default_constructor |
e133ace8 PC |
238 | template<typename _Tp> |
239 | struct has_trivial_default_constructor | |
240 | : public integral_constant<bool, __has_trivial_constructor(_Tp)> | |
241 | { }; | |
242 | ||
939759fc | 243 | /// has_trivial_copy_constructor |
e133ace8 PC |
244 | template<typename _Tp> |
245 | struct has_trivial_copy_constructor | |
246 | : public integral_constant<bool, __has_trivial_copy(_Tp)> | |
247 | { }; | |
248 | ||
939759fc | 249 | /// has_trivial_assign |
e133ace8 PC |
250 | template<typename _Tp> |
251 | struct has_trivial_assign | |
252 | : public integral_constant<bool, __has_trivial_assign(_Tp)> | |
253 | { }; | |
254 | ||
939759fc | 255 | /// has_trivial_destructor |
e133ace8 PC |
256 | template<typename _Tp> |
257 | struct has_trivial_destructor | |
258 | : public integral_constant<bool, __has_trivial_destructor(_Tp)> | |
259 | { }; | |
260 | ||
a7543cfd | 261 | /// has_nothrow_default_constructor |
e133ace8 PC |
262 | template<typename _Tp> |
263 | struct has_nothrow_default_constructor | |
264 | : public integral_constant<bool, __has_nothrow_constructor(_Tp)> | |
265 | { }; | |
266 | ||
a7543cfd | 267 | /// has_nothrow_copy_constructor |
e133ace8 PC |
268 | template<typename _Tp> |
269 | struct has_nothrow_copy_constructor | |
270 | : public integral_constant<bool, __has_nothrow_copy(_Tp)> | |
271 | { }; | |
272 | ||
939759fc | 273 | /// has_nothrow_assign |
e133ace8 PC |
274 | template<typename _Tp> |
275 | struct has_nothrow_assign | |
276 | : public integral_constant<bool, __has_nothrow_assign(_Tp)> | |
277 | { }; | |
278 | ||
b0302c68 PC |
279 | // Relationships between types. |
280 | ||
939759fc | 281 | /// is_base_of |
e133ace8 PC |
282 | template<typename _Base, typename _Derived> |
283 | struct is_base_of | |
284 | : public integral_constant<bool, __is_base_of(_Base, _Derived)> | |
285 | { }; | |
286 | ||
297f34d7 PC |
287 | template<typename _From, typename _To, |
288 | bool = (is_void<_From>::value || is_void<_To>::value | |
289 | || is_function<_To>::value || is_array<_To>::value)> | |
290 | struct __is_convertible_helper | |
291 | { static const bool __value = (is_void<_From>::value | |
292 | && is_void<_To>::value); }; | |
293 | ||
e133ace8 | 294 | template<typename _From, typename _To> |
b0302c68 | 295 | class __is_convertible_helper<_From, _To, false> |
e133ace8 PC |
296 | : public __sfinae_types |
297 | { | |
e133ace8 PC |
298 | static __one __test(_To); |
299 | static __two __test(...); | |
297f34d7 | 300 | |
e133ace8 | 301 | public: |
7274deff | 302 | static const bool __value = sizeof(__test(declval<_From>())) == 1; |
e133ace8 PC |
303 | }; |
304 | ||
b0302c68 | 305 | /// is_convertible |
4a27a739 | 306 | // XXX FIXME |
2d0269f6 | 307 | // The C++0x specifications require front-end support, see N2255. |
e133ace8 PC |
308 | template<typename _From, typename _To> |
309 | struct is_convertible | |
310 | : public integral_constant<bool, | |
311 | __is_convertible_helper<_From, _To>::__value> | |
312 | { }; | |
313 | ||
b0302c68 | 314 | /// is_explicitly_convertible |
75995f37 PC |
315 | template<typename _From, typename _To> |
316 | struct is_explicitly_convertible | |
317 | : public is_constructible<_To, _From> | |
318 | { }; | |
319 | ||
fd735b6a PC |
320 | template<std::size_t _Len> |
321 | struct __aligned_storage_msa | |
322 | { | |
323 | union __type | |
324 | { | |
325 | unsigned char __data[_Len]; | |
326 | struct __attribute__((__aligned__)) { } __align; | |
327 | }; | |
328 | }; | |
329 | ||
939759fc BK |
330 | /** |
331 | * @brief Alignment type. | |
332 | * | |
333 | * The value of _Align is a default-alignment which shall be the | |
334 | * most stringent alignment requirement for any C++ object type | |
335 | * whose size is no greater than _Len (3.9). The member typedef | |
336 | * type shall be a POD type suitable for use as uninitialized | |
337 | * storage for any object whose size is at most _Len and whose | |
338 | * alignment is a divisor of _Align. | |
339 | */ | |
fd735b6a PC |
340 | template<std::size_t _Len, std::size_t _Align = |
341 | __alignof__(typename __aligned_storage_msa<_Len>::__type)> | |
342 | struct aligned_storage | |
343 | { | |
344 | union type | |
345 | { | |
346 | unsigned char __data[_Len]; | |
347 | struct __attribute__((__aligned__((_Align)))) { } __align; | |
348 | }; | |
349 | }; | |
350 | ||
7b50cdef BK |
351 | |
352 | // Define a nested type if some predicate holds. | |
5b9daa7e BK |
353 | // Primary template. |
354 | /// enable_if | |
7b50cdef BK |
355 | template<bool, typename _Tp = void> |
356 | struct enable_if | |
357 | { }; | |
358 | ||
5b9daa7e | 359 | // Partial specialization for true. |
7b50cdef BK |
360 | template<typename _Tp> |
361 | struct enable_if<true, _Tp> | |
362 | { typedef _Tp type; }; | |
363 | ||
364 | ||
5b9daa7e BK |
365 | // A conditional expression, but for types. If true, first, if false, second. |
366 | // Primary template. | |
367 | /// conditional | |
7b50cdef BK |
368 | template<bool _Cond, typename _Iftrue, typename _Iffalse> |
369 | struct conditional | |
370 | { typedef _Iftrue type; }; | |
371 | ||
5b9daa7e | 372 | // Partial specialization for false. |
7b50cdef BK |
373 | template<typename _Iftrue, typename _Iffalse> |
374 | struct conditional<false, _Iftrue, _Iffalse> | |
375 | { typedef _Iffalse type; }; | |
376 | ||
377 | ||
378 | // Decay trait for arrays and functions, used for perfect forwarding | |
379 | // in make_pair, make_tuple, etc. | |
380 | template<typename _Up, | |
381 | bool _IsArray = is_array<_Up>::value, | |
382 | bool _IsFunction = is_function<_Up>::value> | |
383 | struct __decay_selector; | |
384 | ||
ce796131 | 385 | // NB: DR 705. |
7b50cdef BK |
386 | template<typename _Up> |
387 | struct __decay_selector<_Up, false, false> | |
ce796131 | 388 | { typedef typename remove_cv<_Up>::type __type; }; |
7b50cdef BK |
389 | |
390 | template<typename _Up> | |
391 | struct __decay_selector<_Up, true, false> | |
392 | { typedef typename remove_extent<_Up>::type* __type; }; | |
393 | ||
7b50cdef BK |
394 | template<typename _Up> |
395 | struct __decay_selector<_Up, false, true> | |
396 | { typedef typename add_pointer<_Up>::type __type; }; | |
397 | ||
939759fc | 398 | /// decay |
7b50cdef | 399 | template<typename _Tp> |
b0302c68 | 400 | class decay |
7b50cdef | 401 | { |
7b50cdef BK |
402 | typedef typename remove_reference<_Tp>::type __remove_type; |
403 | ||
404 | public: | |
405 | typedef typename __decay_selector<__remove_type>::__type type; | |
406 | }; | |
407 | ||
5e108459 PC |
408 | template<typename _Tp> |
409 | class reference_wrapper; | |
410 | ||
411 | // Helper which adds a reference to a type when given a reference_wrapper | |
412 | template<typename _Tp> | |
413 | struct __strip_reference_wrapper | |
414 | { | |
415 | typedef _Tp __type; | |
416 | }; | |
417 | ||
418 | template<typename _Tp> | |
419 | struct __strip_reference_wrapper<reference_wrapper<_Tp> > | |
420 | { | |
421 | typedef _Tp& __type; | |
422 | }; | |
423 | ||
424 | template<typename _Tp> | |
425 | struct __strip_reference_wrapper<const reference_wrapper<_Tp> > | |
426 | { | |
427 | typedef _Tp& __type; | |
428 | }; | |
429 | ||
430 | template<typename _Tp> | |
431 | struct __decay_and_strip | |
432 | { | |
433 | typedef typename __strip_reference_wrapper< | |
434 | typename decay<_Tp>::type>::__type __type; | |
435 | }; | |
436 | ||
7b50cdef BK |
437 | |
438 | // Utility for constructing identically cv-qualified types. | |
439 | template<typename _Unqualified, bool _IsConst, bool _IsVol> | |
440 | struct __cv_selector; | |
441 | ||
442 | template<typename _Unqualified> | |
443 | struct __cv_selector<_Unqualified, false, false> | |
444 | { typedef _Unqualified __type; }; | |
445 | ||
446 | template<typename _Unqualified> | |
447 | struct __cv_selector<_Unqualified, false, true> | |
448 | { typedef volatile _Unqualified __type; }; | |
449 | ||
450 | template<typename _Unqualified> | |
451 | struct __cv_selector<_Unqualified, true, false> | |
452 | { typedef const _Unqualified __type; }; | |
453 | ||
454 | template<typename _Unqualified> | |
455 | struct __cv_selector<_Unqualified, true, true> | |
456 | { typedef const volatile _Unqualified __type; }; | |
457 | ||
458 | template<typename _Qualified, typename _Unqualified, | |
459 | bool _IsConst = is_const<_Qualified>::value, | |
460 | bool _IsVol = is_volatile<_Qualified>::value> | |
b0302c68 | 461 | class __match_cv_qualifiers |
7b50cdef | 462 | { |
7b50cdef BK |
463 | typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match; |
464 | ||
465 | public: | |
466 | typedef typename __match::__type __type; | |
467 | }; | |
468 | ||
469 | ||
470 | // Utility for finding the unsigned versions of signed integral types. | |
471 | template<typename _Tp> | |
e133ace8 PC |
472 | struct __make_unsigned |
473 | { typedef _Tp __type; }; | |
7b50cdef BK |
474 | |
475 | template<> | |
476 | struct __make_unsigned<char> | |
477 | { typedef unsigned char __type; }; | |
478 | ||
479 | template<> | |
480 | struct __make_unsigned<signed char> | |
481 | { typedef unsigned char __type; }; | |
482 | ||
7b50cdef BK |
483 | template<> |
484 | struct __make_unsigned<short> | |
485 | { typedef unsigned short __type; }; | |
486 | ||
487 | template<> | |
488 | struct __make_unsigned<int> | |
489 | { typedef unsigned int __type; }; | |
490 | ||
491 | template<> | |
492 | struct __make_unsigned<long> | |
493 | { typedef unsigned long __type; }; | |
494 | ||
495 | template<> | |
496 | struct __make_unsigned<long long> | |
497 | { typedef unsigned long long __type; }; | |
498 | ||
499 | ||
500 | // Select between integral and enum: not possible to be both. | |
501 | template<typename _Tp, | |
502 | bool _IsInt = is_integral<_Tp>::value, | |
7b50cdef | 503 | bool _IsEnum = is_enum<_Tp>::value> |
b0302c68 PC |
504 | class __make_unsigned_selector; |
505 | ||
7b50cdef | 506 | template<typename _Tp> |
b0302c68 | 507 | class __make_unsigned_selector<_Tp, true, false> |
7b50cdef | 508 | { |
7b50cdef BK |
509 | typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt; |
510 | typedef typename __unsignedt::__type __unsigned_type; | |
511 | typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned; | |
512 | ||
513 | public: | |
514 | typedef typename __cv_unsigned::__type __type; | |
515 | }; | |
516 | ||
7b50cdef | 517 | template<typename _Tp> |
b0302c68 | 518 | class __make_unsigned_selector<_Tp, false, true> |
7b50cdef | 519 | { |
a0230468 MM |
520 | // With -fshort-enums, an enum may be as small as a char. |
521 | typedef unsigned char __smallest; | |
522 | static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); | |
523 | static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short); | |
ce2e6349 | 524 | static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int); |
a0230468 MM |
525 | typedef conditional<__b2, unsigned int, unsigned long> __cond2; |
526 | typedef typename __cond2::type __cond2_type; | |
527 | typedef conditional<__b1, unsigned short, __cond2_type> __cond1; | |
528 | typedef typename __cond1::type __cond1_type; | |
7b50cdef BK |
529 | |
530 | public: | |
a0230468 | 531 | typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; |
7b50cdef BK |
532 | }; |
533 | ||
7b50cdef BK |
534 | // Given an integral/enum type, return the corresponding unsigned |
535 | // integer type. | |
5b9daa7e BK |
536 | // Primary template. |
537 | /// make_unsigned | |
7b50cdef BK |
538 | template<typename _Tp> |
539 | struct make_unsigned | |
540 | { typedef typename __make_unsigned_selector<_Tp>::__type type; }; | |
541 | ||
542 | // Integral, but don't define. | |
543 | template<> | |
544 | struct make_unsigned<bool>; | |
545 | ||
546 | ||
547 | // Utility for finding the signed versions of unsigned integral types. | |
548 | template<typename _Tp> | |
e133ace8 PC |
549 | struct __make_signed |
550 | { typedef _Tp __type; }; | |
7b50cdef BK |
551 | |
552 | template<> | |
553 | struct __make_signed<char> | |
554 | { typedef signed char __type; }; | |
555 | ||
556 | template<> | |
557 | struct __make_signed<unsigned char> | |
558 | { typedef signed char __type; }; | |
559 | ||
7b50cdef BK |
560 | template<> |
561 | struct __make_signed<unsigned short> | |
562 | { typedef signed short __type; }; | |
563 | ||
564 | template<> | |
565 | struct __make_signed<unsigned int> | |
566 | { typedef signed int __type; }; | |
567 | ||
568 | template<> | |
569 | struct __make_signed<unsigned long> | |
570 | { typedef signed long __type; }; | |
571 | ||
572 | template<> | |
573 | struct __make_signed<unsigned long long> | |
574 | { typedef signed long long __type; }; | |
575 | ||
576 | ||
fb8ffd10 | 577 | // Select between integral and enum: not possible to be both. |
7b50cdef BK |
578 | template<typename _Tp, |
579 | bool _IsInt = is_integral<_Tp>::value, | |
7b50cdef | 580 | bool _IsEnum = is_enum<_Tp>::value> |
b0302c68 PC |
581 | class __make_signed_selector; |
582 | ||
7b50cdef | 583 | template<typename _Tp> |
b0302c68 | 584 | class __make_signed_selector<_Tp, true, false> |
7b50cdef | 585 | { |
7b50cdef BK |
586 | typedef __make_signed<typename remove_cv<_Tp>::type> __signedt; |
587 | typedef typename __signedt::__type __signed_type; | |
588 | typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed; | |
589 | ||
590 | public: | |
591 | typedef typename __cv_signed::__type __type; | |
592 | }; | |
593 | ||
7b50cdef | 594 | template<typename _Tp> |
b0302c68 | 595 | class __make_signed_selector<_Tp, false, true> |
7b50cdef | 596 | { |
a0230468 MM |
597 | // With -fshort-enums, an enum may be as small as a char. |
598 | typedef signed char __smallest; | |
599 | static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); | |
600 | static const bool __b1 = sizeof(_Tp) <= sizeof(signed short); | |
ce2e6349 | 601 | static const bool __b2 = sizeof(_Tp) <= sizeof(signed int); |
a0230468 MM |
602 | typedef conditional<__b2, signed int, signed long> __cond2; |
603 | typedef typename __cond2::type __cond2_type; | |
604 | typedef conditional<__b1, signed short, __cond2_type> __cond1; | |
605 | typedef typename __cond1::type __cond1_type; | |
7b50cdef BK |
606 | |
607 | public: | |
a0230468 | 608 | typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; |
7b50cdef BK |
609 | }; |
610 | ||
7b50cdef BK |
611 | // Given an integral/enum type, return the corresponding signed |
612 | // integer type. | |
5b9daa7e BK |
613 | // Primary template. |
614 | /// make_signed | |
7b50cdef BK |
615 | template<typename _Tp> |
616 | struct make_signed | |
617 | { typedef typename __make_signed_selector<_Tp>::__type type; }; | |
618 | ||
619 | // Integral, but don't define. | |
620 | template<> | |
621 | struct make_signed<bool>; | |
cfa9a96b | 622 | |
5b9daa7e | 623 | /// common_type |
cfa9a96b CF |
624 | template<typename... _Tp> |
625 | struct common_type; | |
626 | ||
627 | template<typename _Tp> | |
628 | struct common_type<_Tp> | |
7274deff | 629 | { typedef _Tp type; }; |
cfa9a96b CF |
630 | |
631 | template<typename _Tp, typename _Up> | |
7274deff PC |
632 | struct common_type<_Tp, _Up> |
633 | { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; }; | |
cfa9a96b CF |
634 | |
635 | template<typename _Tp, typename _Up, typename... _Vp> | |
636 | struct common_type<_Tp, _Up, _Vp...> | |
637 | { | |
638 | typedef typename | |
639 | common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; | |
640 | }; | |
5b9daa7e | 641 | // @} group metaprogramming |
7274deff PC |
642 | |
643 | /// declval | |
644 | template<typename _Tp> | |
645 | struct __declval_protector | |
646 | { | |
647 | static const bool __stop = false; | |
648 | static typename add_rvalue_reference<_Tp>::type __delegate(); | |
649 | }; | |
650 | ||
651 | template<typename _Tp> | |
652 | inline typename add_rvalue_reference<_Tp>::type | |
653 | declval() | |
654 | { | |
655 | static_assert(__declval_protector<_Tp>::__stop, | |
656 | "declval() must not be used!"); | |
657 | return __declval_protector<_Tp>::__delegate(); | |
658 | } | |
e133ace8 | 659 | } |
7b50cdef | 660 | |
57317d2a PC |
661 | #endif // __GXX_EXPERIMENTAL_CXX0X__ |
662 | ||
7274deff | 663 | #endif // _GLIBCXX_TYPE_TRAITS |