]>
Commit | Line | Data |
---|---|---|
af13a7a6 BK |
1 | // <type_traits> -*- C++ -*- |
2 | ||
939759fc | 3 | // Copyright (C) 2007, 2008 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 | |
8 | // Free Software Foundation; either version 2, or (at your option) | |
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 | ||
16 | // You should have received a copy of the GNU General Public License | |
17 | // along with this library; see the file COPYING. If not, write to | |
18 | // the Free Software Foundation, 51 Franklin Street, Fifth Floor, | |
19 | // Boston, MA 02110-1301, USA. | |
20 | ||
21 | // As a special exception, you may use this file as part of a free software | |
22 | // library without restriction. Specifically, if other files instantiate | |
23 | // templates or use macros or inline functions from this file, or you compile | |
24 | // this file and link it with other files to produce an executable, this | |
25 | // file does not by itself cause the resulting executable to be covered by | |
26 | // the GNU General Public License. This exception does not however | |
27 | // invalidate any other reasons why the executable file might be covered by | |
28 | // the GNU General Public License. | |
29 | ||
30 | /** @file include/type_traits | |
31 | * This is a Standard C++ Library header. | |
32 | */ | |
33 | ||
4514bed6 BK |
34 | #ifndef _GLIBCXX_TYPE_TRAITS |
35 | #define _GLIBCXX_TYPE_TRAITS 1 | |
af13a7a6 BK |
36 | |
37 | #pragma GCC system_header | |
38 | ||
57317d2a | 39 | #ifndef __GXX_EXPERIMENTAL_CXX0X__ |
af13a7a6 | 40 | # include <c++0x_warning.h> |
57317d2a | 41 | #else |
af13a7a6 | 42 | |
e133ace8 PC |
43 | #if defined(_GLIBCXX_INCLUDE_AS_TR1) |
44 | # error C++0x header cannot be included from TR1 header | |
45 | #endif | |
46 | ||
47 | #include <cstddef> | |
48 | ||
49 | #if defined(_GLIBCXX_INCLUDE_AS_CXX0X) | |
50 | # include <tr1_impl/type_traits> | |
51 | #else | |
52 | # define _GLIBCXX_INCLUDE_AS_CXX0X | |
53 | # define _GLIBCXX_BEGIN_NAMESPACE_TR1 | |
54 | # define _GLIBCXX_END_NAMESPACE_TR1 | |
55 | # define _GLIBCXX_TR1 | |
56 | # include <tr1_impl/type_traits> | |
57 | # undef _GLIBCXX_TR1 | |
58 | # undef _GLIBCXX_END_NAMESPACE_TR1 | |
59 | # undef _GLIBCXX_BEGIN_NAMESPACE_TR1 | |
60 | # undef _GLIBCXX_INCLUDE_AS_CXX0X | |
61 | #endif | |
62 | ||
63 | namespace std | |
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, | |
110 | bool = is_object<_Tp>::value || is_function<_Tp>::value, | |
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, | |
130 | bool = is_object<_Tp>::value || is_function<_Tp>::value> | |
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> | |
158 | : public integral_constant<bool, _Tp(-1) < _Tp(0)> | |
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 BK |
175 | |
176 | /// is_pod | |
e133ace8 PC |
177 | template<typename _Tp> |
178 | struct is_pod | |
179 | : public integral_constant<bool, __is_pod(_Tp)> | |
180 | { }; | |
181 | ||
939759fc | 182 | /// has_trivial_default_constructor |
e133ace8 PC |
183 | template<typename _Tp> |
184 | struct has_trivial_default_constructor | |
185 | : public integral_constant<bool, __has_trivial_constructor(_Tp)> | |
186 | { }; | |
187 | ||
939759fc | 188 | /// has_trivial_copy_constructor |
e133ace8 PC |
189 | template<typename _Tp> |
190 | struct has_trivial_copy_constructor | |
191 | : public integral_constant<bool, __has_trivial_copy(_Tp)> | |
192 | { }; | |
193 | ||
939759fc | 194 | /// has_trivial_assign |
e133ace8 PC |
195 | template<typename _Tp> |
196 | struct has_trivial_assign | |
197 | : public integral_constant<bool, __has_trivial_assign(_Tp)> | |
198 | { }; | |
199 | ||
939759fc | 200 | /// has_trivial_destructor |
e133ace8 PC |
201 | template<typename _Tp> |
202 | struct has_trivial_destructor | |
203 | : public integral_constant<bool, __has_trivial_destructor(_Tp)> | |
204 | { }; | |
205 | ||
a7543cfd | 206 | /// has_nothrow_default_constructor |
e133ace8 PC |
207 | template<typename _Tp> |
208 | struct has_nothrow_default_constructor | |
209 | : public integral_constant<bool, __has_nothrow_constructor(_Tp)> | |
210 | { }; | |
211 | ||
a7543cfd | 212 | /// has_nothrow_copy_constructor |
e133ace8 PC |
213 | template<typename _Tp> |
214 | struct has_nothrow_copy_constructor | |
215 | : public integral_constant<bool, __has_nothrow_copy(_Tp)> | |
216 | { }; | |
217 | ||
939759fc | 218 | /// has_nothrow_assign |
e133ace8 PC |
219 | template<typename _Tp> |
220 | struct has_nothrow_assign | |
221 | : public integral_constant<bool, __has_nothrow_assign(_Tp)> | |
222 | { }; | |
223 | ||
939759fc | 224 | /// is_base_of |
e133ace8 PC |
225 | template<typename _Base, typename _Derived> |
226 | struct is_base_of | |
227 | : public integral_constant<bool, __is_base_of(_Base, _Derived)> | |
228 | { }; | |
229 | ||
4a27a739 | 230 | // Relationships between types. |
e133ace8 PC |
231 | template<typename _From, typename _To> |
232 | struct __is_convertible_simple | |
233 | : public __sfinae_types | |
234 | { | |
235 | private: | |
236 | static __one __test(_To); | |
237 | static __two __test(...); | |
238 | static _From __makeFrom(); | |
239 | ||
240 | public: | |
241 | static const bool __value = sizeof(__test(__makeFrom())) == 1; | |
242 | }; | |
243 | ||
244 | template<typename _Tp> | |
245 | struct __is_int_or_cref | |
246 | { | |
247 | typedef typename remove_reference<_Tp>::type __rr_Tp; | |
248 | static const bool __value = (is_integral<_Tp>::value | |
249 | || (is_integral<__rr_Tp>::value | |
250 | && is_const<__rr_Tp>::value | |
251 | && !is_volatile<__rr_Tp>::value)); | |
252 | }; | |
253 | ||
254 | template<typename _From, typename _To, | |
255 | bool = (is_void<_From>::value || is_void<_To>::value | |
256 | || is_function<_To>::value || is_array<_To>::value | |
939759fc | 257 | // This special case is here only to avoid warnings. |
e133ace8 PC |
258 | || (is_floating_point<typename |
259 | remove_reference<_From>::type>::value | |
260 | && __is_int_or_cref<_To>::__value))> | |
261 | struct __is_convertible_helper | |
262 | { | |
263 | // "An imaginary lvalue of type From...". | |
264 | static const bool __value = (__is_convertible_simple<typename | |
6c9bfe99 CF |
265 | add_lvalue_reference<_From>::type, |
266 | _To>::__value); | |
e133ace8 PC |
267 | }; |
268 | ||
269 | template<typename _From, typename _To> | |
270 | struct __is_convertible_helper<_From, _To, true> | |
271 | { static const bool __value = (is_void<_To>::value | |
272 | || (__is_int_or_cref<_To>::__value | |
273 | && !is_void<_From>::value)); }; | |
274 | ||
4a27a739 PC |
275 | // XXX FIXME |
276 | // The C++0x specifications are different, see N2255. | |
939759fc | 277 | /// is_convertible |
e133ace8 PC |
278 | template<typename _From, typename _To> |
279 | struct is_convertible | |
280 | : public integral_constant<bool, | |
281 | __is_convertible_helper<_From, _To>::__value> | |
282 | { }; | |
283 | ||
fd735b6a PC |
284 | template<std::size_t _Len> |
285 | struct __aligned_storage_msa | |
286 | { | |
287 | union __type | |
288 | { | |
289 | unsigned char __data[_Len]; | |
290 | struct __attribute__((__aligned__)) { } __align; | |
291 | }; | |
292 | }; | |
293 | ||
939759fc BK |
294 | /** |
295 | * @brief Alignment type. | |
296 | * | |
297 | * The value of _Align is a default-alignment which shall be the | |
298 | * most stringent alignment requirement for any C++ object type | |
299 | * whose size is no greater than _Len (3.9). The member typedef | |
300 | * type shall be a POD type suitable for use as uninitialized | |
301 | * storage for any object whose size is at most _Len and whose | |
302 | * alignment is a divisor of _Align. | |
303 | */ | |
fd735b6a PC |
304 | template<std::size_t _Len, std::size_t _Align = |
305 | __alignof__(typename __aligned_storage_msa<_Len>::__type)> | |
306 | struct aligned_storage | |
307 | { | |
308 | union type | |
309 | { | |
310 | unsigned char __data[_Len]; | |
311 | struct __attribute__((__aligned__((_Align)))) { } __align; | |
312 | }; | |
313 | }; | |
314 | ||
7b50cdef BK |
315 | |
316 | // Define a nested type if some predicate holds. | |
939759fc | 317 | /// Primary template. |
7b50cdef BK |
318 | template<bool, typename _Tp = void> |
319 | struct enable_if | |
320 | { }; | |
321 | ||
939759fc | 322 | /// Partial specialization for true. |
7b50cdef BK |
323 | template<typename _Tp> |
324 | struct enable_if<true, _Tp> | |
325 | { typedef _Tp type; }; | |
326 | ||
327 | ||
939759fc BK |
328 | // A conditional expression, but for types. |
329 | // If true, first, if false, second. | |
330 | /// Primary template. | |
7b50cdef BK |
331 | template<bool _Cond, typename _Iftrue, typename _Iffalse> |
332 | struct conditional | |
333 | { typedef _Iftrue type; }; | |
334 | ||
939759fc | 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: | |
ce2e6349 BK |
458 | // GNU enums start with sizeof short. |
459 | typedef unsigned short __smallest; | |
460 | static const bool __b1 = sizeof(_Tp) <= sizeof(__smallest); | |
461 | static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int); | |
462 | typedef conditional<__b2, unsigned int, unsigned long> __cond; | |
7b50cdef | 463 | typedef typename __cond::type __cond_type; |
7b50cdef BK |
464 | |
465 | public: | |
ce2e6349 | 466 | typedef typename conditional<__b1, __smallest, __cond_type>::type __type; |
7b50cdef BK |
467 | }; |
468 | ||
7b50cdef BK |
469 | // Given an integral/enum type, return the corresponding unsigned |
470 | // integer type. | |
939759fc | 471 | /// Primary template. |
7b50cdef BK |
472 | template<typename _Tp> |
473 | struct make_unsigned | |
474 | { typedef typename __make_unsigned_selector<_Tp>::__type type; }; | |
475 | ||
476 | // Integral, but don't define. | |
477 | template<> | |
478 | struct make_unsigned<bool>; | |
479 | ||
480 | ||
481 | // Utility for finding the signed versions of unsigned integral types. | |
482 | template<typename _Tp> | |
e133ace8 PC |
483 | struct __make_signed |
484 | { typedef _Tp __type; }; | |
7b50cdef BK |
485 | |
486 | template<> | |
487 | struct __make_signed<char> | |
488 | { typedef signed char __type; }; | |
489 | ||
490 | template<> | |
491 | struct __make_signed<unsigned char> | |
492 | { typedef signed char __type; }; | |
493 | ||
7b50cdef BK |
494 | template<> |
495 | struct __make_signed<unsigned short> | |
496 | { typedef signed short __type; }; | |
497 | ||
498 | template<> | |
499 | struct __make_signed<unsigned int> | |
500 | { typedef signed int __type; }; | |
501 | ||
502 | template<> | |
503 | struct __make_signed<unsigned long> | |
504 | { typedef signed long __type; }; | |
505 | ||
506 | template<> | |
507 | struct __make_signed<unsigned long long> | |
508 | { typedef signed long long __type; }; | |
509 | ||
510 | ||
fb8ffd10 | 511 | // Select between integral and enum: not possible to be both. |
7b50cdef BK |
512 | template<typename _Tp, |
513 | bool _IsInt = is_integral<_Tp>::value, | |
7b50cdef BK |
514 | bool _IsEnum = is_enum<_Tp>::value> |
515 | struct __make_signed_selector; | |
516 | ||
517 | template<typename _Tp> | |
e133ace8 | 518 | struct __make_signed_selector<_Tp, true, false> |
7b50cdef BK |
519 | { |
520 | private: | |
521 | typedef __make_signed<typename remove_cv<_Tp>::type> __signedt; | |
522 | typedef typename __signedt::__type __signed_type; | |
523 | typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed; | |
524 | ||
525 | public: | |
526 | typedef typename __cv_signed::__type __type; | |
527 | }; | |
528 | ||
7b50cdef | 529 | template<typename _Tp> |
e133ace8 | 530 | struct __make_signed_selector<_Tp, false, true> |
7b50cdef BK |
531 | { |
532 | private: | |
ce2e6349 BK |
533 | // GNU enums start with sizeof short. |
534 | typedef signed short __smallest; | |
535 | static const bool __b1 = sizeof(_Tp) <= sizeof(__smallest); | |
536 | static const bool __b2 = sizeof(_Tp) <= sizeof(signed int); | |
537 | typedef conditional<__b2, signed int, signed long> __cond; | |
7b50cdef | 538 | typedef typename __cond::type __cond_type; |
7b50cdef BK |
539 | |
540 | public: | |
ce2e6349 | 541 | typedef typename conditional<__b1, __smallest, __cond_type>::type __type; |
7b50cdef BK |
542 | }; |
543 | ||
7b50cdef BK |
544 | // Given an integral/enum type, return the corresponding signed |
545 | // integer type. | |
939759fc | 546 | /// Primary template. |
7b50cdef BK |
547 | template<typename _Tp> |
548 | struct make_signed | |
549 | { typedef typename __make_signed_selector<_Tp>::__type type; }; | |
550 | ||
551 | // Integral, but don't define. | |
552 | template<> | |
553 | struct make_signed<bool>; | |
cfa9a96b CF |
554 | |
555 | template<typename... _Tp> | |
556 | struct common_type; | |
557 | ||
558 | template<typename _Tp> | |
559 | struct common_type<_Tp> | |
560 | { | |
561 | static_assert(sizeof(_Tp) > 0, "must be complete type"); | |
562 | typedef _Tp type; | |
563 | }; | |
564 | ||
565 | template<typename _Tp, typename _Up> | |
566 | class common_type<_Tp, _Up> | |
567 | { | |
568 | static_assert(sizeof(_Tp) > 0, "must be complete type"); | |
569 | static_assert(sizeof(_Up) > 0, "must be complete type"); | |
570 | ||
571 | static _Tp&& __t(); | |
572 | static _Up&& __u(); | |
573 | ||
574 | // HACK: Prevents optimization of ?: in the decltype | |
575 | // expression when the condition is the literal, "true". | |
576 | // See, PR36628. | |
577 | static bool __true_or_false(); | |
578 | ||
579 | public: | |
580 | typedef decltype(__true_or_false() ? __t() : __u()) type; | |
581 | }; | |
582 | ||
583 | template<typename _Tp, typename _Up, typename... _Vp> | |
584 | struct common_type<_Tp, _Up, _Vp...> | |
585 | { | |
586 | typedef typename | |
587 | common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; | |
588 | }; | |
e133ace8 | 589 | } |
7b50cdef | 590 | |
57317d2a PC |
591 | #endif // __GXX_EXPERIMENTAL_CXX0X__ |
592 | ||
4514bed6 | 593 | #endif // _GLIBCXX_TYPE_TRAITS |
af13a7a6 | 594 |