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