CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
00001 // ====================================================================== 00002 // 00003 // Test basic functionality of primary type traits 00004 // 00005 // Author: W. E. Brown, 2010-03-27, adapted in part from the boost 00006 // library's type_traits and related functionality whose internal 00007 // attributions bear the following various notices: 00008 // 00009 // (C) Copyright John Maddock 2000. 00010 // Distributed under the Boost Software License, Version 1.0. 00011 // See http://www.boost.org/LICENSE_1_0.txt 00012 // 00013 // ====================================================================== 00014 00015 00016 #include "CLHEP/Utility/noncopyable.h" 00017 #include "CLHEP/Utility/type_traits.h" 00018 00019 #include <cassert> 00020 #include <iostream> 00021 00022 00023 using namespace CLHEP; 00024 00025 00026 // primary type category codes: 00027 unsigned _unknown = 0uL ; 00028 unsigned _void = 1uL << 0; 00029 unsigned _integral = 1uL << 1; 00030 unsigned _floating_point = 1uL << 2; 00031 unsigned _array = 1uL << 3; 00032 unsigned _pointer = 1uL << 4; 00033 unsigned _lvalue_reference = 1uL << 5; 00034 unsigned _rvalue_reference = 1uL << 6; 00035 unsigned _member_object_pointer = 1uL << 7; 00036 unsigned _member_function_pointer = 1uL << 8; 00037 unsigned _enum = 1uL << 9; 00038 unsigned _union = 1uL << 10; // Help, compiler! 00039 unsigned _class = 1uL << 11; 00040 unsigned _function = 1uL << 12; 00041 00042 // composite type category codes: 00043 unsigned _reference = 1uL << 13; 00044 unsigned _arithmetic = 1uL << 14; 00045 unsigned _fundamental = 1uL << 15; 00046 unsigned _object = 1uL << 16; 00047 unsigned _scalar = 1uL << 17; 00048 unsigned _compound = 1uL << 18; 00049 unsigned _member_pointer = 1uL << 19; 00050 00051 00052 // evaluate categories: 00053 template< typename T > 00054 unsigned 00055 evaluate() 00056 { 00057 unsigned ans = _unknown; 00058 00059 if( is_void <T>::value ) ans += _void; 00060 if( is_integral <T>::value ) ans += _integral; 00061 if( is_floating_point <T>::value ) ans += _floating_point; 00062 if( is_array <T>::value ) ans += _array; 00063 if( is_pointer <T>::value ) ans += _pointer; 00064 if( is_lvalue_reference <T>::value ) ans += _lvalue_reference; 00065 if( is_rvalue_reference <T>::value ) ans += _rvalue_reference; 00066 if( is_member_object_pointer <T>::value ) ans += _member_object_pointer; 00067 if( is_member_function_pointer<T>::value ) ans += _member_function_pointer; 00068 if( is_enum <T>::value ) ans += _enum; 00069 if( is_union <T>::value ) ans += _union; 00070 if( is_class <T>::value ) ans += _class; 00071 if( is_function <T>::value ) ans += _function;; 00072 00073 if( is_reference <T>::value ) ans += _reference; 00074 if( is_arithmetic <T>::value ) ans += _arithmetic; 00075 if( is_fundamental <T>::value ) ans += _fundamental; 00076 if( is_object <T>::value ) ans += _object; 00077 if( is_scalar <T>::value ) ans += _scalar; 00078 if( is_compound <T>::value ) ans += _compound; 00079 if( is_member_pointer <T>::value ) ans += _member_pointer; 00080 00081 return ans; 00082 } 00083 00084 00085 unsigned cat_void 00086 = _void | _fundamental; 00087 unsigned cat_int 00088 = _integral | _arithmetic | _object | _fundamental | _scalar; 00089 unsigned cat_flt 00090 = _floating_point | _arithmetic | _object | _fundamental | _scalar; 00091 unsigned cat_arr 00092 = _array | _object | _compound; 00093 unsigned cat_ptr 00094 = _pointer | _object | _compound | _scalar; 00095 unsigned cat_lref 00096 = _lvalue_reference | _reference | _compound; 00097 unsigned cat_rref 00098 = _rvalue_reference | _reference | _compound; 00099 unsigned cat_mem_obj_ptr 00100 = _member_object_pointer | _member_pointer | _object | _compound | _scalar; 00101 unsigned cat_mbr_fctn_ptr 00102 = _member_function_pointer | _member_pointer | _object | _compound | _scalar; 00103 unsigned cat_enum 00104 = _enum | _object | _compound | _scalar; 00105 unsigned cat_union 00106 = _union | _object | _compound; 00107 unsigned cat_class 00108 = _class | _object | _compound; 00109 unsigned cat_fctn 00110 = _function | _compound; 00111 00112 00113 // define some test types: 00114 00115 // class type: 00116 struct mytype 00117 { 00118 int a; 00119 int * p; 00120 int f(); 00121 }; // mytype 00122 00123 00124 // enum type: 00125 enum myenum { a=12, b=16 }; 00126 00127 00128 // union type: 00129 union myblend 00130 { 00131 int a; 00132 int * p; 00133 int f(); 00134 }; 00135 00136 enum enum_UDT{ one, two, three }; 00137 struct UDT 00138 { 00139 UDT() { }; 00140 ~UDT() { }; 00141 UDT(const UDT&); 00142 UDT& operator=(const UDT&); 00143 int i; 00144 00145 void f1(); 00146 int f2(); 00147 int f3(int); 00148 int f4(int, float); 00149 }; 00150 00151 typedef void(*f1)(); 00152 typedef int(*f2)(int); 00153 typedef int(*f3)(int, bool); 00154 typedef void (UDT::*mf1)(); 00155 typedef int (UDT::*mf2)(); 00156 typedef int (UDT::*mf3)(int); 00157 typedef int (UDT::*mf4)(int, float); 00158 typedef int (UDT::*mp); 00159 typedef int (UDT::*cmf)(int) const; 00160 00161 // cv-qualifiers applied to reference types should have no effect 00162 00163 // This is intentional: 00164 // r_type and cr_type should be the same type 00165 // but some compilers wrongly apply cv-qualifiers 00166 // to reference types (this may generate a warning 00167 // on some compilers): 00168 00169 typedef int& r_type; 00170 #if ! defined(_MSC_VER) 00171 typedef const r_type cr_type; 00172 #endif // _MSC_VER 00173 00174 struct POD_UDT { int x; }; 00175 struct empty_UDT 00176 { 00177 empty_UDT() { }; 00178 empty_UDT(const empty_UDT&) { }; 00179 ~empty_UDT() { }; 00180 empty_UDT& operator=(const empty_UDT&){ return *this; } 00181 bool operator==(const empty_UDT&)const 00182 { return true; } 00183 }; 00184 struct empty_POD_UDT 00185 { 00186 bool operator==(const empty_POD_UDT&)const 00187 { return true; } 00188 }; 00189 union union_UDT 00190 { 00191 int x; 00192 double y; 00193 ~union_UDT() { } 00194 }; 00195 union POD_union_UDT 00196 { 00197 int x; 00198 double y; 00199 }; 00200 union empty_union_UDT 00201 { 00202 ~empty_union_UDT() { } 00203 }; 00204 union empty_POD_union_UDT { }; 00205 00206 struct nothrow_copy_UDT 00207 { 00208 nothrow_copy_UDT(); 00209 nothrow_copy_UDT(const nothrow_copy_UDT&)throw(); 00210 ~nothrow_copy_UDT() { }; 00211 nothrow_copy_UDT& operator=(const nothrow_copy_UDT&){ return *this; } 00212 bool operator==(const nothrow_copy_UDT&)const 00213 { return true; } 00214 }; 00215 00216 struct nothrow_assign_UDT 00217 { 00218 nothrow_assign_UDT(); 00219 nothrow_assign_UDT(const nothrow_assign_UDT&); 00220 ~nothrow_assign_UDT() { }; 00221 nothrow_assign_UDT& operator=(const nothrow_assign_UDT&)throw(){ return *this; } 00222 bool operator==(const nothrow_assign_UDT&)const 00223 { return true; } 00224 }; 00225 00226 struct nothrow_construct_UDT 00227 { 00228 nothrow_construct_UDT()throw(); 00229 nothrow_construct_UDT(const nothrow_construct_UDT&); 00230 ~nothrow_construct_UDT() { }; 00231 nothrow_construct_UDT& operator=(const nothrow_construct_UDT&){ return *this; } 00232 bool operator==(const nothrow_construct_UDT&)const 00233 { return true; } 00234 }; 00235 00236 class Base { }; 00237 00238 class Derived : public Base { }; 00239 class Derived2 : public Base { }; 00240 class MultiBase : public Derived, public Derived2 { }; 00241 class PrivateBase : private Base { }; 00242 00243 class NonDerived { }; 00244 00245 enum enum1 00246 { one_,two_ }; 00247 00248 enum enum2 00249 { three_,four_ }; 00250 00251 struct VB 00252 { virtual ~VB() { }; }; 00253 00254 struct VD : VB 00255 { ~VD() { }; }; 00256 00257 // struct non_pointer: 00258 // used to verify that is_pointer does not return 00259 // true for class types that implement operator void*() 00260 00261 struct non_pointer 00262 { operator void*(){return this;} }; 00263 struct non_int_pointer 00264 { 00265 int i; 00266 operator int*(){return &i;} 00267 }; 00268 struct int_constructible 00269 { int_constructible(int); }; 00270 struct int_convertible 00271 { operator int(); }; 00272 00273 // struct non_empty: 00274 // used to verify that is_empty does not emit 00275 // spurious warnings or errors. 00276 00277 struct non_empty : private noncopyable 00278 { int i; }; 00279 00280 // abstract base classes: 00281 struct test_abc1 00282 { 00283 test_abc1(); 00284 virtual ~test_abc1(); 00285 test_abc1(const test_abc1&); 00286 test_abc1& operator=(const test_abc1&); 00287 virtual void foo() = 0; 00288 virtual void foo2() = 0; 00289 }; 00290 00291 struct test_abc2 00292 { 00293 virtual ~test_abc2(); 00294 virtual void foo() = 0; 00295 virtual void foo2() = 0; 00296 }; 00297 00298 struct test_abc3 : public test_abc1 00299 { virtual void foo3() = 0; }; 00300 00301 struct incomplete_type; 00302 00303 struct polymorphic_base 00304 { 00305 virtual ~polymorphic_base(); 00306 virtual void method(); 00307 }; 00308 00309 struct polymorphic_derived1 : polymorphic_base 00310 { }; 00311 00312 struct polymorphic_derived2 : polymorphic_base 00313 { virtual void method(); }; 00314 00315 struct virtual_inherit1 : virtual Base { }; 00316 struct virtual_inherit2 : virtual_inherit1 { }; 00317 struct virtual_inherit3 : private virtual Base { }; 00318 struct virtual_inherit4 : virtual noncopyable { }; 00319 struct virtual_inherit5 : virtual int_convertible { }; 00320 struct virtual_inherit6 : virtual Base { virtual ~virtual_inherit6()throw(); }; 00321 00322 typedef void foo0_t(); 00323 typedef void foo1_t(int); 00324 typedef void foo2_t(int&, double); 00325 typedef void foo3_t(int&, bool, int, int); 00326 typedef void foo4_t(int, bool, int*, int[], int, int, int, int, int); 00327 00328 struct trivial_except_construct 00329 { 00330 trivial_except_construct(); 00331 int i; 00332 }; 00333 00334 struct trivial_except_destroy 00335 { 00336 ~trivial_except_destroy(); 00337 int i; 00338 }; 00339 00340 struct trivial_except_copy 00341 { 00342 trivial_except_copy(trivial_except_copy const&); 00343 int i; 00344 }; 00345 00346 struct trivial_except_assign 00347 { 00348 trivial_except_assign& operator=(trivial_except_assign const&); 00349 int i; 00350 }; 00351 00352 template <class T> 00353 struct wrap 00354 { 00355 T t; 00356 int j; 00357 protected: 00358 wrap(); 00359 wrap(const wrap&); 00360 wrap& operator=(const wrap&); 00361 }; 00362 00363 00364 struct convertible_to_pointer 00365 { operator char*() const; }; 00366 00367 00368 typedef const double (UDT::*mp2) ; 00369 00370 00371 int 00372 main() 00373 { 00374 // void types 00375 assert(evaluate<void >() == cat_void); 00376 assert(evaluate<void const >() == cat_void); 00377 assert(evaluate<void volatile >() == cat_void); 00378 assert(evaluate<void const volatile >() == cat_void); 00379 00380 // integral types 00381 assert(evaluate<bool >() == cat_int); 00382 assert(evaluate<bool const >() == cat_int); 00383 assert(evaluate<bool volatile >() == cat_int); 00384 assert(evaluate<bool const volatile >() == cat_int); 00385 assert(evaluate<char >() == cat_int); 00386 assert(evaluate<char const >() == cat_int); 00387 assert(evaluate<char volatile >() == cat_int); 00388 assert(evaluate<char const volatile >() == cat_int); 00389 typedef signed char schar; 00390 assert(evaluate<schar >() == cat_int); 00391 assert(evaluate<schar const >() == cat_int); 00392 assert(evaluate<schar volatile >() == cat_int); 00393 assert(evaluate<schar const volatile >() == cat_int); 00394 typedef unsigned char uchar; 00395 assert(evaluate<uchar >() == cat_int); 00396 assert(evaluate<uchar const >() == cat_int); 00397 assert(evaluate<uchar volatile >() == cat_int); 00398 assert(evaluate<uchar const volatile >() == cat_int); 00399 assert(evaluate<short >() == cat_int); 00400 assert(evaluate<short const >() == cat_int); 00401 assert(evaluate<short volatile >() == cat_int); 00402 assert(evaluate<short const volatile >() == cat_int); 00403 typedef unsigned short ushort; 00404 assert(evaluate<ushort >() == cat_int); 00405 assert(evaluate<ushort const >() == cat_int); 00406 assert(evaluate<ushort volatile >() == cat_int); 00407 assert(evaluate<ushort const volatile >() == cat_int); 00408 assert(evaluate<int >() == cat_int); 00409 assert(evaluate<int const >() == cat_int); 00410 assert(evaluate<int volatile >() == cat_int); 00411 assert(evaluate<int const volatile >() == cat_int); 00412 typedef unsigned int uint; 00413 assert(evaluate<uint >() == cat_int); 00414 assert(evaluate<uint const >() == cat_int); 00415 assert(evaluate<uint volatile >() == cat_int); 00416 assert(evaluate<uint const volatile >() == cat_int); 00417 assert(evaluate<long >() == cat_int); 00418 assert(evaluate<long const >() == cat_int); 00419 assert(evaluate<long volatile >() == cat_int); 00420 assert(evaluate<long const volatile >() == cat_int); 00421 typedef unsigned long ulong; 00422 assert(evaluate<ulong >() == cat_int); 00423 assert(evaluate<ulong const >() == cat_int); 00424 assert(evaluate<ulong volatile >() == cat_int); 00425 assert(evaluate<ulong const volatile >() == cat_int); 00426 00427 // floating-point types 00428 assert(evaluate<float >() == cat_flt); 00429 assert(evaluate<float const >() == cat_flt); 00430 assert(evaluate<float volatile >() == cat_flt); 00431 assert(evaluate<float const volatile >() == cat_flt); 00432 assert(evaluate<double >() == cat_flt); 00433 assert(evaluate<double const >() == cat_flt); 00434 assert(evaluate<double volatile >() == cat_flt); 00435 assert(evaluate<double const volatile >() == cat_flt); 00436 typedef long double ldouble; 00437 assert(evaluate<ldouble >() == cat_flt); 00438 assert(evaluate<ldouble const >() == cat_flt); 00439 assert(evaluate<ldouble volatile >() == cat_flt); 00440 assert(evaluate<ldouble const volatile >() == cat_flt); 00441 00442 // array types 00443 assert(evaluate<double [1]>() == cat_arr); 00444 assert(evaluate<char const [2]>() == cat_arr); 00445 assert(evaluate<float volatile [3]>() == cat_arr); 00446 assert(evaluate<long const volatile [4]>() == cat_arr); 00447 assert(evaluate<mytype * [6]>() == cat_arr); 00448 assert(evaluate<unsigned * [6]>() == cat_arr); 00449 assert(evaluate<long double [7][7]>() == cat_arr); 00450 assert(evaluate<UDT [2]>() == cat_arr); 00451 00452 // pointer types 00453 assert(evaluate<char * >() == cat_ptr); 00454 assert(evaluate<int * >() == cat_ptr); 00455 assert(evaluate<int const * >() == cat_ptr); 00456 assert(evaluate<int volatile * >() == cat_ptr); 00457 assert(evaluate<int * * >() == cat_ptr); 00458 assert(evaluate<int * * volatile >() == cat_ptr); 00459 assert(evaluate<uint volatile * >() == cat_ptr); 00460 assert(evaluate<long volatile * const >() == cat_ptr); 00461 assert(evaluate<double * const * >() == cat_ptr); 00462 assert(evaluate<float * const * const >() == cat_ptr); 00463 assert(evaluate<int (*)(int) >() == cat_ptr); 00464 assert(evaluate<non_pointer* >() == cat_ptr); 00465 assert(evaluate<f1 >() == cat_ptr); 00466 assert(evaluate<f2 >() == cat_ptr); 00467 assert(evaluate<f3 >() == cat_ptr); 00468 00469 // lvalue reference types 00470 assert(evaluate<int & >() == cat_lref); 00471 assert(evaluate<int const & >() == cat_lref); 00472 assert(evaluate<int volatile & >() == cat_lref); 00473 assert(evaluate<int const volatile & >() == cat_lref); 00474 assert(evaluate<int * & >() == cat_lref); 00475 assert(evaluate<int (&)(int) >() == cat_lref); 00476 assert(evaluate<int (&)[2] >() == cat_lref); 00477 assert(evaluate<r_type >() == cat_lref); 00478 #if ! defined(_MSC_VER) 00479 assert(evaluate<cr_type >() == cat_lref); 00480 #endif // _MSC_VER 00481 assert(evaluate<UDT & >() == cat_lref); 00482 assert(evaluate<const UDT & >() == cat_lref); 00483 assert(evaluate<volatile UDT & >() == cat_lref); 00484 assert(evaluate<const volatile UDT & >() == cat_lref); 00485 00486 // member object pointer types 00487 assert(evaluate<int mytype::* >() == cat_mem_obj_ptr); 00488 assert(evaluate<int mytype::* const >() == cat_mem_obj_ptr); 00489 assert(evaluate<int mytype::* volatile >() == cat_mem_obj_ptr); 00490 assert(evaluate<mp >() == cat_mem_obj_ptr); 00491 assert(evaluate<mp2 >() == cat_mem_obj_ptr); 00492 00493 // member function pointer types 00494 assert(evaluate<int (mytype::*)() >() == cat_mbr_fctn_ptr); 00495 assert(evaluate<int (mytype::*)()const >() == cat_mbr_fctn_ptr); 00496 assert(evaluate<int (mytype::*)(int) >() == cat_mbr_fctn_ptr); 00497 assert(evaluate<mf1 >() == cat_mbr_fctn_ptr); 00498 assert(evaluate<mf2 >() == cat_mbr_fctn_ptr); 00499 assert(evaluate<mf3 >() == cat_mbr_fctn_ptr); 00500 assert(evaluate<mf4 >() == cat_mbr_fctn_ptr); 00501 assert(evaluate<cmf >() == cat_mbr_fctn_ptr); 00502 00503 // enum types 00504 assert(evaluate<myenum >() == cat_enum); 00505 assert(evaluate<myenum const >() == cat_enum); 00506 assert(evaluate<myenum volatile >() == cat_enum); 00507 assert(evaluate<myenum const volatile >() == cat_enum); 00508 assert(evaluate<enum_UDT >() == cat_enum); 00509 00510 // union types 00511 #if 0 00512 assert(evaluate<myblend >() == cat_union); 00513 assert(evaluate<myblend const >() == cat_union); 00514 assert(evaluate<myblend volatile >() == cat_union); 00515 assert(evaluate<myblend const volatile >() == cat_union); 00516 assert(evaluate<union_UDT >() == cat_union); 00517 assert(evaluate<POD_union_UDT >() == cat_union); 00518 assert(evaluate<empty_union_UDT >() == cat_union); 00519 assert(evaluate<empty_POD_union_UDT >() == cat_union); 00520 assert(evaluate<union_UDT const >() == cat_union); 00521 assert(evaluate<POD_union_UDT volatile >() == cat_union); 00522 assert(evaluate<empty_union_UDT const volatile>() == cat_union); 00523 assert(evaluate<empty_POD_union_UDT const>() == cat_union); 00524 #endif // 0 00525 00526 // class types 00527 assert(evaluate<UDT >() == cat_class); 00528 assert(evaluate<UDT const >() == cat_class); 00529 assert(evaluate<UDT volatile >() == cat_class); 00530 assert(evaluate<UDT const volatile >() == cat_class); 00531 assert(evaluate<empty_UDT >() == cat_class); 00532 assert(evaluate<test_abc1 >() == cat_class); 00533 assert(evaluate<test_abc1 const >() == cat_class); 00534 assert(evaluate<std::iostream >() == cat_class); 00535 00536 // function types 00537 assert(evaluate<int (int) >() == cat_fctn); 00538 assert(evaluate<void (int,float, long) >() == cat_fctn); 00539 assert(evaluate<foo0_t >() == cat_fctn); 00540 assert(evaluate<foo1_t >() == cat_fctn); 00541 assert(evaluate<foo2_t >() == cat_fctn); 00542 assert(evaluate<foo3_t >() == cat_fctn); 00543 assert(evaluate<foo4_t >() == cat_fctn); 00544 00545 return 0; 00546 }