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 32namespace detail { 33 34struct __select_types 35{ 36 typedef char __t1; 37 struct __t2 38 { 39 char __two[2]; 40 }; 41}; 42 43template <class _Tp> 44struct __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 64template <class _Tp> 65const bool __instance<_Tp>::__value = sizeof(__instance<_Tp>::__test<_Tp>(0)) == sizeof(__select_types::__t1); 66#endif 67 68template <class T> 69struct __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 88template <class T> 89const bool __uoc_aux<T>::__value = sizeof(__uoc_aux<T>::__test<T>(0)) == sizeof(__select_types::__t1); 90#endif 91 92template <class T> 93class __empty 94{ }; 95 96template <class T, bool B> 97class __inheritance_aux 98{}; 99 100template <class T> 101class __inheritance_aux<T,true> : 102 public T 103{ 104 public: 105 virtual ~__inheritance_aux() 106 { } 107}; 108 109#if 0 110template <class T, bool B> 111struct __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 122template <class T, bool B> 123const bool __virtual_aux<T,B>::__value = B ? (sizeof(__inheritance_aux<T,B>) == sizeof(T)) : false; 124#endif 125#endif 126 127} // namespace detail 128 129template <class _Tp, _Tp __v> 130struct 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 139typedef integral_constant<bool, true> true_type; 140typedef integral_constant<bool, false> false_type; 141 142namespace detail { 143 144template <typename _Tp> 145struct __is_union_or_class : 146 public integral_constant<bool, __uoc_aux<_Tp>::__value> 147{ }; 148 149#if 0 150template<typename _Tp> 151struct __is_vtbl : // has virtual table? 152 public integral_constant<bool, __virtual_aux<_Tp,__is_union_or_class<_Tp>::value >::__value> 153{ }; 154#endif 155 156template <typename _Tp> 157struct __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) \ 164template <> \ 165struct 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) \ 176template <class _Tp> \ 177struct 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) \ 188template <class _Tp1, class _Tp2> \ 189struct 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 201template <class _Tp> 202struct is_void : 203 public false_type 204{ }; 205 206template <> 207struct is_void<void> : 208 public true_type 209{ }; 210 211template <class _Tp> 212struct 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 230template <class _Tp> 231struct 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 239template <class _Tp> 240struct is_array : 241 public false_type 242{ }; 243 244template <class _Tp, std::size_t _Sz> 245struct is_array<_Tp[_Sz]> : 246 public true_type 247{ }; 248 249template <class _Tp> 250struct is_array<_Tp[]> : 251 public true_type 252{ }; 253 254template <class _Tp> 255struct is_pointer : 256 public false_type 257{ }; 258 259__CV_SPEC_1(is_pointer,_Tp *,true); 260 261template <class _Tp> 262struct is_lvalue_reference : 263 public false_type 264{ }; 265 266template <class _Tp> 267struct is_lvalue_reference<_Tp&> : 268 public true_type 269{ }; 270 271template <class _Tp> 272struct 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 281template <class _Tp> 282struct is_reference : 283 public false_type 284{ }; 285 286template <class _Tp> 287struct is_reference<_Tp&> : 288 public true_type 289{ }; 290 291template <class _Tp> 292struct 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 299template <class _Tp> 300struct is_member_object_pointer : 301 public false_type 302{ }; 303 304// _SPEC_FULL2(is_member_object_pointer, _Tp1 _Tp2::*,!is_function<_Tp1>::value); 305 306template <class _Tp1, class _Tp2> 307struct is_member_object_pointer<_Tp1 _Tp2::*> : 308 public integral_constant<bool, !is_function<_Tp1>::value> 309{ }; 310 311template <class _Tp1, class _Tp2> 312struct is_member_object_pointer<_Tp1 _Tp2::* const> : 313 public integral_constant<bool, !is_function<_Tp1>::value> 314{ }; 315 316template <class _Tp1, class _Tp2> 317struct is_member_object_pointer<_Tp1 _Tp2::* volatile> : 318 public integral_constant<bool, !is_function<_Tp1>::value> 319{ }; 320 321template <class _Tp1, class _Tp2> 322struct is_member_object_pointer<_Tp1 _Tp2::* const volatile> : 323 public integral_constant<bool, !is_function<_Tp1>::value> 324{ }; 325 326template <class _Tp> 327struct is_member_function_pointer : 328 public false_type 329{ }; 330 331// _SPEC_FULL2(is_member_function_pointer,_Tp1 _Tp2::*,is_function<_Tp1>::value); 332 333template <class _Tp1, class _Tp2> 334struct is_member_function_pointer<_Tp1 _Tp2::*> : 335 public integral_constant<bool, is_function<_Tp1>::value> 336{ }; 337 338template <class _Tp1, class _Tp2> 339struct is_member_function_pointer<_Tp1 _Tp2::* const> : 340 public integral_constant<bool, is_function<_Tp1>::value> 341{ }; 342 343template <class _Tp1, class _Tp2> 344struct is_member_function_pointer<_Tp1 _Tp2::* volatile> : 345 public integral_constant<bool, is_function<_Tp1>::value> 346{ }; 347 348template <class _Tp1, class _Tp2> 349struct is_member_function_pointer<_Tp1 _Tp2::* const volatile> : 350 public integral_constant<bool, is_function<_Tp1>::value> 351{ }; 352 353template <class _Tp> 354struct 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 360template <class _Tp> 361struct is_arithmetic : 362 public integral_constant<bool, (is_integral<_Tp>::value || is_floating_point<_Tp>::value)> 363{ }; 364 365template <class _Tp> 366struct 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 372template <class _Tp> 373struct 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 383template <class T> 384struct is_union 385{ }; 386 387template <class T> 388struct 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 398template <class _Tp> 399struct 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 407template <class _Tp> 408struct 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 415template <class _Tp> 416struct 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 424template <class _Tp> 425struct is_const : 426 public false_type 427{ }; 428 429template <class _Tp> 430struct is_const<_Tp const> : 431 public true_type 432{ }; 433 434template <class _Tp> 435struct is_volatile : 436 public false_type 437{ }; 438 439template <class _Tp> 440struct is_volatile<_Tp volatile> : 441 public true_type 442{ }; 443 444 445// 4.7.3 array modifications: 446 447template <class _Tp> 448struct remove_extent 449{ 450 typedef _Tp type; 451}; 452 453template <class _Tp, std::size_t _Sz> 454struct remove_extent<_Tp[_Sz]> 455{ 456 typedef _Tp type; 457}; 458 459template <class _Tp> 460struct remove_extent<_Tp[]> 461{ 462 typedef _Tp type; 463}; 464 465template <class _Tp> 466struct remove_all_extents 467{ 468 typedef _Tp type; 469}; 470 471template <class _Tp, std::size_t _Size> 472struct remove_all_extents<_Tp[_Size]> 473{ 474 typedef typename remove_all_extents<_Tp>::type type; 475}; 476 477template<typename _Tp> 478struct remove_all_extents<_Tp[]> 479{ 480 typedef typename remove_all_extents<_Tp>::type type; 481}; 482 483// 4.5.3 type properties (continued): 484 485template <class _Tp> 486struct is_trivial : 487 public integral_constant<bool, (is_void<_Tp>::value 488 || is_scalar<typename remove_all_extents<_Tp>::type>::value)> 489{ }; 490 491template <class _Tp> 492struct is_standard_layout : 493 public integral_constant<bool, (is_void<_Tp>::value 494 || is_scalar<typename remove_all_extents<_Tp>::type>::value)> 495{ }; 496 497template <class _Tp> 498struct is_pod : 499 public integral_constant<bool, (is_void<_Tp>::value 500 || is_scalar<typename remove_all_extents<_Tp>::type>::value)> 501{ }; 502 503template<typename _Tp> 504struct 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 512template <class _Tp> 513struct has_trivial_constructor : 514 public integral_constant<bool, is_pod<_Tp>::value> 515{ }; 516 517template <class _Tp> 518struct has_trivial_copy : 519 public integral_constant<bool, is_pod<_Tp>::value> 520{ }; 521 522template <class _Tp> 523struct has_trivial_assign : 524 public integral_constant<bool, is_pod<_Tp>::value> 525{ }; 526 527template <class _Tp> 528struct has_trivial_destructor : 529 public integral_constant<bool, is_pod<_Tp>::value> 530{ }; 531 532template <class _Tp> 533struct has_nothrow_constructor : 534 public integral_constant<bool, is_pod<_Tp>::value> 535{ }; 536 537template <class _Tp> 538struct has_nothrow_copy : 539 public integral_constant<bool, is_pod<_Tp>::value> 540{ }; 541 542template <class _Tp> 543struct has_nothrow_assign : 544 public integral_constant<bool, is_pod<_Tp>::value> 545{ }; 546 547template <class _Tp> 548struct has_virtual_destructor : 549 public false_type 550{ }; 551 552template <class _Tp> 553struct 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 563template <class _Tp> 564struct 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 580template <class _Tp1, class _Tp2> 581struct is_same : 582 public false_type 583{ }; 584 585template <class _Tp> 586struct 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 595template <class _Tp> 596struct remove_const 597{ 598 typedef _Tp type; 599}; 600 601template <class _Tp> 602struct remove_const<_Tp const> 603{ 604 typedef _Tp type; 605}; 606 607template <class _Tp> 608struct remove_volatile 609{ 610 typedef _Tp type; 611}; 612 613template <class _Tp> 614struct remove_volatile<_Tp volatile> 615{ 616 typedef _Tp type; 617}; 618 619template <class _Tp> 620struct remove_cv 621{ 622 typedef typename remove_const<typename remove_volatile<_Tp>::type>::type type; 623}; 624 625template <class _Tp> 626struct add_const 627{ 628 typedef _Tp const type; 629}; 630 631template <class _Tp> 632struct add_volatile 633{ 634 typedef _Tp volatile type; 635}; 636 637template <class _Tp> 638struct add_cv 639{ 640 typedef typename add_const<typename add_volatile<_Tp>::type>::type type; 641}; 642 643// 4.7.2 reference modifications: 644 645template <class _Tp> 646struct remove_reference 647{ 648 typedef _Tp type; 649}; 650 651template <class _Tp> 652struct remove_reference<_Tp&> 653{ 654 typedef _Tp type; 655}; 656 657template <class _Tp> 658struct add_reference 659{ 660 typedef _Tp& type; 661}; 662 663template <class _Tp> 664struct 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 673template <class _Tp> 674struct remove_pointer 675{ 676 typedef _Tp type; 677}; 678 679template <class _Tp> 680struct remove_pointer<_Tp *> 681{ 682 typedef _Tp type; 683}; 684 685template <class _Tp> 686struct remove_pointer<_Tp * const> 687{ 688 typedef _Tp type; 689}; 690 691template <class _Tp> 692struct remove_pointer<_Tp * volatile> 693{ 694 typedef _Tp type; 695}; 696 697template <class _Tp> 698struct remove_pointer<_Tp * const volatile> 699{ 700 typedef _Tp type; 701}; 702 703template <class _Tp> 704struct 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 714namespace detail { 715 716template <bool,class _U> 717struct _decay_aux2 718{ 719 typedef typename remove_cv<_U>::type type; 720}; 721 722template <class _U> 723struct _decay_aux2<true,_U> 724{ 725 typedef typename add_pointer<_U>::type type; 726}; 727 728template <bool, class _U> 729struct _decay_aux1 730{ 731 typedef typename _decay_aux2<is_function<_U>::value,_U>::type type; 732}; 733 734template <class _U> 735struct _decay_aux1<true,_U> 736{ 737 typedef typename remove_extent<_U>::type* type; 738}; 739 740} // namespace detail 741 742template <class _Tp> 743class 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 752template <bool, class _Tp = void> 753struct enable_if 754{ 755}; 756 757template <class _Tp> 758struct enable_if<true,_Tp> 759{ 760 typedef _Tp type; 761}; 762 763template <bool, class _Tp1, class _Tp2> 764struct conditional 765{ 766 typedef _Tp2 type; 767}; 768 769template <class _Tp1, class _Tp2> 770struct 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