1 // -*- C++ -*- Time-stamp: <08/07/20 19:10:15 ptr> 2 3 /* 4 * Copyright (c) 2007, 2008 5 * Petr Ovtchenkov 6 * 7 * Licensed under the Academic Free License version 3.0 8 * 9 * Derived from original <misc/type_traits.h> of 'complement' project 10 * [http://complement.sourceforge.net] 11 * to make it close to JTC1/SC22/WG21 C++ 0x working draft 12 * [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf] 13 */ 14 15 #ifndef __STLP_TYPE_TRAITS 16 #define __STLP_TYPE_TRAITS 17 18 #ifndef _STLP_OUTERMOST_HEADER_ID 19 # define _STLP_OUTERMOST_HEADER_ID 0x3 20 # include <stl/_prolog.h> 21 #endif 22 23 // libstdc++ v3, timestamp 20050519 (3.4.4) has __type_traits, 24 // libstdc++ v3, timestamp 20060306 (3.4.6) has __type_traits, 25 // while libstdc++ v3, 20050921 (4.0.2) not; use libstdc++ instead 26 // # if defined(STLPORT) || (defined(__GNUC__) && (__GNUC__ < 4)) /* !defined(__GLIBCXX__) || (defined(__GNUC__) && (__GNUC__ < 4)) */ 27 28 _STLP_BEGIN_NAMESPACE 29 30 _STLP_BEGIN_TR1_NAMESPACE 31 32 namespace detail { 33 34 struct __select_types 35 { 36 typedef char __t1; 37 struct __t2 38 { 39 char __two[2]; 40 }; 41 }; 42 43 template <class _Tp> 44 struct __instance : 45 public __select_types 46 { 47 private: 48 template <class _Up> 49 static __t1 __test(_Up(*)[1]); 50 51 template <class> 52 static __t2 __test(...); 53 54 public: 55 #ifdef _STLP_STATIC_CONST_INIT_BUG 56 static const bool __value; 57 #else 58 static const bool __value = sizeof(__test<_Tp>(0)) == sizeof(__select_types::__t1); 59 #endif 60 61 }; 62 63 #ifdef _STLP_STATIC_CONST_INIT_BUG 64 template <class _Tp> 65 const bool __instance<_Tp>::__value = sizeof(__instance<_Tp>::__test<_Tp>(0)) == sizeof(__select_types::__t1); 66 #endif 67 68 template <class T> 69 struct __uoc_aux : // union or class 70 public __select_types 71 { 72 private: 73 template <class _Up> 74 static __t1 __test( int _Up::* ); 75 76 template <class> 77 static __t2 __test(...); 78 79 public: 80 #ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION 81 static const bool __value; 82 #else 83 static const bool __value = sizeof(__test<T>(0)) == sizeof(__select_types::__t1); 84 #endif 85 }; 86 87 #ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION 88 template <class T> 89 const bool __uoc_aux<T>::__value = sizeof(__uoc_aux<T>::__test<T>(0)) == sizeof(__select_types::__t1); 90 #endif 91 92 template <class T> 93 class __empty 94 { }; 95 96 template <class T, bool B> 97 class __inheritance_aux 98 {}; 99 100 template <class T> 101 class __inheritance_aux<T,true> : 102 public T 103 { 104 public: 105 virtual ~__inheritance_aux() 106 { } 107 }; 108 109 #if 0 110 template <class T, bool B> 111 struct __virtual_aux 112 { 113 public: 114 #ifdef _STLP_STATIC_CONST_INIT_BUG 115 static const bool __value; 116 #else 117 static const bool __value = B ? (sizeof(__inheritance_aux<T,B>) == sizeof(T)) : false; 118 #endif 119 }; 120 121 #ifdef _STLP_STATIC_CONST_INIT_BUG 122 template <class T, bool B> 123 const bool __virtual_aux<T,B>::__value = B ? (sizeof(__inheritance_aux<T,B>) == sizeof(T)) : false; 124 #endif 125 #endif 126 127 } // namespace detail 128 129 template <class _Tp, _Tp __v> 130 struct integral_constant 131 { 132 static const _Tp value = __v; 133 // enum { value = __v }; ? 134 135 typedef _Tp value_type; 136 typedef integral_constant<_Tp, __v> type; 137 }; 138 139 typedef integral_constant<bool, true> true_type; 140 typedef integral_constant<bool, false> false_type; 141 142 namespace detail { 143 144 template <typename _Tp> 145 struct __is_union_or_class : 146 public integral_constant<bool, __uoc_aux<_Tp>::__value> 147 { }; 148 149 #if 0 150 template<typename _Tp> 151 struct __is_vtbl : // has virtual table? 152 public integral_constant<bool, __virtual_aux<_Tp,__is_union_or_class<_Tp>::value >::__value> 153 { }; 154 #endif 155 156 template <typename _Tp> 157 struct __is_vtbl : // has virtual table? 158 public integral_constant<bool, __is_union_or_class<_Tp>::value ? (sizeof(__inheritance_aux<_Tp,__is_union_or_class<_Tp>::value>) == sizeof(_Tp)) : false > 159 { }; 160 161 } // namespace detail 162 163 #define __SPEC_(C,T,B) \ 164 template <> \ 165 struct C<T> : \ 166 public integral_constant<bool, B> \ 167 { } 168 169 #define __CV_SPEC(C,T,B) \ 170 __SPEC_(C,T,B); \ 171 __SPEC_(C,const T,B); \ 172 __SPEC_(C,volatile T,B); \ 173 __SPEC_(C,const volatile T,B) 174 175 #define __SPEC_1(C,T,B) \ 176 template <class _Tp> \ 177 struct C<T> : \ 178 public integral_constant<bool, B> \ 179 { } 180 181 #define __CV_SPEC_1(C,T,B) \ 182 __SPEC_1(C,T,B); \ 183 __SPEC_1(C,T const,B); \ 184 __SPEC_1(C,T volatile,B); \ 185 __SPEC_1(C,T const volatile,B) 186 187 #define __SPEC_2(C,T,B) \ 188 template <class _Tp1, class _Tp2> \ 189 struct C<T> : \ 190 public integral_constant<bool, B> \ 191 { } 192 193 #define __CV_SPEC_2(C,T,B) \ 194 __SPEC_2(C,T,B); \ 195 __SPEC_2(C,T const,B); \ 196 __SPEC_2(C,T volatile,B); \ 197 __SPEC_2(C,T const volatile,B) 198 199 // [4.5.1] primary type categories: 200 201 template <class _Tp> 202 struct is_void : 203 public false_type 204 { }; 205 206 template <> 207 struct is_void<void> : 208 public true_type 209 { }; 210 211 template <class _Tp> 212 struct is_integral : 213 public false_type 214 { }; 215 216 __CV_SPEC(is_integral,bool,true); 217 __CV_SPEC(is_integral,char,true); 218 __CV_SPEC(is_integral,signed char,true); 219 __CV_SPEC(is_integral,unsigned char,true); 220 __CV_SPEC(is_integral,wchar_t,true); 221 __CV_SPEC(is_integral,short,true); 222 __CV_SPEC(is_integral,unsigned short,true); 223 __CV_SPEC(is_integral,int,true); 224 __CV_SPEC(is_integral,unsigned int,true); 225 __CV_SPEC(is_integral,long,true); 226 __CV_SPEC(is_integral,unsigned long,true); 227 __CV_SPEC(is_integral,long long,true); 228 __CV_SPEC(is_integral,unsigned long long,true); 229 230 template <class _Tp> 231 struct is_floating_point : 232 public false_type 233 { }; 234 235 __CV_SPEC(is_floating_point,float,true); 236 __CV_SPEC(is_floating_point,double,true); 237 __CV_SPEC(is_floating_point,long double,true); 238 239 template <class _Tp> 240 struct is_array : 241 public false_type 242 { }; 243 244 template <class _Tp, std::size_t _Sz> 245 struct is_array<_Tp[_Sz]> : 246 public true_type 247 { }; 248 249 template <class _Tp> 250 struct is_array<_Tp[]> : 251 public true_type 252 { }; 253 254 template <class _Tp> 255 struct is_pointer : 256 public false_type 257 { }; 258 259 __CV_SPEC_1(is_pointer,_Tp *,true); 260 261 template <class _Tp> 262 struct is_lvalue_reference : 263 public false_type 264 { }; 265 266 template <class _Tp> 267 struct is_lvalue_reference<_Tp&> : 268 public true_type 269 { }; 270 271 template <class _Tp> 272 struct is_rvalue_reference : 273 public false_type 274 { }; 275 276 // template <class _Tp> 277 // struct is_rvalue_reference<_Tp&&> : 278 // public true_type 279 // { }; 280 281 template <class _Tp> 282 struct is_reference : 283 public false_type 284 { }; 285 286 template <class _Tp> 287 struct is_reference<_Tp&> : 288 public true_type 289 { }; 290 291 template <class _Tp> 292 struct is_function : 293 public integral_constant<bool, !(detail::__instance<_Tp>::__value 294 || detail::__is_union_or_class<_Tp>::value 295 || is_reference<_Tp>::value 296 || is_void<_Tp>::value)> 297 { }; 298 299 template <class _Tp> 300 struct is_member_object_pointer : 301 public false_type 302 { }; 303 304 // _SPEC_FULL2(is_member_object_pointer, _Tp1 _Tp2::*,!is_function<_Tp1>::value); 305 306 template <class _Tp1, class _Tp2> 307 struct is_member_object_pointer<_Tp1 _Tp2::*> : 308 public integral_constant<bool, !is_function<_Tp1>::value> 309 { }; 310 311 template <class _Tp1, class _Tp2> 312 struct is_member_object_pointer<_Tp1 _Tp2::* const> : 313 public integral_constant<bool, !is_function<_Tp1>::value> 314 { }; 315 316 template <class _Tp1, class _Tp2> 317 struct is_member_object_pointer<_Tp1 _Tp2::* volatile> : 318 public integral_constant<bool, !is_function<_Tp1>::value> 319 { }; 320 321 template <class _Tp1, class _Tp2> 322 struct is_member_object_pointer<_Tp1 _Tp2::* const volatile> : 323 public integral_constant<bool, !is_function<_Tp1>::value> 324 { }; 325 326 template <class _Tp> 327 struct is_member_function_pointer : 328 public false_type 329 { }; 330 331 // _SPEC_FULL2(is_member_function_pointer,_Tp1 _Tp2::*,is_function<_Tp1>::value); 332 333 template <class _Tp1, class _Tp2> 334 struct is_member_function_pointer<_Tp1 _Tp2::*> : 335 public integral_constant<bool, is_function<_Tp1>::value> 336 { }; 337 338 template <class _Tp1, class _Tp2> 339 struct is_member_function_pointer<_Tp1 _Tp2::* const> : 340 public integral_constant<bool, is_function<_Tp1>::value> 341 { }; 342 343 template <class _Tp1, class _Tp2> 344 struct is_member_function_pointer<_Tp1 _Tp2::* volatile> : 345 public integral_constant<bool, is_function<_Tp1>::value> 346 { }; 347 348 template <class _Tp1, class _Tp2> 349 struct is_member_function_pointer<_Tp1 _Tp2::* const volatile> : 350 public integral_constant<bool, is_function<_Tp1>::value> 351 { }; 352 353 template <class _Tp> 354 struct is_member_pointer : 355 public integral_constant<bool, (is_member_object_pointer<_Tp>::value || is_member_function_pointer<_Tp>::value)> 356 { }; 357 358 // 4.5.2 composite type categories 359 360 template <class _Tp> 361 struct is_arithmetic : 362 public integral_constant<bool, (is_integral<_Tp>::value || is_floating_point<_Tp>::value)> 363 { }; 364 365 template <class _Tp> 366 struct is_fundamental : 367 public integral_constant<bool, (is_arithmetic<_Tp>::value || is_void<_Tp>::value)> 368 { }; 369 370 // [4.5.1] primary type categories (continued): 371 372 template <class _Tp> 373 struct is_enum : 374 public integral_constant<bool, !(is_fundamental<_Tp>::value 375 || is_array<_Tp>::value 376 || is_pointer<_Tp>::value 377 || is_reference<_Tp>::value 378 || is_member_pointer<_Tp>::value 379 || is_function<_Tp>::value 380 || detail::__is_union_or_class<_Tp>::value) > 381 { }; 382 383 template <class T> 384 struct is_union 385 { }; 386 387 template <class T> 388 struct is_class 389 { }; 390 391 // is_function (above) 392 393 // 4.5.2 composite type categories (continued) 394 395 // is_arithmetic (above) 396 // is_fundamental (above) 397 398 template <class _Tp> 399 struct is_object : 400 public integral_constant<bool, (is_arithmetic<_Tp>::value || 401 is_array<_Tp>::value || 402 is_pointer<_Tp>::value || 403 is_member_pointer<_Tp>::value || 404 detail::__is_union_or_class<_Tp>::value)> 405 { }; 406 407 template <class _Tp> 408 struct is_scalar : 409 public integral_constant<bool, (is_arithmetic<_Tp>::value 410 || is_enum<_Tp>::value 411 || is_pointer<_Tp>::value 412 || is_member_pointer<_Tp>::value)> 413 { }; 414 415 template <class _Tp> 416 struct is_compound : 417 public integral_constant<bool, !is_fundamental<_Tp>::value> 418 { }; 419 420 // is_member_pointer 421 422 // 4.5.3 type properties: 423 424 template <class _Tp> 425 struct is_const : 426 public false_type 427 { }; 428 429 template <class _Tp> 430 struct is_const<_Tp const> : 431 public true_type 432 { }; 433 434 template <class _Tp> 435 struct is_volatile : 436 public false_type 437 { }; 438 439 template <class _Tp> 440 struct is_volatile<_Tp volatile> : 441 public true_type 442 { }; 443 444 445 // 4.7.3 array modifications: 446 447 template <class _Tp> 448 struct remove_extent 449 { 450 typedef _Tp type; 451 }; 452 453 template <class _Tp, std::size_t _Sz> 454 struct remove_extent<_Tp[_Sz]> 455 { 456 typedef _Tp type; 457 }; 458 459 template <class _Tp> 460 struct remove_extent<_Tp[]> 461 { 462 typedef _Tp type; 463 }; 464 465 template <class _Tp> 466 struct remove_all_extents 467 { 468 typedef _Tp type; 469 }; 470 471 template <class _Tp, std::size_t _Size> 472 struct remove_all_extents<_Tp[_Size]> 473 { 474 typedef typename remove_all_extents<_Tp>::type type; 475 }; 476 477 template<typename _Tp> 478 struct remove_all_extents<_Tp[]> 479 { 480 typedef typename remove_all_extents<_Tp>::type type; 481 }; 482 483 // 4.5.3 type properties (continued): 484 485 template <class _Tp> 486 struct is_trivial : 487 public integral_constant<bool, (is_void<_Tp>::value 488 || is_scalar<typename remove_all_extents<_Tp>::type>::value)> 489 { }; 490 491 template <class _Tp> 492 struct is_standard_layout : 493 public integral_constant<bool, (is_void<_Tp>::value 494 || is_scalar<typename remove_all_extents<_Tp>::type>::value)> 495 { }; 496 497 template <class _Tp> 498 struct is_pod : 499 public integral_constant<bool, (is_void<_Tp>::value 500 || is_scalar<typename remove_all_extents<_Tp>::type>::value)> 501 { }; 502 503 template<typename _Tp> 504 struct is_empty 505 : public integral_constant<bool, (detail::__is_union_or_class<_Tp>::value 506 && (sizeof(detail::__empty<_Tp>) == sizeof(_Tp)))> 507 { }; 508 509 // is_polimorphic 510 // is_abstract 511 512 template <class _Tp> 513 struct has_trivial_constructor : 514 public integral_constant<bool, is_pod<_Tp>::value> 515 { }; 516 517 template <class _Tp> 518 struct has_trivial_copy : 519 public integral_constant<bool, is_pod<_Tp>::value> 520 { }; 521 522 template <class _Tp> 523 struct has_trivial_assign : 524 public integral_constant<bool, is_pod<_Tp>::value> 525 { }; 526 527 template <class _Tp> 528 struct has_trivial_destructor : 529 public integral_constant<bool, is_pod<_Tp>::value> 530 { }; 531 532 template <class _Tp> 533 struct has_nothrow_constructor : 534 public integral_constant<bool, is_pod<_Tp>::value> 535 { }; 536 537 template <class _Tp> 538 struct has_nothrow_copy : 539 public integral_constant<bool, is_pod<_Tp>::value> 540 { }; 541 542 template <class _Tp> 543 struct has_nothrow_assign : 544 public integral_constant<bool, is_pod<_Tp>::value> 545 { }; 546 547 template <class _Tp> 548 struct has_virtual_destructor : 549 public false_type 550 { }; 551 552 template <class _Tp> 553 struct is_signed : 554 public false_type 555 { }; 556 557 __CV_SPEC(is_signed,signed char,true); 558 __CV_SPEC(is_signed,short,true); 559 __CV_SPEC(is_signed,int,true); 560 __CV_SPEC(is_signed,long,true); 561 __CV_SPEC(is_signed,long long,true); 562 563 template <class _Tp> 564 struct is_unsigned : 565 public false_type 566 { }; 567 568 __CV_SPEC(is_unsigned,unsigned char,true); 569 __CV_SPEC(is_unsigned,unsigned short,true); 570 __CV_SPEC(is_unsigned,unsigned int,true); 571 __CV_SPEC(is_unsigned,unsigned long,true); 572 __CV_SPEC(is_unsigned,unsigned long long,true); 573 574 // alignment_of 575 // rank 576 // extent 577 578 // 4.6 type relations: 579 580 template <class _Tp1, class _Tp2> 581 struct is_same : 582 public false_type 583 { }; 584 585 template <class _Tp> 586 struct is_same<_Tp, _Tp> : 587 public true_type 588 { }; 589 590 // is_base_of 591 // is_convertible 592 593 // 4.7.1 const-volatile modifications 594 595 template <class _Tp> 596 struct remove_const 597 { 598 typedef _Tp type; 599 }; 600 601 template <class _Tp> 602 struct remove_const<_Tp const> 603 { 604 typedef _Tp type; 605 }; 606 607 template <class _Tp> 608 struct remove_volatile 609 { 610 typedef _Tp type; 611 }; 612 613 template <class _Tp> 614 struct remove_volatile<_Tp volatile> 615 { 616 typedef _Tp type; 617 }; 618 619 template <class _Tp> 620 struct remove_cv 621 { 622 typedef typename remove_const<typename remove_volatile<_Tp>::type>::type type; 623 }; 624 625 template <class _Tp> 626 struct add_const 627 { 628 typedef _Tp const type; 629 }; 630 631 template <class _Tp> 632 struct add_volatile 633 { 634 typedef _Tp volatile type; 635 }; 636 637 template <class _Tp> 638 struct add_cv 639 { 640 typedef typename add_const<typename add_volatile<_Tp>::type>::type type; 641 }; 642 643 // 4.7.2 reference modifications: 644 645 template <class _Tp> 646 struct remove_reference 647 { 648 typedef _Tp type; 649 }; 650 651 template <class _Tp> 652 struct remove_reference<_Tp&> 653 { 654 typedef _Tp type; 655 }; 656 657 template <class _Tp> 658 struct add_reference 659 { 660 typedef _Tp& type; 661 }; 662 663 template <class _Tp> 664 struct add_reference<_Tp&> 665 { 666 typedef _Tp& type; 667 }; 668 669 // 4.7.3 array modifications (see above) 670 671 // 4.7.4 pointer modifications: 672 673 template <class _Tp> 674 struct remove_pointer 675 { 676 typedef _Tp type; 677 }; 678 679 template <class _Tp> 680 struct remove_pointer<_Tp *> 681 { 682 typedef _Tp type; 683 }; 684 685 template <class _Tp> 686 struct remove_pointer<_Tp * const> 687 { 688 typedef _Tp type; 689 }; 690 691 template <class _Tp> 692 struct remove_pointer<_Tp * volatile> 693 { 694 typedef _Tp type; 695 }; 696 697 template <class _Tp> 698 struct remove_pointer<_Tp * const volatile> 699 { 700 typedef _Tp type; 701 }; 702 703 template <class _Tp> 704 struct add_pointer 705 { 706 typedef typename remove_reference<_Tp>::type * type; 707 }; 708 709 // 20.5.7 other transformations: 710 711 // template <std::size_t Len, std::size_t Align> struct aligned_storage; 712 // template <std::size_t Len, class... Types> struct aligned_union; 713 714 namespace detail { 715 716 template <bool,class _U> 717 struct _decay_aux2 718 { 719 typedef typename remove_cv<_U>::type type; 720 }; 721 722 template <class _U> 723 struct _decay_aux2<true,_U> 724 { 725 typedef typename add_pointer<_U>::type type; 726 }; 727 728 template <bool, class _U> 729 struct _decay_aux1 730 { 731 typedef typename _decay_aux2<is_function<_U>::value,_U>::type type; 732 }; 733 734 template <class _U> 735 struct _decay_aux1<true,_U> 736 { 737 typedef typename remove_extent<_U>::type* type; 738 }; 739 740 } // namespace detail 741 742 template <class _Tp> 743 class decay 744 { 745 private: 746 typedef typename remove_reference<_Tp>::type _U; 747 748 public: 749 typedef typename detail::_decay_aux1<is_array<_U>::value,_U>::type type; 750 }; 751 752 template <bool, class _Tp = void> 753 struct enable_if 754 { 755 }; 756 757 template <class _Tp> 758 struct enable_if<true,_Tp> 759 { 760 typedef _Tp type; 761 }; 762 763 template <bool, class _Tp1, class _Tp2> 764 struct conditional 765 { 766 typedef _Tp2 type; 767 }; 768 769 template <class _Tp1, class _Tp2> 770 struct conditional<true,_Tp1,_Tp2> 771 { 772 typedef _Tp1 type; 773 }; 774 775 // template <class... _Tp> struct common_type; 776 777 #undef __CV_SPEC 778 #undef __SPEC_ 779 #undef __CV_SPEC_1 780 #undef __SPEC_1 781 #undef __CV_SPEC_2 782 #undef __SPEC_2 783 784 _STLP_END_NAMESPACE // tr1 785 786 _STLP_END_NAMESPACE 787 788 // # else // __GLIBCXX__ && (__GNUC__ >= 4) && !STLPORT 789 // # include <tr1/type_traits> 790 // # endif 791 792 #if (_STLP_OUTERMOST_HEADER_ID == 0x3) 793 # include <stl/_epilog.h> 794 # undef _STLP_OUTERMOST_HEADER_ID 795 #endif 796 797 #endif // __STLP_TYPE_TRAITS 798 799