1 // TR1 type_traits -*- C++ -*-
3 // Copyright (C) 2004, 2005 Free Software Foundation, Inc.
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)
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.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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.
31 * This is a TR1 C++ Library header.
35 #define _TYPE_TRAITS 1
37 #include <bits/c++config.h>
38 #include <tr1/type_traits_fwd.h>
45 // For use in __in_array and elsewhere.
49 typedef struct { char __arr[2]; } __two;
52 template<typename _Tp>
54 : public __sfinae_types
57 template<typename _Up>
58 static __one __test(_Up(*)[1]);
60 static __two __test(...);
63 static const bool __value = sizeof(__test<_Tp>(0)) == 1;
66 #define _DEFINE_SPEC_BODY(_Value) \
67 : public integral_constant<bool, _Value> { };
69 #define _DEFINE_SPEC_0_HELPER(_Spec, _Value) \
72 _DEFINE_SPEC_BODY(_Value)
74 #define _DEFINE_SPEC_1_HELPER(_Spec, _Value) \
75 template<typename _Tp> \
77 _DEFINE_SPEC_BODY(_Value)
79 #define _DEFINE_SPEC_2_HELPER(_Spec, _Value) \
80 template<typename _Tp, typename _Cp> \
82 _DEFINE_SPEC_BODY(_Value)
84 #define _DEFINE_SPEC(_Order, _Trait, _Type, _Value) \
85 _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type>, _Value) \
86 _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const>, _Value) \
87 _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type volatile>, _Value) \
88 _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const volatile>, _Value)
90 /// @brief helper classes [4.3].
91 template<typename _Tp, _Tp __v>
92 struct integral_constant
94 static const _Tp value = __v;
95 typedef _Tp value_type;
96 typedef integral_constant<_Tp, __v> type;
98 typedef integral_constant<bool, true> true_type;
99 typedef integral_constant<bool, false> false_type;
101 /// @brief primary type categories [4.5.1].
104 : public false_type { };
105 _DEFINE_SPEC(0, is_void, void, true)
109 : public false_type { };
110 _DEFINE_SPEC(0, is_integral, bool, true)
111 _DEFINE_SPEC(0, is_integral, char, true)
112 _DEFINE_SPEC(0, is_integral, signed char, true)
113 _DEFINE_SPEC(0, is_integral, unsigned char, true)
114 #ifdef _GLIBCXX_USE_WCHAR_T
115 _DEFINE_SPEC(0, is_integral, wchar_t, true)
117 _DEFINE_SPEC(0, is_integral, short, true)
118 _DEFINE_SPEC(0, is_integral, unsigned short, true)
119 _DEFINE_SPEC(0, is_integral, int, true)
120 _DEFINE_SPEC(0, is_integral, unsigned int, true)
121 _DEFINE_SPEC(0, is_integral, long, true)
122 _DEFINE_SPEC(0, is_integral, unsigned long, true)
123 _DEFINE_SPEC(0, is_integral, long long, true)
124 _DEFINE_SPEC(0, is_integral, unsigned long long, true)
127 struct is_floating_point
128 : public false_type { };
129 _DEFINE_SPEC(0, is_floating_point, float, true)
130 _DEFINE_SPEC(0, is_floating_point, double, true)
131 _DEFINE_SPEC(0, is_floating_point, long double, true)
135 : public false_type { };
137 template<typename _Tp, std::size_t _Size>
138 struct is_array<_Tp[_Size]>
139 : public true_type { };
141 template<typename _Tp>
142 struct is_array<_Tp[]>
143 : public true_type { };
147 : public false_type { };
148 _DEFINE_SPEC(1, is_pointer, _Tp*, true)
152 : public false_type { };
154 template<typename _Tp>
155 struct is_reference<_Tp&>
156 : public true_type { };
159 struct is_member_object_pointer
160 : public false_type { };
161 _DEFINE_SPEC(2, is_member_object_pointer, _Tp _Cp::*,
162 !is_function<_Tp>::value)
165 struct is_member_function_pointer
166 : public false_type { };
167 _DEFINE_SPEC(2, is_member_function_pointer, _Tp _Cp::*,
168 is_function<_Tp>::value)
170 template<typename _Tp>
172 : public integral_constant<bool, !(is_fundamental<_Tp>::value
173 || is_array<_Tp>::value
174 || is_pointer<_Tp>::value
175 || is_reference<_Tp>::value
176 || is_member_pointer<_Tp>::value
177 || is_function<_Tp>::value
178 || __is_union_or_class<_Tp>::value)>
187 template<typename _Tp>
189 : public integral_constant<bool, !(__in_array<_Tp>::__value
190 || __is_union_or_class<_Tp>::value
191 || is_reference<_Tp>::value
192 || is_void<_Tp>::value)>
195 /// @brief composite type traits [4.5.2].
196 template<typename _Tp>
198 : public integral_constant<bool, (is_integral<_Tp>::value
199 || is_floating_point<_Tp>::value)>
202 template<typename _Tp>
203 struct is_fundamental
204 : public integral_constant<bool, (is_arithmetic<_Tp>::value
205 || is_void<_Tp>::value)>
208 template<typename _Tp>
210 : public integral_constant<bool, !(is_function<_Tp>::value
211 || is_reference<_Tp>::value
212 || is_void<_Tp>::value)>
215 template<typename _Tp>
217 : public integral_constant<bool, (is_arithmetic<_Tp>::value
218 || is_enum<_Tp>::value
219 || is_pointer<_Tp>::value
220 || is_member_pointer<_Tp>::value)>
223 template<typename _Tp>
225 : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
227 template<typename _Tp>
228 struct is_member_pointer
229 : public integral_constant<bool,
230 (is_member_object_pointer<_Tp>::value
231 || is_member_function_pointer<_Tp>::value)>
234 template<typename _Tp>
235 struct __is_union_or_class_helper
236 : public __sfinae_types
239 template<typename _Up>
240 static __one __test(int _Up::*);
242 static __two __test(...);
245 static const bool __value = sizeof(__test<_Tp>(0)) == 1;
249 template<typename _Tp>
250 struct __is_union_or_class
251 : public integral_constant<bool, __is_union_or_class_helper<_Tp>::__value>
254 /// @brief type properties [4.5.3].
257 : public false_type { };
259 template<typename _Tp>
260 struct is_const<_Tp const>
261 : public true_type { };
265 : public false_type { };
267 template<typename _Tp>
268 struct is_volatile<_Tp volatile>
269 : public true_type { };
271 template<typename _Tp>
273 : public integral_constant<bool, (is_void<_Tp>::value
274 || is_scalar<typename
275 remove_all_extents<_Tp>::type>::value)>
278 // N.B. Without compiler support we cannot tell union from class types,
279 // and is_empty and is_polymorphic don't work at all with the former.
280 template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
281 struct __is_empty_helper
286 template<typename _Up>
291 static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
294 template<typename _Tp>
295 struct __is_empty_helper<_Tp, true>
296 { static const bool __value = false; };
298 template<typename _Tp>
300 : public integral_constant<bool, __is_empty_helper<_Tp>::__value>
303 template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
304 struct __is_polymorphic_helper
307 template<typename _Up>
310 template<typename _Up>
314 virtual void __dummy();
315 virtual ~__second() throw();
319 static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
322 template<typename _Tp>
323 struct __is_polymorphic_helper<_Tp, true>
324 { static const bool __value = false; };
326 template<typename _Tp>
327 struct is_polymorphic
328 : public integral_constant<bool, __is_polymorphic_helper<_Tp>::__value>
331 // Exploit the resolution DR core/337.
332 template<typename _Tp>
334 : public integral_constant<bool, (!__in_array<_Tp>::__value
335 && __is_union_or_class<_Tp>::value)> { };
337 template<typename _Tp>
338 struct has_trivial_constructor
339 : public integral_constant<bool, is_pod<_Tp>::value> { };
341 template<typename _Tp>
342 struct has_trivial_copy
343 : public integral_constant<bool, is_pod<_Tp>::value> { };
345 template<typename _Tp>
346 struct has_trivial_assign
347 : public integral_constant<bool, is_pod<_Tp>::value> { };
349 template<typename _Tp>
350 struct has_trivial_destructor
351 : public integral_constant<bool, is_pod<_Tp>::value> { };
353 template<typename _Tp>
354 struct has_nothrow_constructor
355 : public integral_constant<bool, is_pod<_Tp>::value> { };
357 template<typename _Tp>
358 struct has_nothrow_copy
359 : public integral_constant<bool, is_pod<_Tp>::value> { };
361 template<typename _Tp>
362 struct has_nothrow_assign
363 : public integral_constant<bool, is_pod<_Tp>::value> { };
366 struct has_virtual_destructor
367 : public false_type { };
371 : public false_type { };
372 _DEFINE_SPEC(0, is_signed, signed char, true)
373 _DEFINE_SPEC(0, is_signed, short, true)
374 _DEFINE_SPEC(0, is_signed, int, true)
375 _DEFINE_SPEC(0, is_signed, long, true)
376 _DEFINE_SPEC(0, is_signed, long long, true)
380 : public false_type { };
381 _DEFINE_SPEC(0, is_unsigned, unsigned char, true)
382 _DEFINE_SPEC(0, is_unsigned, unsigned short, true)
383 _DEFINE_SPEC(0, is_unsigned, unsigned int, true)
384 _DEFINE_SPEC(0, is_unsigned, unsigned long, true)
385 _DEFINE_SPEC(0, is_unsigned, unsigned long long, true)
387 template<typename _Tp>
389 : public integral_constant<std::size_t, __alignof__(_Tp)> { };
393 : public integral_constant<std::size_t, 0> { };
395 template<typename _Tp, std::size_t _Size>
396 struct rank<_Tp[_Size]>
397 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
399 template<typename _Tp>
401 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
403 template<typename, unsigned>
405 : public integral_constant<std::size_t, 0> { };
407 template<typename _Tp, unsigned _Uint, std::size_t _Size>
408 struct extent<_Tp[_Size], _Uint>
409 : public integral_constant<std::size_t,
410 _Uint == 0 ? _Size : extent<_Tp,
414 template<typename _Tp, unsigned _Uint>
415 struct extent<_Tp[], _Uint>
416 : public integral_constant<std::size_t,
417 _Uint == 0 ? 0 : extent<_Tp,
421 /// @brief relationships between types [4.6].
422 template<typename, typename>
424 : public false_type { };
426 template<typename _Tp>
427 struct is_same<_Tp, _Tp>
428 : public true_type { };
430 // See Daveed Vandevoorde explanation in http://tinyurl.com/502f.
431 // Also see Rani Sharoni in http://tinyurl.com/6jvyq.
432 template<typename _Base, typename _Derived,
433 bool = (!__is_union_or_class<_Base>::value
434 || !__is_union_or_class<_Derived>::value
435 || is_same<_Base, _Derived>::value)>
436 struct __is_base_of_helper
437 : public __sfinae_types
440 typedef typename remove_cv<_Base>::type _NoCv_Base;
441 typedef typename remove_cv<_Derived>::type _NoCv_Derived;
443 template<typename _Up>
444 static __one __test(_NoCv_Derived&, _Up);
445 static __two __test(_NoCv_Base&, int);
449 operator _NoCv_Derived&();
450 operator _NoCv_Base&() const;
454 static const bool __value = sizeof(__test(_Conv(), 0)) == 1;
457 template<typename _Base, typename _Derived>
458 struct __is_base_of_helper<_Base, _Derived, true>
459 { static const bool __value = is_same<_Base, _Derived>::value; };
461 template<typename _Base, typename _Derived>
463 : public integral_constant<bool,
464 __is_base_of_helper<_Base, _Derived>::__value>
467 template<typename _From, typename _To>
468 struct __is_convertible_simple
469 : public __sfinae_types
472 static __one __test(_To);
473 static __two __test(...);
474 static _From __makeFrom();
477 static const bool __value = sizeof(__test(__makeFrom())) == 1;
480 template<typename _Tp>
481 struct __is_int_or_cref
483 typedef typename remove_reference<_Tp>::type __rr_Tp;
484 static const bool __value = (is_integral<_Tp>::value
485 || (is_integral<__rr_Tp>::value
486 && is_const<__rr_Tp>::value
487 && !is_volatile<__rr_Tp>::value));
490 template<typename _From, typename _To,
491 bool = (is_void<_From>::value || is_void<_To>::value
492 || is_function<_To>::value || is_array<_To>::value
493 // This special case is here only to avoid warnings.
494 || (is_floating_point<typename
495 remove_reference<_From>::type>::value
496 && __is_int_or_cref<_To>::__value))>
497 struct __is_convertible_helper
499 // "An imaginary lvalue of type From...".
500 static const bool __value = (__is_convertible_simple<typename
501 add_reference<_From>::type, _To>::__value);
504 template<typename _From, typename _To>
505 struct __is_convertible_helper<_From, _To, true>
506 { static const bool __value = (is_void<_To>::value
507 || (__is_int_or_cref<_To>::__value
508 && !is_void<_From>::value)); };
510 template<typename _From, typename _To>
511 struct is_convertible
512 : public integral_constant<bool,
513 __is_convertible_helper<_From, _To>::__value>
516 /// @brief const-volatile modifications [4.7.1].
517 template<typename _Tp>
519 { typedef _Tp type; };
521 template<typename _Tp>
522 struct remove_const<_Tp const>
523 { typedef _Tp type; };
525 template<typename _Tp>
526 struct remove_volatile
527 { typedef _Tp type; };
529 template<typename _Tp>
530 struct remove_volatile<_Tp volatile>
531 { typedef _Tp type; };
533 template<typename _Tp>
537 remove_const<typename remove_volatile<_Tp>::type>::type type;
540 template<typename _Tp>
542 { typedef _Tp const type; };
544 template<typename _Tp>
546 { typedef _Tp volatile type; };
548 template<typename _Tp>
552 add_const<typename add_volatile<_Tp>::type>::type type;
555 /// @brief reference modifications [4.7.2].
556 template<typename _Tp>
557 struct remove_reference
558 { typedef _Tp type; };
560 template<typename _Tp>
561 struct remove_reference<_Tp&>
562 { typedef _Tp type; };
564 template<typename _Tp>
566 { typedef _Tp& type; };
568 template<typename _Tp>
569 struct add_reference<_Tp&>
570 { typedef _Tp& type; };
572 /// @brief array modififications [4.7.3].
573 template<typename _Tp>
575 { typedef _Tp type; };
577 template<typename _Tp, std::size_t _Size>
578 struct remove_extent<_Tp[_Size]>
579 { typedef _Tp type; };
581 template<typename _Tp>
582 struct remove_extent<_Tp[]>
583 { typedef _Tp type; };
585 template<typename _Tp>
586 struct remove_all_extents
587 { typedef _Tp type; };
589 template<typename _Tp, std::size_t _Size>
590 struct remove_all_extents<_Tp[_Size]>
591 { typedef typename remove_all_extents<_Tp>::type type; };
593 template<typename _Tp>
594 struct remove_all_extents<_Tp[]>
595 { typedef typename remove_all_extents<_Tp>::type type; };
597 /// @brief pointer modifications [4.7.4].
598 #undef _DEFINE_SPEC_BODY
599 #define _DEFINE_SPEC_BODY(_Value) \
600 { typedef _Tp type; };
602 template<typename _Tp>
603 struct remove_pointer
604 { typedef _Tp type; };
605 _DEFINE_SPEC(1, remove_pointer, _Tp*, false)
607 template<typename _Tp>
609 { typedef typename remove_reference<_Tp>::type* type; };
611 /// @brief other transformations [4.8].
613 // Due to c++/19163 and c++/17743, for the time being we cannot use
614 // the correct, neat implementation :-(
616 // template<std::size_t _Len, std::size_t _Align>
617 // struct aligned_storage
618 // { typedef char type[_Len] __attribute__((__aligned__(_Align))); }
620 // Temporary workaround, useful for Align up to 32:
621 template<std::size_t, std::size_t>
622 struct aligned_storage { };
624 template<std::size_t _Len>
625 struct aligned_storage<_Len, 1>
629 unsigned char __data[_Len];
630 char __align __attribute__((__aligned__(1)));
634 template<std::size_t _Len>
635 struct aligned_storage<_Len, 2>
639 unsigned char __data[_Len];
640 char __align __attribute__((__aligned__(2)));
644 template<std::size_t _Len>
645 struct aligned_storage<_Len, 4>
649 unsigned char __data[_Len];
650 char __align __attribute__((__aligned__(4)));
654 template<std::size_t _Len>
655 struct aligned_storage<_Len, 8>
659 unsigned char __data[_Len];
660 char __align __attribute__((__aligned__(8)));
664 template<std::size_t _Len>
665 struct aligned_storage<_Len, 16>
669 unsigned char __data[_Len];
670 char __align __attribute__((__aligned__(16)));
674 template<std::size_t _Len>
675 struct aligned_storage<_Len, 32>
679 unsigned char __data[_Len];
680 char __align __attribute__((__aligned__(32)));
684 #undef _DEFINE_SPEC_0_HELPER
685 #undef _DEFINE_SPEC_1_HELPER
686 #undef _DEFINE_SPEC_2_HELPER
688 #undef _DEFINE_SPEC_BODY