1// TR1 type_traits -*- C++ -*- 2 3// Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. 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 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, 19// 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 tr1/type_traits 31 * This is a TR1 C++ Library header. 32 */ 33 34#ifndef _TR1_TYPE_TRAITS 35#define _TR1_TYPE_TRAITS 1 36 37#include <bits/c++config.h> 38#include <tr1/type_traits_fwd.h> 39 40// namespace std::tr1 41namespace std 42{ 43_GLIBCXX_BEGIN_NAMESPACE(tr1) 44 45 // For use in __in_array and elsewhere. 46 struct __sfinae_types 47 { 48 typedef char __one; 49 typedef struct { char __arr[2]; } __two; 50 }; 51 52 template<typename _Tp> 53 struct __in_array 54 : public __sfinae_types 55 { 56 private: 57 template<typename _Up> 58 static __one __test(_Up(*)[1]); 59 template<typename> 60 static __two __test(...); 61 62 public: 63 static const bool __value = sizeof(__test<_Tp>(0)) == 1; 64 }; 65 66#define _DEFINE_SPEC_BODY(_Value) \ 67 : public integral_constant<bool, _Value> { }; 68 69#define _DEFINE_SPEC_0_HELPER(_Spec, _Value) \ 70 template<> \ 71 struct _Spec \ 72 _DEFINE_SPEC_BODY(_Value) 73 74#define _DEFINE_SPEC_1_HELPER(_Spec, _Value) \ 75 template<typename _Tp> \ 76 struct _Spec \ 77 _DEFINE_SPEC_BODY(_Value) 78 79#define _DEFINE_SPEC_2_HELPER(_Spec, _Value) \ 80 template<typename _Tp, typename _Cp> \ 81 struct _Spec \ 82 _DEFINE_SPEC_BODY(_Value) 83 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) 89 90 /// @brief helper classes [4.3]. 91 template<typename _Tp, _Tp __v> 92 struct integral_constant 93 { 94 static const _Tp value = __v; 95 typedef _Tp value_type; 96 typedef integral_constant<_Tp, __v> type; 97 }; 98 typedef integral_constant<bool, true> true_type; 99 typedef integral_constant<bool, false> false_type; 100 101 template<typename _Tp, _Tp __v> 102 const _Tp integral_constant<_Tp, __v>::value; 103 104 /// @brief primary type categories [4.5.1]. 105 template<typename> 106 struct is_void 107 : public false_type { }; 108 _DEFINE_SPEC(0, is_void, void, true) 109 110 template<typename> 111 struct is_integral 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) 119#endif 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) 128 129 template<typename> 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) 135 136 template<typename> 137 struct is_array 138 : public false_type { }; 139 140 template<typename _Tp, std::size_t _Size> 141 struct is_array<_Tp[_Size]> 142 : public true_type { }; 143 144 template<typename _Tp> 145 struct is_array<_Tp[]> 146 : public true_type { }; 147 148 template<typename> 149 struct is_pointer 150 : public false_type { }; 151 _DEFINE_SPEC(1, is_pointer, _Tp*, true) 152 153 template<typename> 154 struct is_reference 155 : public false_type { }; 156 157 template<typename _Tp> 158 struct is_reference<_Tp&> 159 : public true_type { }; 160 161 template<typename> 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) 166 167 template<typename> 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) 172 173 template<typename _Tp> 174 struct is_enum 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)> 182 { }; 183 184 template<typename> 185 struct is_union { }; 186 187 template<typename> 188 struct is_class { }; 189 190 template<typename _Tp> 191 struct is_function 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)> 196 { }; 197 198 /// @brief composite type traits [4.5.2]. 199 template<typename _Tp> 200 struct is_arithmetic 201 : public integral_constant<bool, (is_integral<_Tp>::value 202 || is_floating_point<_Tp>::value)> 203 { }; 204 205 template<typename _Tp> 206 struct is_fundamental 207 : public integral_constant<bool, (is_arithmetic<_Tp>::value 208 || is_void<_Tp>::value)> 209 { }; 210 211 template<typename _Tp> 212 struct is_object 213 : public integral_constant<bool, !(is_function<_Tp>::value 214 || is_reference<_Tp>::value 215 || is_void<_Tp>::value)> 216 { }; 217 218 template<typename _Tp> 219 struct is_scalar 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)> 224 { }; 225 226 template<typename _Tp> 227 struct is_compound 228 : public integral_constant<bool, !is_fundamental<_Tp>::value> { }; 229 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)> 235 { }; 236 237 template<typename _Tp> 238 struct __is_union_or_class_helper 239 : public __sfinae_types 240 { 241 private: 242 template<typename _Up> 243 static __one __test(int _Up::*); 244 template<typename> 245 static __two __test(...); 246 247 public: 248 static const bool __value = sizeof(__test<_Tp>(0)) == 1; 249 }; 250 251 // Extension. 252 template<typename _Tp> 253 struct __is_union_or_class 254 : public integral_constant<bool, __is_union_or_class_helper<_Tp>::__value> 255 { }; 256 257 /// @brief type properties [4.5.3]. 258 template<typename> 259 struct is_const 260 : public false_type { }; 261 262 template<typename _Tp> 263 struct is_const<_Tp const> 264 : public true_type { }; 265 266 template<typename> 267 struct is_volatile 268 : public false_type { }; 269 270 template<typename _Tp> 271 struct is_volatile<_Tp volatile> 272 : public true_type { }; 273 274 template<typename _Tp> 275 struct is_pod 276 : public integral_constant<bool, (is_void<_Tp>::value 277 || is_scalar<typename 278 remove_all_extents<_Tp>::type>::value)> 279 { }; 280 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 285 { 286 private: 287 template<typename> 288 struct __first { }; 289 template<typename _Up> 290 struct __second 291 : public _Up { }; 292 293 public: 294 static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>); 295 }; 296 297 template<typename _Tp> 298 struct __is_empty_helper<_Tp, true> 299 { static const bool __value = false; }; 300 301 template<typename _Tp> 302 struct is_empty 303 : public integral_constant<bool, __is_empty_helper<_Tp>::__value> 304 { }; 305 306 template<typename _Tp, bool = !__is_union_or_class<_Tp>::value> 307 struct __is_polymorphic_helper 308 { 309 private: 310 template<typename _Up> 311 struct __first 312 : public _Up { }; 313 template<typename _Up> 314 struct __second 315 : public _Up 316 { 317 virtual void __dummy(); 318 virtual ~__second() throw(); 319 }; 320 321 public: 322 static const bool __value = sizeof(__first<_Tp>) == sizeof(__second<_Tp>); 323 }; 324 325 template<typename _Tp> 326 struct __is_polymorphic_helper<_Tp, true> 327 { static const bool __value = false; }; 328 329 template<typename _Tp> 330 struct is_polymorphic 331 : public integral_constant<bool, __is_polymorphic_helper<_Tp>::__value> 332 { }; 333 334 // Exploit the resolution DR core/337. 335 template<typename _Tp> 336 struct is_abstract 337 : public integral_constant<bool, (!__in_array<_Tp>::__value 338 && __is_union_or_class<_Tp>::value)> { }; 339 340 template<typename _Tp> 341 struct has_trivial_constructor 342 : public integral_constant<bool, is_pod<_Tp>::value> { }; 343 344 template<typename _Tp> 345 struct has_trivial_copy 346 : public integral_constant<bool, is_pod<_Tp>::value> { }; 347 348 template<typename _Tp> 349 struct has_trivial_assign 350 : public integral_constant<bool, is_pod<_Tp>::value> { }; 351 352 template<typename _Tp> 353 struct has_trivial_destructor 354 : public integral_constant<bool, is_pod<_Tp>::value> { }; 355 356 template<typename _Tp> 357 struct has_nothrow_constructor 358 : public integral_constant<bool, is_pod<_Tp>::value> { }; 359 360 template<typename _Tp> 361 struct has_nothrow_copy 362 : public integral_constant<bool, is_pod<_Tp>::value> { }; 363 364 template<typename _Tp> 365 struct has_nothrow_assign 366 : public integral_constant<bool, is_pod<_Tp>::value> { }; 367 368 template<typename> 369 struct has_virtual_destructor 370 : public false_type { }; 371 372 template<typename> 373 struct is_signed 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) 380 381 template<typename> 382 struct is_unsigned 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) 389 390 template<typename _Tp> 391 struct alignment_of 392 : public integral_constant<std::size_t, __alignof__(_Tp)> { }; 393 394 template<typename> 395 struct rank 396 : public integral_constant<std::size_t, 0> { }; 397 398 template<typename _Tp, std::size_t _Size> 399 struct rank<_Tp[_Size]> 400 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { }; 401 402 template<typename _Tp> 403 struct rank<_Tp[]> 404 : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { }; 405 406 template<typename, unsigned> 407 struct extent 408 : public integral_constant<std::size_t, 0> { }; 409 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, 414 _Uint - 1>::value> 415 { }; 416 417 template<typename _Tp, unsigned _Uint> 418 struct extent<_Tp[], _Uint> 419 : public integral_constant<std::size_t, 420 _Uint == 0 ? 0 : extent<_Tp, 421 _Uint - 1>::value> 422 { }; 423 424 /// @brief relationships between types [4.6]. 425 template<typename, typename> 426 struct is_same 427 : public false_type { }; 428 429 template<typename _Tp> 430 struct is_same<_Tp, _Tp> 431 : public true_type { }; 432 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 441 { 442 private: 443 typedef typename remove_cv<_Base>::type _NoCv_Base; 444 typedef typename remove_cv<_Derived>::type _NoCv_Derived; 445 446 template<typename _Up> 447 static __one __test(_NoCv_Derived&, _Up); 448 static __two __test(_NoCv_Base&, int); 449 450 struct _Conv 451 { 452 operator _NoCv_Derived&(); 453 operator _NoCv_Base&() const; 454 }; 455 456 public: 457 static const bool __value = sizeof(__test(_Conv(), 0)) == 1; 458 }; 459 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; }; 463 464 template<typename _Base, typename _Derived> 465 struct is_base_of 466 : public integral_constant<bool, 467 __is_base_of_helper<_Base, _Derived>::__value> 468 { }; 469 470 template<typename _From, typename _To> 471 struct __is_convertible_simple 472 : public __sfinae_types 473 { 474 private: 475 static __one __test(_To); 476 static __two __test(...); 477 static _From __makeFrom(); 478 479 public: 480 static const bool __value = sizeof(__test(__makeFrom())) == 1; 481 }; 482 483 template<typename _Tp> 484 struct __is_int_or_cref 485 { 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)); 491 }; 492 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 501 { 502 // "An imaginary lvalue of type From...". 503 static const bool __value = (__is_convertible_simple<typename 504 add_reference<_From>::type, _To>::__value); 505 }; 506 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)); }; 512 513 template<typename _From, typename _To> 514 struct is_convertible 515 : public integral_constant<bool, 516 __is_convertible_helper<_From, _To>::__value> 517 { }; 518 519 /// @brief const-volatile modifications [4.7.1]. 520 template<typename _Tp> 521 struct remove_const 522 { typedef _Tp type; }; 523 524 template<typename _Tp> 525 struct remove_const<_Tp const> 526 { typedef _Tp type; }; 527 528 template<typename _Tp> 529 struct remove_volatile 530 { typedef _Tp type; }; 531 532 template<typename _Tp> 533 struct remove_volatile<_Tp volatile> 534 { typedef _Tp type; }; 535 536 template<typename _Tp> 537 struct remove_cv 538 { 539 typedef typename 540 remove_const<typename remove_volatile<_Tp>::type>::type type; 541 }; 542 543 template<typename _Tp> 544 struct add_const 545 { typedef _Tp const type; }; 546 547 template<typename _Tp> 548 struct add_volatile 549 { typedef _Tp volatile type; }; 550 551 template<typename _Tp> 552 struct add_cv 553 { 554 typedef typename 555 add_const<typename add_volatile<_Tp>::type>::type type; 556 }; 557 558 /// @brief reference modifications [4.7.2]. 559 template<typename _Tp> 560 struct remove_reference 561 { typedef _Tp type; }; 562 563 template<typename _Tp> 564 struct remove_reference<_Tp&> 565 { typedef _Tp type; }; 566 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; }; 572 573 template<typename _Tp> 574 struct __add_reference_helper<_Tp, true> 575 { typedef _Tp type; }; 576 577 template<typename _Tp> 578 struct add_reference 579 : public __add_reference_helper<_Tp> 580 { }; 581 582 /// @brief array modifications [4.7.3]. 583 template<typename _Tp> 584 struct remove_extent 585 { typedef _Tp type; }; 586 587 template<typename _Tp, std::size_t _Size> 588 struct remove_extent<_Tp[_Size]> 589 { typedef _Tp type; }; 590 591 template<typename _Tp> 592 struct remove_extent<_Tp[]> 593 { typedef _Tp type; }; 594 595 template<typename _Tp> 596 struct remove_all_extents 597 { typedef _Tp type; }; 598 599 template<typename _Tp, std::size_t _Size> 600 struct remove_all_extents<_Tp[_Size]> 601 { typedef typename remove_all_extents<_Tp>::type type; }; 602 603 template<typename _Tp> 604 struct remove_all_extents<_Tp[]> 605 { typedef typename remove_all_extents<_Tp>::type type; }; 606 607 /// @brief pointer modifications [4.7.4]. 608#undef _DEFINE_SPEC_BODY 609#define _DEFINE_SPEC_BODY(_Value) \ 610 { typedef _Tp type; }; 611 612 template<typename _Tp> 613 struct remove_pointer 614 { typedef _Tp type; }; 615 _DEFINE_SPEC(1, remove_pointer, _Tp*, false) 616 617 template<typename _Tp> 618 struct add_pointer 619 { typedef typename remove_reference<_Tp>::type* type; }; 620 621 /// @brief other transformations [4.8]. 622 623 // Due to c++/19163 and c++/17743, for the time being we cannot use 624 // the correct, neat implementation :-( 625 // 626 // template<std::size_t _Len, std::size_t _Align> 627 // struct aligned_storage 628 // { typedef char type[_Len] __attribute__((__aligned__(_Align))); } 629 // 630 // Temporary workaround, useful for Align up to 32: 631 template<std::size_t, std::size_t> 632 struct aligned_storage { }; 633 634 template<std::size_t _Len> 635 struct aligned_storage<_Len, 1> 636 { 637 union type 638 { 639 unsigned char __data[_Len]; 640 char __align __attribute__((__aligned__(1))); 641 }; 642 }; 643 644 template<std::size_t _Len> 645 struct aligned_storage<_Len, 2> 646 { 647 union type 648 { 649 unsigned char __data[_Len]; 650 char __align __attribute__((__aligned__(2))); 651 }; 652 }; 653 654 template<std::size_t _Len> 655 struct aligned_storage<_Len, 4> 656 { 657 union type 658 { 659 unsigned char __data[_Len]; 660 char __align __attribute__((__aligned__(4))); 661 }; 662 }; 663 664 template<std::size_t _Len> 665 struct aligned_storage<_Len, 8> 666 { 667 union type 668 { 669 unsigned char __data[_Len]; 670 char __align __attribute__((__aligned__(8))); 671 }; 672 }; 673 674 template<std::size_t _Len> 675 struct aligned_storage<_Len, 16> 676 { 677 union type 678 { 679 unsigned char __data[_Len]; 680 char __align __attribute__((__aligned__(16))); 681 }; 682 }; 683 684 template<std::size_t _Len> 685 struct aligned_storage<_Len, 32> 686 { 687 union type 688 { 689 unsigned char __data[_Len]; 690 char __align __attribute__((__aligned__(32))); 691 }; 692 }; 693 694#undef _DEFINE_SPEC_0_HELPER 695#undef _DEFINE_SPEC_1_HELPER 696#undef _DEFINE_SPEC_2_HELPER 697#undef _DEFINE_SPEC 698#undef _DEFINE_SPEC_BODY 699 700_GLIBCXX_END_NAMESPACE 701} 702 703#endif 704