]>
Commit | Line | Data |
---|---|---|
5b9daa7e | 1 | // C++0x type_traits -*- C++ -*- |
af13a7a6 | 2 | |
5b9daa7e | 3 | // Copyright (C) 2007, 2008, 2009 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__ |
af13a7a6 | 35 | # include <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 | { | |
5b9daa7e BK |
60 | /** @addtogroup metaprogramming |
61 | * @{ | |
62 | */ | |
63 | ||
4a27a739 | 64 | // Primary classification traits. |
939759fc BK |
65 | |
66 | /// is_lvalue_reference | |
4a27a739 PC |
67 | template<typename> |
68 | struct is_lvalue_reference | |
69 | : public false_type { }; | |
70 | ||
71 | template<typename _Tp> | |
72 | struct is_lvalue_reference<_Tp&> | |
73 | : public true_type { }; | |
74 | ||
939759fc | 75 | /// is_rvalue_reference |
4a27a739 PC |
76 | template<typename> |
77 | struct is_rvalue_reference | |
78 | : public false_type { }; | |
79 | ||
80 | template<typename _Tp> | |
81 | struct is_rvalue_reference<_Tp&&> | |
82 | : public true_type { }; | |
83 | ||
84 | // Secondary classification traits. | |
939759fc BK |
85 | |
86 | /// is_reference | |
4a27a739 PC |
87 | template<typename _Tp> |
88 | struct is_reference | |
89 | : public integral_constant<bool, (is_lvalue_reference<_Tp>::value | |
90 | || is_rvalue_reference<_Tp>::value)> | |
91 | { }; | |
92 | ||
93 | // Reference transformations. | |
939759fc BK |
94 | |
95 | /// remove_reference | |
4a27a739 PC |
96 | template<typename _Tp> |
97 | struct remove_reference | |
98 | { typedef _Tp type; }; | |
99 | ||
100 | template<typename _Tp> | |
101 | struct remove_reference<_Tp&> | |
102 | { typedef _Tp type; }; | |
103 | ||
104 | template<typename _Tp> | |
105 | struct remove_reference<_Tp&&> | |
106 | { typedef _Tp type; }; | |
107 | ||
108 | template<typename _Tp, | |
58366b08 | 109 | bool = !is_reference<_Tp>::value && !is_void<_Tp>::value, |
4a27a739 PC |
110 | bool = is_rvalue_reference<_Tp>::value> |
111 | struct __add_lvalue_reference_helper | |
112 | { typedef _Tp type; }; | |
113 | ||
114 | template<typename _Tp> | |
115 | struct __add_lvalue_reference_helper<_Tp, true, false> | |
116 | { typedef _Tp& type; }; | |
117 | ||
118 | template<typename _Tp> | |
119 | struct __add_lvalue_reference_helper<_Tp, false, true> | |
120 | { typedef typename remove_reference<_Tp>::type& type; }; | |
121 | ||
939759fc | 122 | /// add_lvalue_reference |
4a27a739 PC |
123 | template<typename _Tp> |
124 | struct add_lvalue_reference | |
125 | : public __add_lvalue_reference_helper<_Tp> | |
126 | { }; | |
127 | ||
128 | template<typename _Tp, | |
58366b08 | 129 | bool = !is_reference<_Tp>::value && !is_void<_Tp>::value> |
4a27a739 PC |
130 | struct __add_rvalue_reference_helper |
131 | { typedef _Tp type; }; | |
132 | ||
133 | template<typename _Tp> | |
134 | struct __add_rvalue_reference_helper<_Tp, true> | |
135 | { typedef _Tp&& type; }; | |
136 | ||
939759fc | 137 | /// add_rvalue_reference |
4a27a739 PC |
138 | template<typename _Tp> |
139 | struct add_rvalue_reference | |
140 | : public __add_rvalue_reference_helper<_Tp> | |
141 | { }; | |
142 | ||
143 | // Scalar properties and transformations. | |
939759fc | 144 | |
e133ace8 PC |
145 | template<typename _Tp, |
146 | bool = is_integral<_Tp>::value, | |
147 | bool = is_floating_point<_Tp>::value> | |
148 | struct __is_signed_helper | |
149 | : public false_type { }; | |
150 | ||
151 | template<typename _Tp> | |
152 | struct __is_signed_helper<_Tp, false, true> | |
153 | : public true_type { }; | |
154 | ||
155 | template<typename _Tp> | |
156 | struct __is_signed_helper<_Tp, true, false> | |
157 | : public integral_constant<bool, _Tp(-1) < _Tp(0)> | |
158 | { }; | |
159 | ||
939759fc | 160 | /// is_signed |
e133ace8 PC |
161 | template<typename _Tp> |
162 | struct is_signed | |
163 | : public integral_constant<bool, __is_signed_helper<_Tp>::value> | |
164 | { }; | |
165 | ||
939759fc | 166 | /// is_unsigned |
e133ace8 PC |
167 | template<typename _Tp> |
168 | struct is_unsigned | |
169 | : public integral_constant<bool, (is_arithmetic<_Tp>::value | |
170 | && !is_signed<_Tp>::value)> | |
171 | { }; | |
172 | ||
4a27a739 | 173 | // Member introspection. |
939759fc BK |
174 | |
175 | /// is_pod | |
e133ace8 PC |
176 | template<typename _Tp> |
177 | struct is_pod | |
178 | : public integral_constant<bool, __is_pod(_Tp)> | |
179 | { }; | |
180 | ||
939759fc | 181 | /// has_trivial_default_constructor |
e133ace8 PC |
182 | template<typename _Tp> |
183 | struct has_trivial_default_constructor | |
184 | : public integral_constant<bool, __has_trivial_constructor(_Tp)> | |
185 | { }; | |
186 | ||
939759fc | 187 | /// has_trivial_copy_constructor |
e133ace8 PC |
188 | template<typename _Tp> |
189 | struct has_trivial_copy_constructor | |
190 | : public integral_constant<bool, __has_trivial_copy(_Tp)> | |
191 | { }; | |
192 | ||
939759fc | 193 | /// has_trivial_assign |
e133ace8 PC |
194 | template<typename _Tp> |
195 | struct has_trivial_assign | |
196 | : public integral_constant<bool, __has_trivial_assign(_Tp)> | |
197 | { }; | |
198 | ||
939759fc | 199 | /// has_trivial_destructor |
e133ace8 PC |
200 | template<typename _Tp> |
201 | struct has_trivial_destructor | |
202 | : public integral_constant<bool, __has_trivial_destructor(_Tp)> | |
203 | { }; | |
204 | ||
a7543cfd | 205 | /// has_nothrow_default_constructor |
e133ace8 PC |
206 | template<typename _Tp> |
207 | struct has_nothrow_default_constructor | |
208 | : public integral_constant<bool, __has_nothrow_constructor(_Tp)> | |
209 | { }; | |
210 | ||
a7543cfd | 211 | /// has_nothrow_copy_constructor |
e133ace8 PC |
212 | template<typename _Tp> |
213 | struct has_nothrow_copy_constructor | |
214 | : public integral_constant<bool, __has_nothrow_copy(_Tp)> | |
215 | { }; | |
216 | ||
939759fc | 217 | /// has_nothrow_assign |
e133ace8 PC |
218 | template<typename _Tp> |
219 | struct has_nothrow_assign | |
220 | : public integral_constant<bool, __has_nothrow_assign(_Tp)> | |
221 | { }; | |
222 | ||
939759fc | 223 | /// is_base_of |
e133ace8 PC |
224 | template<typename _Base, typename _Derived> |
225 | struct is_base_of | |
226 | : public integral_constant<bool, __is_base_of(_Base, _Derived)> | |
227 | { }; | |
228 | ||
4a27a739 | 229 | // Relationships between types. |
e133ace8 PC |
230 | template<typename _From, typename _To> |
231 | struct __is_convertible_simple | |
232 | : public __sfinae_types | |
233 | { | |
234 | private: | |
235 | static __one __test(_To); | |
236 | static __two __test(...); | |
237 | static _From __makeFrom(); | |
238 | ||
239 | public: | |
240 | static const bool __value = sizeof(__test(__makeFrom())) == 1; | |
241 | }; | |
242 | ||
243 | template<typename _Tp> | |
244 | struct __is_int_or_cref | |
245 | { | |
246 | typedef typename remove_reference<_Tp>::type __rr_Tp; | |
247 | static const bool __value = (is_integral<_Tp>::value | |
248 | || (is_integral<__rr_Tp>::value | |
249 | && is_const<__rr_Tp>::value | |
250 | && !is_volatile<__rr_Tp>::value)); | |
251 | }; | |
252 | ||
253 | template<typename _From, typename _To, | |
254 | bool = (is_void<_From>::value || is_void<_To>::value | |
255 | || is_function<_To>::value || is_array<_To>::value | |
939759fc | 256 | // This special case is here only to avoid warnings. |
e133ace8 PC |
257 | || (is_floating_point<typename |
258 | remove_reference<_From>::type>::value | |
259 | && __is_int_or_cref<_To>::__value))> | |
260 | struct __is_convertible_helper | |
261 | { | |
262 | // "An imaginary lvalue of type From...". | |
263 | static const bool __value = (__is_convertible_simple<typename | |
6c9bfe99 CF |
264 | add_lvalue_reference<_From>::type, |
265 | _To>::__value); | |
e133ace8 PC |
266 | }; |
267 | ||
268 | template<typename _From, typename _To> | |
269 | struct __is_convertible_helper<_From, _To, true> | |
270 | { static const bool __value = (is_void<_To>::value | |
271 | || (__is_int_or_cref<_To>::__value | |
272 | && !is_void<_From>::value)); }; | |
273 | ||
4a27a739 PC |
274 | // XXX FIXME |
275 | // The C++0x specifications are different, see N2255. | |
939759fc | 276 | /// is_convertible |
e133ace8 PC |
277 | template<typename _From, typename _To> |
278 | struct is_convertible | |
279 | : public integral_constant<bool, | |
280 | __is_convertible_helper<_From, _To>::__value> | |
281 | { }; | |
282 | ||
fd735b6a PC |
283 | template<std::size_t _Len> |
284 | struct __aligned_storage_msa | |
285 | { | |
286 | union __type | |
287 | { | |
288 | unsigned char __data[_Len]; | |
289 | struct __attribute__((__aligned__)) { } __align; | |
290 | }; | |
291 | }; | |
292 | ||
939759fc BK |
293 | /** |
294 | * @brief Alignment type. | |
295 | * | |
296 | * The value of _Align is a default-alignment which shall be the | |
297 | * most stringent alignment requirement for any C++ object type | |
298 | * whose size is no greater than _Len (3.9). The member typedef | |
299 | * type shall be a POD type suitable for use as uninitialized | |
300 | * storage for any object whose size is at most _Len and whose | |
301 | * alignment is a divisor of _Align. | |
302 | */ | |
fd735b6a PC |
303 | template<std::size_t _Len, std::size_t _Align = |
304 | __alignof__(typename __aligned_storage_msa<_Len>::__type)> | |
305 | struct aligned_storage | |
306 | { | |
307 | union type | |
308 | { | |
309 | unsigned char __data[_Len]; | |
310 | struct __attribute__((__aligned__((_Align)))) { } __align; | |
311 | }; | |
312 | }; | |
313 | ||
7b50cdef BK |
314 | |
315 | // Define a nested type if some predicate holds. | |
5b9daa7e BK |
316 | // Primary template. |
317 | /// enable_if | |
7b50cdef BK |
318 | template<bool, typename _Tp = void> |
319 | struct enable_if | |
320 | { }; | |
321 | ||
5b9daa7e | 322 | // Partial specialization for true. |
7b50cdef BK |
323 | template<typename _Tp> |
324 | struct enable_if<true, _Tp> | |
325 | { typedef _Tp type; }; | |
326 | ||
327 | ||
5b9daa7e BK |
328 | // A conditional expression, but for types. If true, first, if false, second. |
329 | // Primary template. | |
330 | /// conditional | |
7b50cdef BK |
331 | template<bool _Cond, typename _Iftrue, typename _Iffalse> |
332 | struct conditional | |
333 | { typedef _Iftrue type; }; | |
334 | ||
5b9daa7e | 335 | // Partial specialization for false. |
7b50cdef BK |
336 | template<typename _Iftrue, typename _Iffalse> |
337 | struct conditional<false, _Iftrue, _Iffalse> | |
338 | { typedef _Iffalse type; }; | |
339 | ||
340 | ||
341 | // Decay trait for arrays and functions, used for perfect forwarding | |
342 | // in make_pair, make_tuple, etc. | |
343 | template<typename _Up, | |
344 | bool _IsArray = is_array<_Up>::value, | |
345 | bool _IsFunction = is_function<_Up>::value> | |
346 | struct __decay_selector; | |
347 | ||
ce796131 | 348 | // NB: DR 705. |
7b50cdef BK |
349 | template<typename _Up> |
350 | struct __decay_selector<_Up, false, false> | |
ce796131 | 351 | { typedef typename remove_cv<_Up>::type __type; }; |
7b50cdef BK |
352 | |
353 | template<typename _Up> | |
354 | struct __decay_selector<_Up, true, false> | |
355 | { typedef typename remove_extent<_Up>::type* __type; }; | |
356 | ||
7b50cdef BK |
357 | template<typename _Up> |
358 | struct __decay_selector<_Up, false, true> | |
359 | { typedef typename add_pointer<_Up>::type __type; }; | |
360 | ||
939759fc | 361 | /// decay |
7b50cdef | 362 | template<typename _Tp> |
ce796131 | 363 | struct decay |
7b50cdef BK |
364 | { |
365 | private: | |
366 | typedef typename remove_reference<_Tp>::type __remove_type; | |
367 | ||
368 | public: | |
369 | typedef typename __decay_selector<__remove_type>::__type type; | |
370 | }; | |
371 | ||
372 | ||
373 | // Utility for constructing identically cv-qualified types. | |
374 | template<typename _Unqualified, bool _IsConst, bool _IsVol> | |
375 | struct __cv_selector; | |
376 | ||
377 | template<typename _Unqualified> | |
378 | struct __cv_selector<_Unqualified, false, false> | |
379 | { typedef _Unqualified __type; }; | |
380 | ||
381 | template<typename _Unqualified> | |
382 | struct __cv_selector<_Unqualified, false, true> | |
383 | { typedef volatile _Unqualified __type; }; | |
384 | ||
385 | template<typename _Unqualified> | |
386 | struct __cv_selector<_Unqualified, true, false> | |
387 | { typedef const _Unqualified __type; }; | |
388 | ||
389 | template<typename _Unqualified> | |
390 | struct __cv_selector<_Unqualified, true, true> | |
391 | { typedef const volatile _Unqualified __type; }; | |
392 | ||
393 | template<typename _Qualified, typename _Unqualified, | |
394 | bool _IsConst = is_const<_Qualified>::value, | |
395 | bool _IsVol = is_volatile<_Qualified>::value> | |
396 | struct __match_cv_qualifiers | |
397 | { | |
398 | private: | |
399 | typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match; | |
400 | ||
401 | public: | |
402 | typedef typename __match::__type __type; | |
403 | }; | |
404 | ||
405 | ||
406 | // Utility for finding the unsigned versions of signed integral types. | |
407 | template<typename _Tp> | |
e133ace8 PC |
408 | struct __make_unsigned |
409 | { typedef _Tp __type; }; | |
7b50cdef BK |
410 | |
411 | template<> | |
412 | struct __make_unsigned<char> | |
413 | { typedef unsigned char __type; }; | |
414 | ||
415 | template<> | |
416 | struct __make_unsigned<signed char> | |
417 | { typedef unsigned char __type; }; | |
418 | ||
7b50cdef BK |
419 | template<> |
420 | struct __make_unsigned<short> | |
421 | { typedef unsigned short __type; }; | |
422 | ||
423 | template<> | |
424 | struct __make_unsigned<int> | |
425 | { typedef unsigned int __type; }; | |
426 | ||
427 | template<> | |
428 | struct __make_unsigned<long> | |
429 | { typedef unsigned long __type; }; | |
430 | ||
431 | template<> | |
432 | struct __make_unsigned<long long> | |
433 | { typedef unsigned long long __type; }; | |
434 | ||
435 | ||
436 | // Select between integral and enum: not possible to be both. | |
437 | template<typename _Tp, | |
438 | bool _IsInt = is_integral<_Tp>::value, | |
7b50cdef BK |
439 | bool _IsEnum = is_enum<_Tp>::value> |
440 | struct __make_unsigned_selector; | |
441 | ||
442 | template<typename _Tp> | |
e133ace8 | 443 | struct __make_unsigned_selector<_Tp, true, false> |
7b50cdef BK |
444 | { |
445 | private: | |
446 | typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt; | |
447 | typedef typename __unsignedt::__type __unsigned_type; | |
448 | typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned; | |
449 | ||
450 | public: | |
451 | typedef typename __cv_unsigned::__type __type; | |
452 | }; | |
453 | ||
7b50cdef | 454 | template<typename _Tp> |
e133ace8 | 455 | struct __make_unsigned_selector<_Tp, false, true> |
7b50cdef BK |
456 | { |
457 | private: | |
a0230468 MM |
458 | // With -fshort-enums, an enum may be as small as a char. |
459 | typedef unsigned char __smallest; | |
460 | static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); | |
461 | static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short); | |
ce2e6349 | 462 | static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int); |
a0230468 MM |
463 | typedef conditional<__b2, unsigned int, unsigned long> __cond2; |
464 | typedef typename __cond2::type __cond2_type; | |
465 | typedef conditional<__b1, unsigned short, __cond2_type> __cond1; | |
466 | typedef typename __cond1::type __cond1_type; | |
7b50cdef BK |
467 | |
468 | public: | |
a0230468 | 469 | typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; |
7b50cdef BK |
470 | }; |
471 | ||
7b50cdef BK |
472 | // Given an integral/enum type, return the corresponding unsigned |
473 | // integer type. | |
5b9daa7e BK |
474 | // Primary template. |
475 | /// make_unsigned | |
7b50cdef BK |
476 | template<typename _Tp> |
477 | struct make_unsigned | |
478 | { typedef typename __make_unsigned_selector<_Tp>::__type type; }; | |
479 | ||
480 | // Integral, but don't define. | |
481 | template<> | |
482 | struct make_unsigned<bool>; | |
483 | ||
484 | ||
485 | // Utility for finding the signed versions of unsigned integral types. | |
486 | template<typename _Tp> | |
e133ace8 PC |
487 | struct __make_signed |
488 | { typedef _Tp __type; }; | |
7b50cdef BK |
489 | |
490 | template<> | |
491 | struct __make_signed<char> | |
492 | { typedef signed char __type; }; | |
493 | ||
494 | template<> | |
495 | struct __make_signed<unsigned char> | |
496 | { typedef signed char __type; }; | |
497 | ||
7b50cdef BK |
498 | template<> |
499 | struct __make_signed<unsigned short> | |
500 | { typedef signed short __type; }; | |
501 | ||
502 | template<> | |
503 | struct __make_signed<unsigned int> | |
504 | { typedef signed int __type; }; | |
505 | ||
506 | template<> | |
507 | struct __make_signed<unsigned long> | |
508 | { typedef signed long __type; }; | |
509 | ||
510 | template<> | |
511 | struct __make_signed<unsigned long long> | |
512 | { typedef signed long long __type; }; | |
513 | ||
514 | ||
fb8ffd10 | 515 | // Select between integral and enum: not possible to be both. |
7b50cdef BK |
516 | template<typename _Tp, |
517 | bool _IsInt = is_integral<_Tp>::value, | |
7b50cdef BK |
518 | bool _IsEnum = is_enum<_Tp>::value> |
519 | struct __make_signed_selector; | |
520 | ||
521 | template<typename _Tp> | |
e133ace8 | 522 | struct __make_signed_selector<_Tp, true, false> |
7b50cdef BK |
523 | { |
524 | private: | |
525 | typedef __make_signed<typename remove_cv<_Tp>::type> __signedt; | |
526 | typedef typename __signedt::__type __signed_type; | |
527 | typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed; | |
528 | ||
529 | public: | |
530 | typedef typename __cv_signed::__type __type; | |
531 | }; | |
532 | ||
7b50cdef | 533 | template<typename _Tp> |
e133ace8 | 534 | struct __make_signed_selector<_Tp, false, true> |
7b50cdef BK |
535 | { |
536 | private: | |
a0230468 MM |
537 | // With -fshort-enums, an enum may be as small as a char. |
538 | typedef signed char __smallest; | |
539 | static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); | |
540 | static const bool __b1 = sizeof(_Tp) <= sizeof(signed short); | |
ce2e6349 | 541 | static const bool __b2 = sizeof(_Tp) <= sizeof(signed int); |
a0230468 MM |
542 | typedef conditional<__b2, signed int, signed long> __cond2; |
543 | typedef typename __cond2::type __cond2_type; | |
544 | typedef conditional<__b1, signed short, __cond2_type> __cond1; | |
545 | typedef typename __cond1::type __cond1_type; | |
7b50cdef BK |
546 | |
547 | public: | |
a0230468 | 548 | typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; |
7b50cdef BK |
549 | }; |
550 | ||
7b50cdef BK |
551 | // Given an integral/enum type, return the corresponding signed |
552 | // integer type. | |
5b9daa7e BK |
553 | // Primary template. |
554 | /// make_signed | |
7b50cdef BK |
555 | template<typename _Tp> |
556 | struct make_signed | |
557 | { typedef typename __make_signed_selector<_Tp>::__type type; }; | |
558 | ||
559 | // Integral, but don't define. | |
560 | template<> | |
561 | struct make_signed<bool>; | |
cfa9a96b | 562 | |
5b9daa7e | 563 | /// common_type |
cfa9a96b CF |
564 | template<typename... _Tp> |
565 | struct common_type; | |
566 | ||
567 | template<typename _Tp> | |
568 | struct common_type<_Tp> | |
569 | { | |
570 | static_assert(sizeof(_Tp) > 0, "must be complete type"); | |
571 | typedef _Tp type; | |
572 | }; | |
573 | ||
574 | template<typename _Tp, typename _Up> | |
575 | class common_type<_Tp, _Up> | |
576 | { | |
577 | static_assert(sizeof(_Tp) > 0, "must be complete type"); | |
578 | static_assert(sizeof(_Up) > 0, "must be complete type"); | |
579 | ||
580 | static _Tp&& __t(); | |
581 | static _Up&& __u(); | |
582 | ||
cfa9a96b | 583 | public: |
026ec377 | 584 | typedef decltype(true ? __t() : __u()) type; |
cfa9a96b CF |
585 | }; |
586 | ||
587 | template<typename _Tp, typename _Up, typename... _Vp> | |
588 | struct common_type<_Tp, _Up, _Vp...> | |
589 | { | |
590 | typedef typename | |
591 | common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; | |
592 | }; | |
5b9daa7e BK |
593 | |
594 | // @} group metaprogramming | |
e133ace8 | 595 | } |
7b50cdef | 596 | |
57317d2a PC |
597 | #endif // __GXX_EXPERIMENTAL_CXX0X__ |
598 | ||
4514bed6 | 599 | #endif // _GLIBCXX_TYPE_TRAITS |
af13a7a6 | 600 |