1 // TR1 type_traits -*- C++ -*-
3 // Copyright (C) 2004, 2005, 2006 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.
30 /** @file tr1/type_traits
31 * This is a TR1 C++ Library header.
34 #ifndef _TR1_TYPE_TRAITS
35 #define _TR1_TYPE_TRAITS 1
37 #include <bits/c++config.h>
38 #include <tr1/type_traits_fwd.h>
43 _GLIBCXX_BEGIN_NAMESPACE(tr1)
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 template<typename _Tp, _Tp __v>
102 const _Tp integral_constant<_Tp, __v>::value;
104 /// @brief primary type categories [4.5.1].
107 : public false_type { };
108 _DEFINE_SPEC(0, is_void, void, true)
112 : public false_type { };
113 _DEFINE_SPEC(0, is_integral, bool, true)
114 _DEFINE_SPEC(0, is_integral, char, true)
115 _DEFINE_SPEC(0, is_integral, signed char, true)
116 _DEFINE_SPEC(0, is_integral, unsigned char, true)
117 #ifdef _GLIBCXX_USE_WCHAR_T
118 _DEFINE_SPEC(0, is_integral, wchar_t, true)
120 _DEFINE_SPEC(0, is_integral, short, true)
121 _DEFINE_SPEC(0, is_integral, unsigned short, true)
122 _DEFINE_SPEC(0, is_integral, int, true)
123 _DEFINE_SPEC(0, is_integral, unsigned int, true)
124 _DEFINE_SPEC(0, is_integral, long, true)
125 _DEFINE_SPEC(0, is_integral, unsigned long, true)
126 _DEFINE_SPEC(0, is_integral, long long, true)
127 _DEFINE_SPEC(0, is_integral, unsigned long long, true)
130 struct is_floating_point
131 : public false_type { };
132 _DEFINE_SPEC(0, is_floating_point, float, true)
133 _DEFINE_SPEC(0, is_floating_point, double, true)
134 _DEFINE_SPEC(0, is_floating_point, long double, true)
138 : public false_type { };
140 template<typename _Tp, std::size_t _Size>
141 struct is_array<_Tp[_Size]>
142 : public true_type { };
144 template<typename _Tp>
145 struct is_array<_Tp[]>
146 : public true_type { };
150 : public false_type { };
151 _DEFINE_SPEC(1, is_pointer, _Tp*, true)
155 : public false_type { };
157 template<typename _Tp>
158 struct is_reference<_Tp&>
159 : public true_type { };
162 struct is_member_object_pointer
163 : public false_type { };
164 _DEFINE_SPEC(2, is_member_object_pointer, _Tp _Cp::*,
165 !is_function<_Tp>::value)
168 struct is_member_function_pointer
169 : public false_type { };
170 _DEFINE_SPEC(2, is_member_function_pointer, _Tp _Cp::*,
171 is_function<_Tp>::value)
173 template<typename _Tp>
175 : public integral_constant<bool, !(is_fundamental<_Tp>::value
176 || is_array<_Tp>::value
177 || is_pointer<_Tp>::value
178 || is_reference<_Tp>::value
179 || is_member_pointer<_Tp>::value
180 || is_function<_Tp>::value
181 || __is_union_or_class<_Tp>::value)>
190 template<typename _Tp>
192 : public integral_constant<bool, !(__in_array<_Tp>::__value
193 || __is_union_or_class<_Tp>::value
194 || is_reference<_Tp>::value
195 || is_void<_Tp>::value)>
198 /// @brief composite type traits [4.5.2].
199 template<typename _Tp>
201 : public integral_constant<bool, (is_integral<_Tp>::value
202 || is_floating_point<_Tp>::value)>
205 template<typename _Tp>
206 struct is_fundamental
207 : public integral_constant<bool, (is_arithmetic<_Tp>::value
208 || is_void<_Tp>::value)>
211 template<typename _Tp>
213 : public integral_constant<bool, !(is_function<_Tp>::value
214 || is_reference<_Tp>::value
215 || is_void<_Tp>::value)>
218 template<typename _Tp>
220 : public integral_constant<bool, (is_arithmetic<_Tp>::value
221 || is_enum<_Tp>::value
222 || is_pointer<_Tp>::value
223 || is_member_pointer<_Tp>::value)>
226 template<typename _Tp>
228 : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
230 template<typename _Tp>
231 struct is_member_pointer
232 : public integral_constant<bool,
233 (is_member_object_pointer<_Tp>::value
234 || is_member_function_pointer<_Tp>::value)>
237 template<typename _Tp>
238 struct __is_union_or_class_helper
239 : public __sfinae_types
242 template<typename _Up>
243 static __one __test(int _Up::*);
245 static __two __test(...);
248 static const bool __value = sizeof(__test<_Tp>(0)) == 1;
252 template<typename _Tp>
253 struct __is_union_or_class
254 : public integral_constant<bool, __is_union_or_class_helper<_Tp>::__value>
257 /// @brief type properties [4.5.3].
260 : public false_type { };
262 template<typename _Tp>
263 struct is_const<_Tp const>
264 : public true_type { };
268 : public false_type { };
270 template<typename _Tp>
271 struct is_volatile<_Tp volatile>
272 : public true_type { };
274 template<typename _Tp>
276 : public integral_constant<bool, (is_void<_Tp>::value
277 || is_scalar<typename
278 remove_all_extents<_Tp>::type>::value)>
281 // NB: Without compiler support we cannot tell union from class types,
282 // and is_empty and is_polymorphic don't work at all with the former.
283 template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
284 struct __is_empty_helper
289 template<typename _Up>
294 static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
297 template<typename _Tp>
298 struct __is_empty_helper<_Tp, true>
299 { static const bool __value = false; };
301 template<typename _Tp>
303 : public integral_constant<bool, __is_empty_helper<_Tp>::__value>
306 template<typename _Tp, bool = !__is_union_or_class<_Tp>::value>
307 struct __is_polymorphic_helper
310 template<typename _Up>
313 template<typename _Up>
317 virtual void __dummy();
318 virtual ~__second() throw();
322 static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>);
325 template<typename _Tp>
326 struct __is_polymorphic_helper<_Tp, true>
327 { static const bool __value = false; };
329 template<typename _Tp>
330 struct is_polymorphic
331 : public integral_constant<bool, __is_polymorphic_helper<_Tp>::__value>
334 // Exploit the resolution DR core/337.
335 template<typename _Tp>
337 : public integral_constant<bool, (!__in_array<_Tp>::__value
338 && __is_union_or_class<_Tp>::value)> { };
340 template<typename _Tp>
341 struct has_trivial_constructor
342 : public integral_constant<bool, is_pod<_Tp>::value> { };
344 template<typename _Tp>
345 struct has_trivial_copy
346 : public integral_constant<bool, is_pod<_Tp>::value> { };
348 template<typename _Tp>
349 struct has_trivial_assign
350 : public integral_constant<bool, is_pod<_Tp>::value> { };
352 template<typename _Tp>
353 struct has_trivial_destructor
354 : public integral_constant<bool, is_pod<_Tp>::value> { };
356 template<typename _Tp>
357 struct has_nothrow_constructor
358 : public integral_constant<bool, is_pod<_Tp>::value> { };
360 template<typename _Tp>
361 struct has_nothrow_copy
362 : public integral_constant<bool, is_pod<_Tp>::value> { };
364 template<typename _Tp>
365 struct has_nothrow_assign
366 : public integral_constant<bool, is_pod<_Tp>::value> { };
369 struct has_virtual_destructor
370 : public false_type { };
374 : public false_type { };
375 _DEFINE_SPEC(0, is_signed, signed char, true)
376 _DEFINE_SPEC(0, is_signed, short, true)
377 _DEFINE_SPEC(0, is_signed, int, true)
378 _DEFINE_SPEC(0, is_signed, long, true)
379 _DEFINE_SPEC(0, is_signed, long long, true)
383 : public false_type { };
384 _DEFINE_SPEC(0, is_unsigned, unsigned char, true)
385 _DEFINE_SPEC(0, is_unsigned, unsigned short, true)
386 _DEFINE_SPEC(0, is_unsigned, unsigned int, true)
387 _DEFINE_SPEC(0, is_unsigned, unsigned long, true)
388 _DEFINE_SPEC(0, is_unsigned, unsigned long long, true)
390 template<typename _Tp>
392 : public integral_constant<std::size_t, __alignof__(_Tp)> { };
396 : public integral_constant<std::size_t, 0> { };
398 template<typename _Tp, std::size_t _Size>
399 struct rank<_Tp[_Size]>
400 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
402 template<typename _Tp>
404 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
406 template<typename, unsigned>
408 : public integral_constant<std::size_t, 0> { };
410 template<typename _Tp, unsigned _Uint, std::size_t _Size>
411 struct extent<_Tp[_Size], _Uint>
412 : public integral_constant<std::size_t,
413 _Uint == 0 ? _Size : extent<_Tp,
417 template<typename _Tp, unsigned _Uint>
418 struct extent<_Tp[], _Uint>
419 : public integral_constant<std::size_t,
420 _Uint == 0 ? 0 : extent<_Tp,
424 /// @brief relationships between types [4.6].
425 template<typename, typename>
427 : public false_type { };
429 template<typename _Tp>
430 struct is_same<_Tp, _Tp>
431 : public true_type { };
433 // See Daveed Vandevoorde explanation in http://tinyurl.com/502f.
434 // Also see Rani Sharoni in http://tinyurl.com/6jvyq.
435 template<typename _Base, typename _Derived,
436 bool = (!__is_union_or_class<_Base>::value
437 || !__is_union_or_class<_Derived>::value
438 || is_same<_Base, _Derived>::value)>
439 struct __is_base_of_helper
440 : public __sfinae_types
443 typedef typename remove_cv<_Base>::type _NoCv_Base;
444 typedef typename remove_cv<_Derived>::type _NoCv_Derived;
446 template<typename _Up>
447 static __one __test(_NoCv_Derived&, _Up);
448 static __two __test(_NoCv_Base&, int);
452 operator _NoCv_Derived&();
453 operator _NoCv_Base&() const;
457 static const bool __value = sizeof(__test(_Conv(), 0)) == 1;
460 template<typename _Base, typename _Derived>
461 struct __is_base_of_helper<_Base, _Derived, true>
462 { static const bool __value = is_same<_Base, _Derived>::value; };
464 template<typename _Base, typename _Derived>
466 : public integral_constant<bool,
467 __is_base_of_helper<_Base, _Derived>::__value>
470 template<typename _From, typename _To>
471 struct __is_convertible_simple
472 : public __sfinae_types
475 static __one __test(_To);
476 static __two __test(...);
477 static _From __makeFrom();
480 static const bool __value = sizeof(__test(__makeFrom())) == 1;
483 template<typename _Tp>
484 struct __is_int_or_cref
486 typedef typename remove_reference<_Tp>::type __rr_Tp;
487 static const bool __value = (is_integral<_Tp>::value
488 || (is_integral<__rr_Tp>::value
489 && is_const<__rr_Tp>::value
490 && !is_volatile<__rr_Tp>::value));
493 template<typename _From, typename _To,
494 bool = (is_void<_From>::value || is_void<_To>::value
495 || is_function<_To>::value || is_array<_To>::value
496 // This special case is here only to avoid warnings.
497 || (is_floating_point<typename
498 remove_reference<_From>::type>::value
499 && __is_int_or_cref<_To>::__value))>
500 struct __is_convertible_helper
502 // "An imaginary lvalue of type From...".
503 static const bool __value = (__is_convertible_simple<typename
504 add_reference<_From>::type, _To>::__value);
507 template<typename _From, typename _To>
508 struct __is_convertible_helper<_From, _To, true>
509 { static const bool __value = (is_void<_To>::value
510 || (__is_int_or_cref<_To>::__value
511 && !is_void<_From>::value)); };
513 template<typename _From, typename _To>
514 struct is_convertible
515 : public integral_constant<bool,
516 __is_convertible_helper<_From, _To>::__value>
519 /// @brief const-volatile modifications [4.7.1].
520 template<typename _Tp>
522 { typedef _Tp type; };
524 template<typename _Tp>
525 struct remove_const<_Tp const>
526 { typedef _Tp type; };
528 template<typename _Tp>
529 struct remove_volatile
530 { typedef _Tp type; };
532 template<typename _Tp>
533 struct remove_volatile<_Tp volatile>
534 { typedef _Tp type; };
536 template<typename _Tp>
540 remove_const<typename remove_volatile<_Tp>::type>::type type;
543 template<typename _Tp>
545 { typedef _Tp const type; };
547 template<typename _Tp>
549 { typedef _Tp volatile type; };
551 template<typename _Tp>
555 add_const<typename add_volatile<_Tp>::type>::type type;
558 /// @brief reference modifications [4.7.2].
559 template<typename _Tp>
560 struct remove_reference
561 { typedef _Tp type; };
563 template<typename _Tp>
564 struct remove_reference<_Tp&>
565 { typedef _Tp type; };
567 // NB: Careful with reference to void.
568 template<typename _Tp, bool = (is_void<_Tp>::value
569 || is_reference<_Tp>::value)>
570 struct __add_reference_helper
571 { typedef _Tp& type; };
573 template<typename _Tp>
574 struct __add_reference_helper<_Tp, true>
575 { typedef _Tp type; };
577 template<typename _Tp>
579 : public __add_reference_helper<_Tp>
582 /// @brief array modifications [4.7.3].
583 template<typename _Tp>
585 { typedef _Tp type; };
587 template<typename _Tp, std::size_t _Size>
588 struct remove_extent<_Tp[_Size]>
589 { typedef _Tp type; };
591 template<typename _Tp>
592 struct remove_extent<_Tp[]>
593 { typedef _Tp type; };
595 template<typename _Tp>
596 struct remove_all_extents
597 { typedef _Tp type; };
599 template<typename _Tp, std::size_t _Size>
600 struct remove_all_extents<_Tp[_Size]>
601 { typedef typename remove_all_extents<_Tp>::type type; };
603 template<typename _Tp>
604 struct remove_all_extents<_Tp[]>
605 { typedef typename remove_all_extents<_Tp>::type type; };
607 /// @brief pointer modifications [4.7.4].
608 #undef _DEFINE_SPEC_BODY
609 #define _DEFINE_SPEC_BODY(_Value) \
610 { typedef _Tp type; };
612 template<typename _Tp>
613 struct remove_pointer
614 { typedef _Tp type; };
615 _DEFINE_SPEC(1, remove_pointer, _Tp*, false)
617 template<typename _Tp>
619 { typedef typename remove_reference<_Tp>::type* type; };
621 /// @brief other transformations [4.8].
623 // Due to c++/19163 and c++/17743, for the time being we cannot use
624 // the correct, neat implementation :-(
626 // template<std::size_t _Len, std::size_t _Align>
627 // struct aligned_storage
628 // { typedef char type[_Len] __attribute__((__aligned__(_Align))); }
630 // Temporary workaround, useful for Align up to 32:
631 template<std::size_t, std::size_t>
632 struct aligned_storage { };
634 template<std::size_t _Len>
635 struct aligned_storage<_Len, 1>
639 unsigned char __data[_Len];
640 char __align __attribute__((__aligned__(1)));
644 template<std::size_t _Len>
645 struct aligned_storage<_Len, 2>
649 unsigned char __data[_Len];
650 char __align __attribute__((__aligned__(2)));
654 template<std::size_t _Len>
655 struct aligned_storage<_Len, 4>
659 unsigned char __data[_Len];
660 char __align __attribute__((__aligned__(4)));
664 template<std::size_t _Len>
665 struct aligned_storage<_Len, 8>
669 unsigned char __data[_Len];
670 char __align __attribute__((__aligned__(8)));
674 template<std::size_t _Len>
675 struct aligned_storage<_Len, 16>
679 unsigned char __data[_Len];
680 char __align __attribute__((__aligned__(16)));
684 template<std::size_t _Len>
685 struct aligned_storage<_Len, 32>
689 unsigned char __data[_Len];
690 char __align __attribute__((__aligned__(32)));
694 #undef _DEFINE_SPEC_0_HELPER
695 #undef _DEFINE_SPEC_1_HELPER
696 #undef _DEFINE_SPEC_2_HELPER
698 #undef _DEFINE_SPEC_BODY
700 _GLIBCXX_END_NAMESPACE