libstdc++
|
00001 // C++0x type_traits -*- C++ -*- 00002 00003 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file include/type_traits 00026 * This is a Standard C++ Library header. 00027 */ 00028 00029 #ifndef _GLIBCXX_TYPE_TRAITS 00030 #define _GLIBCXX_TYPE_TRAITS 1 00031 00032 #pragma GCC system_header 00033 00034 #ifndef __GXX_EXPERIMENTAL_CXX0X__ 00035 # include <c++0x_warning.h> 00036 #else 00037 00038 #if defined(_GLIBCXX_INCLUDE_AS_TR1) 00039 # error C++0x header cannot be included from TR1 header 00040 #endif 00041 00042 #include <cstddef> 00043 00044 #if defined(_GLIBCXX_INCLUDE_AS_CXX0X) 00045 # include <tr1_impl/type_traits> 00046 #else 00047 # define _GLIBCXX_INCLUDE_AS_CXX0X 00048 # define _GLIBCXX_BEGIN_NAMESPACE_TR1 00049 # define _GLIBCXX_END_NAMESPACE_TR1 00050 # define _GLIBCXX_TR1 00051 # include <tr1_impl/type_traits> 00052 # undef _GLIBCXX_TR1 00053 # undef _GLIBCXX_END_NAMESPACE_TR1 00054 # undef _GLIBCXX_BEGIN_NAMESPACE_TR1 00055 # undef _GLIBCXX_INCLUDE_AS_CXX0X 00056 #endif 00057 00058 namespace std 00059 { 00060 /** @addtogroup metaprogramming 00061 * @{ 00062 */ 00063 00064 // Primary classification traits. 00065 00066 /// is_lvalue_reference 00067 template<typename> 00068 struct is_lvalue_reference 00069 : public false_type { }; 00070 00071 template<typename _Tp> 00072 struct is_lvalue_reference<_Tp&> 00073 : public true_type { }; 00074 00075 /// is_rvalue_reference 00076 template<typename> 00077 struct is_rvalue_reference 00078 : public false_type { }; 00079 00080 template<typename _Tp> 00081 struct is_rvalue_reference<_Tp&&> 00082 : public true_type { }; 00083 00084 // Secondary classification traits. 00085 00086 /// is_reference 00087 template<typename _Tp> 00088 struct is_reference 00089 : public integral_constant<bool, (is_lvalue_reference<_Tp>::value 00090 || is_rvalue_reference<_Tp>::value)> 00091 { }; 00092 00093 // Reference transformations. 00094 00095 /// remove_reference 00096 template<typename _Tp> 00097 struct remove_reference 00098 { typedef _Tp type; }; 00099 00100 template<typename _Tp> 00101 struct remove_reference<_Tp&> 00102 { typedef _Tp type; }; 00103 00104 template<typename _Tp> 00105 struct remove_reference<_Tp&&> 00106 { typedef _Tp type; }; 00107 00108 template<typename _Tp, 00109 bool = !is_reference<_Tp>::value && !is_void<_Tp>::value, 00110 bool = is_rvalue_reference<_Tp>::value> 00111 struct __add_lvalue_reference_helper 00112 { typedef _Tp type; }; 00113 00114 template<typename _Tp> 00115 struct __add_lvalue_reference_helper<_Tp, true, false> 00116 { typedef _Tp& type; }; 00117 00118 template<typename _Tp> 00119 struct __add_lvalue_reference_helper<_Tp, false, true> 00120 { typedef typename remove_reference<_Tp>::type& type; }; 00121 00122 /// add_lvalue_reference 00123 template<typename _Tp> 00124 struct add_lvalue_reference 00125 : public __add_lvalue_reference_helper<_Tp> 00126 { }; 00127 00128 template<typename _Tp, 00129 bool = !is_reference<_Tp>::value && !is_void<_Tp>::value> 00130 struct __add_rvalue_reference_helper 00131 { typedef _Tp type; }; 00132 00133 template<typename _Tp> 00134 struct __add_rvalue_reference_helper<_Tp, true> 00135 { typedef _Tp&& type; }; 00136 00137 /// add_rvalue_reference 00138 template<typename _Tp> 00139 struct add_rvalue_reference 00140 : public __add_rvalue_reference_helper<_Tp> 00141 { }; 00142 00143 // Scalar properties and transformations. 00144 00145 template<typename _Tp, 00146 bool = is_integral<_Tp>::value, 00147 bool = is_floating_point<_Tp>::value> 00148 struct __is_signed_helper 00149 : public false_type { }; 00150 00151 template<typename _Tp> 00152 struct __is_signed_helper<_Tp, false, true> 00153 : public true_type { }; 00154 00155 template<typename _Tp> 00156 struct __is_signed_helper<_Tp, true, false> 00157 : public integral_constant<bool, _Tp(-1) < _Tp(0)> 00158 { }; 00159 00160 /// is_signed 00161 template<typename _Tp> 00162 struct is_signed 00163 : public integral_constant<bool, __is_signed_helper<_Tp>::value> 00164 { }; 00165 00166 /// is_unsigned 00167 template<typename _Tp> 00168 struct is_unsigned 00169 : public integral_constant<bool, (is_arithmetic<_Tp>::value 00170 && !is_signed<_Tp>::value)> 00171 { }; 00172 00173 // Member introspection. 00174 00175 /// is_pod 00176 template<typename _Tp> 00177 struct is_pod 00178 : public integral_constant<bool, __is_pod(_Tp)> 00179 { }; 00180 00181 /// has_trivial_default_constructor 00182 template<typename _Tp> 00183 struct has_trivial_default_constructor 00184 : public integral_constant<bool, __has_trivial_constructor(_Tp)> 00185 { }; 00186 00187 /// has_trivial_copy_constructor 00188 template<typename _Tp> 00189 struct has_trivial_copy_constructor 00190 : public integral_constant<bool, __has_trivial_copy(_Tp)> 00191 { }; 00192 00193 /// has_trivial_assign 00194 template<typename _Tp> 00195 struct has_trivial_assign 00196 : public integral_constant<bool, __has_trivial_assign(_Tp)> 00197 { }; 00198 00199 /// has_trivial_destructor 00200 template<typename _Tp> 00201 struct has_trivial_destructor 00202 : public integral_constant<bool, __has_trivial_destructor(_Tp)> 00203 { }; 00204 00205 /// has_nothrow_default_constructor 00206 template<typename _Tp> 00207 struct has_nothrow_default_constructor 00208 : public integral_constant<bool, __has_nothrow_constructor(_Tp)> 00209 { }; 00210 00211 /// has_nothrow_copy_constructor 00212 template<typename _Tp> 00213 struct has_nothrow_copy_constructor 00214 : public integral_constant<bool, __has_nothrow_copy(_Tp)> 00215 { }; 00216 00217 /// has_nothrow_assign 00218 template<typename _Tp> 00219 struct has_nothrow_assign 00220 : public integral_constant<bool, __has_nothrow_assign(_Tp)> 00221 { }; 00222 00223 /// is_base_of 00224 template<typename _Base, typename _Derived> 00225 struct is_base_of 00226 : public integral_constant<bool, __is_base_of(_Base, _Derived)> 00227 { }; 00228 00229 // Relationships between types. 00230 template<typename _From, typename _To> 00231 struct __is_convertible_simple 00232 : public __sfinae_types 00233 { 00234 private: 00235 static __one __test(_To); 00236 static __two __test(...); 00237 static _From __makeFrom(); 00238 00239 public: 00240 static const bool __value = sizeof(__test(__makeFrom())) == 1; 00241 }; 00242 00243 template<typename _Tp> 00244 struct __is_int_or_cref 00245 { 00246 typedef typename remove_reference<_Tp>::type __rr_Tp; 00247 static const bool __value = (is_integral<_Tp>::value 00248 || (is_integral<__rr_Tp>::value 00249 && is_const<__rr_Tp>::value 00250 && !is_volatile<__rr_Tp>::value)); 00251 }; 00252 00253 template<typename _From, typename _To, 00254 bool = (is_void<_From>::value || is_void<_To>::value 00255 || is_function<_To>::value || is_array<_To>::value 00256 // This special case is here only to avoid warnings. 00257 || (is_floating_point<typename 00258 remove_reference<_From>::type>::value 00259 && __is_int_or_cref<_To>::__value))> 00260 struct __is_convertible_helper 00261 { 00262 // "An imaginary lvalue of type From...". 00263 static const bool __value = (__is_convertible_simple<typename 00264 add_lvalue_reference<_From>::type, 00265 _To>::__value); 00266 }; 00267 00268 template<typename _From, typename _To> 00269 struct __is_convertible_helper<_From, _To, true> 00270 { static const bool __value = (is_void<_To>::value 00271 || (__is_int_or_cref<_To>::__value 00272 && !is_void<_From>::value)); }; 00273 00274 // XXX FIXME 00275 // The C++0x specifications are different, see N2255. 00276 /// is_convertible 00277 template<typename _From, typename _To> 00278 struct is_convertible 00279 : public integral_constant<bool, 00280 __is_convertible_helper<_From, _To>::__value> 00281 { }; 00282 00283 template<std::size_t _Len> 00284 struct __aligned_storage_msa 00285 { 00286 union __type 00287 { 00288 unsigned char __data[_Len]; 00289 struct __attribute__((__aligned__)) { } __align; 00290 }; 00291 }; 00292 00293 /** 00294 * @brief Alignment type. 00295 * 00296 * The value of _Align is a default-alignment which shall be the 00297 * most stringent alignment requirement for any C++ object type 00298 * whose size is no greater than _Len (3.9). The member typedef 00299 * type shall be a POD type suitable for use as uninitialized 00300 * storage for any object whose size is at most _Len and whose 00301 * alignment is a divisor of _Align. 00302 */ 00303 template<std::size_t _Len, std::size_t _Align = 00304 __alignof__(typename __aligned_storage_msa<_Len>::__type)> 00305 struct aligned_storage 00306 { 00307 union type 00308 { 00309 unsigned char __data[_Len]; 00310 struct __attribute__((__aligned__((_Align)))) { } __align; 00311 }; 00312 }; 00313 00314 00315 // Define a nested type if some predicate holds. 00316 // Primary template. 00317 /// enable_if 00318 template<bool, typename _Tp = void> 00319 struct enable_if 00320 { }; 00321 00322 // Partial specialization for true. 00323 template<typename _Tp> 00324 struct enable_if<true, _Tp> 00325 { typedef _Tp type; }; 00326 00327 00328 // A conditional expression, but for types. If true, first, if false, second. 00329 // Primary template. 00330 /// conditional 00331 template<bool _Cond, typename _Iftrue, typename _Iffalse> 00332 struct conditional 00333 { typedef _Iftrue type; }; 00334 00335 // Partial specialization for false. 00336 template<typename _Iftrue, typename _Iffalse> 00337 struct conditional<false, _Iftrue, _Iffalse> 00338 { typedef _Iffalse type; }; 00339 00340 00341 // Decay trait for arrays and functions, used for perfect forwarding 00342 // in make_pair, make_tuple, etc. 00343 template<typename _Up, 00344 bool _IsArray = is_array<_Up>::value, 00345 bool _IsFunction = is_function<_Up>::value> 00346 struct __decay_selector; 00347 00348 // NB: DR 705. 00349 template<typename _Up> 00350 struct __decay_selector<_Up, false, false> 00351 { typedef typename remove_cv<_Up>::type __type; }; 00352 00353 template<typename _Up> 00354 struct __decay_selector<_Up, true, false> 00355 { typedef typename remove_extent<_Up>::type* __type; }; 00356 00357 template<typename _Up> 00358 struct __decay_selector<_Up, false, true> 00359 { typedef typename add_pointer<_Up>::type __type; }; 00360 00361 /// decay 00362 template<typename _Tp> 00363 struct decay 00364 { 00365 private: 00366 typedef typename remove_reference<_Tp>::type __remove_type; 00367 00368 public: 00369 typedef typename __decay_selector<__remove_type>::__type type; 00370 }; 00371 00372 00373 // Utility for constructing identically cv-qualified types. 00374 template<typename _Unqualified, bool _IsConst, bool _IsVol> 00375 struct __cv_selector; 00376 00377 template<typename _Unqualified> 00378 struct __cv_selector<_Unqualified, false, false> 00379 { typedef _Unqualified __type; }; 00380 00381 template<typename _Unqualified> 00382 struct __cv_selector<_Unqualified, false, true> 00383 { typedef volatile _Unqualified __type; }; 00384 00385 template<typename _Unqualified> 00386 struct __cv_selector<_Unqualified, true, false> 00387 { typedef const _Unqualified __type; }; 00388 00389 template<typename _Unqualified> 00390 struct __cv_selector<_Unqualified, true, true> 00391 { typedef const volatile _Unqualified __type; }; 00392 00393 template<typename _Qualified, typename _Unqualified, 00394 bool _IsConst = is_const<_Qualified>::value, 00395 bool _IsVol = is_volatile<_Qualified>::value> 00396 struct __match_cv_qualifiers 00397 { 00398 private: 00399 typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match; 00400 00401 public: 00402 typedef typename __match::__type __type; 00403 }; 00404 00405 00406 // Utility for finding the unsigned versions of signed integral types. 00407 template<typename _Tp> 00408 struct __make_unsigned 00409 { typedef _Tp __type; }; 00410 00411 template<> 00412 struct __make_unsigned<char> 00413 { typedef unsigned char __type; }; 00414 00415 template<> 00416 struct __make_unsigned<signed char> 00417 { typedef unsigned char __type; }; 00418 00419 template<> 00420 struct __make_unsigned<short> 00421 { typedef unsigned short __type; }; 00422 00423 template<> 00424 struct __make_unsigned<int> 00425 { typedef unsigned int __type; }; 00426 00427 template<> 00428 struct __make_unsigned<long> 00429 { typedef unsigned long __type; }; 00430 00431 template<> 00432 struct __make_unsigned<long long> 00433 { typedef unsigned long long __type; }; 00434 00435 00436 // Select between integral and enum: not possible to be both. 00437 template<typename _Tp, 00438 bool _IsInt = is_integral<_Tp>::value, 00439 bool _IsEnum = is_enum<_Tp>::value> 00440 struct __make_unsigned_selector; 00441 00442 template<typename _Tp> 00443 struct __make_unsigned_selector<_Tp, true, false> 00444 { 00445 private: 00446 typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt; 00447 typedef typename __unsignedt::__type __unsigned_type; 00448 typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned; 00449 00450 public: 00451 typedef typename __cv_unsigned::__type __type; 00452 }; 00453 00454 template<typename _Tp> 00455 struct __make_unsigned_selector<_Tp, false, true> 00456 { 00457 private: 00458 // With -fshort-enums, an enum may be as small as a char. 00459 typedef unsigned char __smallest; 00460 static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); 00461 static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short); 00462 static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int); 00463 typedef conditional<__b2, unsigned int, unsigned long> __cond2; 00464 typedef typename __cond2::type __cond2_type; 00465 typedef conditional<__b1, unsigned short, __cond2_type> __cond1; 00466 typedef typename __cond1::type __cond1_type; 00467 00468 public: 00469 typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; 00470 }; 00471 00472 // Given an integral/enum type, return the corresponding unsigned 00473 // integer type. 00474 // Primary template. 00475 /// make_unsigned 00476 template<typename _Tp> 00477 struct make_unsigned 00478 { typedef typename __make_unsigned_selector<_Tp>::__type type; }; 00479 00480 // Integral, but don't define. 00481 template<> 00482 struct make_unsigned<bool>; 00483 00484 00485 // Utility for finding the signed versions of unsigned integral types. 00486 template<typename _Tp> 00487 struct __make_signed 00488 { typedef _Tp __type; }; 00489 00490 template<> 00491 struct __make_signed<char> 00492 { typedef signed char __type; }; 00493 00494 template<> 00495 struct __make_signed<unsigned char> 00496 { typedef signed char __type; }; 00497 00498 template<> 00499 struct __make_signed<unsigned short> 00500 { typedef signed short __type; }; 00501 00502 template<> 00503 struct __make_signed<unsigned int> 00504 { typedef signed int __type; }; 00505 00506 template<> 00507 struct __make_signed<unsigned long> 00508 { typedef signed long __type; }; 00509 00510 template<> 00511 struct __make_signed<unsigned long long> 00512 { typedef signed long long __type; }; 00513 00514 00515 // Select between integral and enum: not possible to be both. 00516 template<typename _Tp, 00517 bool _IsInt = is_integral<_Tp>::value, 00518 bool _IsEnum = is_enum<_Tp>::value> 00519 struct __make_signed_selector; 00520 00521 template<typename _Tp> 00522 struct __make_signed_selector<_Tp, true, false> 00523 { 00524 private: 00525 typedef __make_signed<typename remove_cv<_Tp>::type> __signedt; 00526 typedef typename __signedt::__type __signed_type; 00527 typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed; 00528 00529 public: 00530 typedef typename __cv_signed::__type __type; 00531 }; 00532 00533 template<typename _Tp> 00534 struct __make_signed_selector<_Tp, false, true> 00535 { 00536 private: 00537 // With -fshort-enums, an enum may be as small as a char. 00538 typedef signed char __smallest; 00539 static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); 00540 static const bool __b1 = sizeof(_Tp) <= sizeof(signed short); 00541 static const bool __b2 = sizeof(_Tp) <= sizeof(signed int); 00542 typedef conditional<__b2, signed int, signed long> __cond2; 00543 typedef typename __cond2::type __cond2_type; 00544 typedef conditional<__b1, signed short, __cond2_type> __cond1; 00545 typedef typename __cond1::type __cond1_type; 00546 00547 public: 00548 typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; 00549 }; 00550 00551 // Given an integral/enum type, return the corresponding signed 00552 // integer type. 00553 // Primary template. 00554 /// make_signed 00555 template<typename _Tp> 00556 struct make_signed 00557 { typedef typename __make_signed_selector<_Tp>::__type type; }; 00558 00559 // Integral, but don't define. 00560 template<> 00561 struct make_signed<bool>; 00562 00563 /// common_type 00564 template<typename... _Tp> 00565 struct common_type; 00566 00567 template<typename _Tp> 00568 struct common_type<_Tp> 00569 { 00570 static_assert(sizeof(_Tp) > 0, "must be complete type"); 00571 typedef _Tp type; 00572 }; 00573 00574 template<typename _Tp, typename _Up> 00575 class common_type<_Tp, _Up> 00576 { 00577 static_assert(sizeof(_Tp) > 0, "must be complete type"); 00578 static_assert(sizeof(_Up) > 0, "must be complete type"); 00579 00580 static _Tp&& __t(); 00581 static _Up&& __u(); 00582 00583 // HACK: Prevents optimization of ?: in the decltype 00584 // expression when the condition is the literal, "true". 00585 // See, PR36628. 00586 static bool __true_or_false(); 00587 00588 public: 00589 typedef decltype(__true_or_false() ? __t() : __u()) type; 00590 }; 00591 00592 template<typename _Tp, typename _Up, typename... _Vp> 00593 struct common_type<_Tp, _Up, _Vp...> 00594 { 00595 typedef typename 00596 common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; 00597 }; 00598 00599 // @} group metaprogramming 00600 } 00601 00602 #endif // __GXX_EXPERIMENTAL_CXX0X__ 00603 00604 #endif // _GLIBCXX_TYPE_TRAITS 00605