00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef ABSL_META_TYPE_TRAITS_H_
00036 #define ABSL_META_TYPE_TRAITS_H_
00037
00038 #include <stddef.h>
00039 #include <functional>
00040 #include <type_traits>
00041
00042 #include "absl/base/config.h"
00043
00044 namespace absl {
00045
00046
00047 template <typename T>
00048 struct is_trivially_move_assignable;
00049
00050 namespace type_traits_internal {
00051
00052
00053 #if defined(_MSC_VER) && !defined(__GNUC__)
00054 #pragma warning(push)
00055 #pragma warning(disable : 4624)
00056 #endif // defined(_MSC_VER) && !defined(__GNUC__)
00057
00058 template <class T>
00059 union SingleMemberUnion {
00060 T t;
00061 };
00062
00063
00064 #if defined(_MSC_VER) && !defined(__GNUC__)
00065 #pragma warning(pop)
00066 #endif // defined(_MSC_VER) && !defined(__GNUC__)
00067
00068 template <class T>
00069 struct IsTriviallyMoveAssignableReference : std::false_type {};
00070
00071 template <class T>
00072 struct IsTriviallyMoveAssignableReference<T&>
00073 : absl::is_trivially_move_assignable<T>::type {};
00074
00075 template <class T>
00076 struct IsTriviallyMoveAssignableReference<T&&>
00077 : absl::is_trivially_move_assignable<T>::type {};
00078
00079 template <typename... Ts>
00080 struct VoidTImpl {
00081 using type = void;
00082 };
00083
00084
00085
00086
00087 template <size_t Len, typename T = std::aligned_storage<Len>>
00088 struct default_alignment_of_aligned_storage;
00089
00090 template <size_t Len, size_t Align>
00091 struct default_alignment_of_aligned_storage<Len,
00092 std::aligned_storage<Len, Align>> {
00093 static constexpr size_t value = Align;
00094 };
00095
00097
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 template <class Enabler, template <class...> class Op, class... Args>
00111 struct is_detected_impl {
00112 using type = std::false_type;
00113 };
00114
00115 template <template <class...> class Op, class... Args>
00116 struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
00117 using type = std::true_type;
00118 };
00119
00120 template <template <class...> class Op, class... Args>
00121 struct is_detected : is_detected_impl<void, Op, Args...>::type {};
00122
00123 template <class Enabler, class To, template <class...> class Op, class... Args>
00124 struct is_detected_convertible_impl {
00125 using type = std::false_type;
00126 };
00127
00128 template <class To, template <class...> class Op, class... Args>
00129 struct is_detected_convertible_impl<
00130 typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
00131 To, Op, Args...> {
00132 using type = std::true_type;
00133 };
00134
00135 template <class To, template <class...> class Op, class... Args>
00136 struct is_detected_convertible
00137 : is_detected_convertible_impl<void, To, Op, Args...>::type {};
00138
00139 template <typename T>
00140 using IsCopyAssignableImpl =
00141 decltype(std::declval<T&>() = std::declval<const T&>());
00142
00143 template <typename T>
00144 using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
00145
00146 }
00147
00148 template <typename T>
00149 struct is_copy_assignable : type_traits_internal::is_detected<
00150 type_traits_internal::IsCopyAssignableImpl, T> {
00151 };
00152
00153 template <typename T>
00154 struct is_move_assignable : type_traits_internal::is_detected<
00155 type_traits_internal::IsMoveAssignableImpl, T> {
00156 };
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 template <typename... Ts>
00171 using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 template <typename... Ts>
00183 struct conjunction;
00184
00185 template <typename T, typename... Ts>
00186 struct conjunction<T, Ts...>
00187 : std::conditional<T::value, conjunction<Ts...>, T>::type {};
00188
00189 template <typename T>
00190 struct conjunction<T> : T {};
00191
00192 template <>
00193 struct conjunction<> : std::true_type {};
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 template <typename... Ts>
00205 struct disjunction;
00206
00207 template <typename T, typename... Ts>
00208 struct disjunction<T, Ts...> :
00209 std::conditional<T::value, T, disjunction<Ts...>>::type {};
00210
00211 template <typename T>
00212 struct disjunction<T> : T {};
00213
00214 template <>
00215 struct disjunction<> : std::false_type {};
00216
00217
00218
00219
00220
00221
00222
00223
00224 template <typename T>
00225 struct negation : std::integral_constant<bool, !T::value> {};
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 template <typename T>
00242 struct is_trivially_destructible
00243 : std::integral_constant<bool, __has_trivial_destructor(T) &&
00244 std::is_destructible<T>::value> {
00245 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
00246 private:
00247 static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
00248 is_trivially_destructible::value;
00249 static_assert(compliant || std::is_trivially_destructible<T>::value,
00250 "Not compliant with std::is_trivially_destructible; "
00251 "Standard: false, Implementation: true");
00252 static_assert(compliant || !std::is_trivially_destructible<T>::value,
00253 "Not compliant with std::is_trivially_destructible; "
00254 "Standard: true, Implementation: false");
00255 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
00256 };
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 template <typename T>
00291 struct is_trivially_default_constructible
00292 : std::integral_constant<bool, __has_trivial_constructor(T) &&
00293 std::is_default_constructible<T>::value &&
00294 is_trivially_destructible<T>::value> {
00295 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00296 private:
00297 static constexpr bool compliant =
00298 std::is_trivially_default_constructible<T>::value ==
00299 is_trivially_default_constructible::value;
00300 static_assert(compliant || std::is_trivially_default_constructible<T>::value,
00301 "Not compliant with std::is_trivially_default_constructible; "
00302 "Standard: false, Implementation: true");
00303 static_assert(compliant || !std::is_trivially_default_constructible<T>::value,
00304 "Not compliant with std::is_trivially_default_constructible; "
00305 "Standard: true, Implementation: false");
00306 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00307 };
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 template <typename T>
00323 struct is_trivially_move_constructible
00324 : std::conditional<
00325 std::is_object<T>::value && !std::is_array<T>::value,
00326 std::is_move_constructible<
00327 type_traits_internal::SingleMemberUnion<T>>,
00328 std::is_reference<T>>::type::type {
00329 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00330 private:
00331 static constexpr bool compliant =
00332 std::is_trivially_move_constructible<T>::value ==
00333 is_trivially_move_constructible::value;
00334 static_assert(compliant || std::is_trivially_move_constructible<T>::value,
00335 "Not compliant with std::is_trivially_move_constructible; "
00336 "Standard: false, Implementation: true");
00337 static_assert(compliant || !std::is_trivially_move_constructible<T>::value,
00338 "Not compliant with std::is_trivially_move_constructible; "
00339 "Standard: true, Implementation: false");
00340 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00341 };
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 template <typename T>
00357 struct is_trivially_copy_constructible
00358 : std::conditional<
00359 std::is_object<T>::value && !std::is_array<T>::value,
00360 std::is_copy_constructible<
00361 type_traits_internal::SingleMemberUnion<T>>,
00362 std::is_lvalue_reference<T>>::type::type {
00363 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00364 private:
00365 static constexpr bool compliant =
00366 std::is_trivially_copy_constructible<T>::value ==
00367 is_trivially_copy_constructible::value;
00368 static_assert(compliant || std::is_trivially_copy_constructible<T>::value,
00369 "Not compliant with std::is_trivially_copy_constructible; "
00370 "Standard: false, Implementation: true");
00371 static_assert(compliant || !std::is_trivially_copy_constructible<T>::value,
00372 "Not compliant with std::is_trivially_copy_constructible; "
00373 "Standard: true, Implementation: false");
00374 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
00375 };
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 template <typename T>
00393 struct is_trivially_move_assignable
00394 : std::conditional<
00395 std::is_object<T>::value && !std::is_array<T>::value,
00396 std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
00397 type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
00398 type {
00399 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00400 private:
00401 static constexpr bool compliant =
00402 std::is_trivially_move_assignable<T>::value ==
00403 is_trivially_move_assignable::value;
00404 static_assert(compliant || std::is_trivially_move_assignable<T>::value,
00405 "Not compliant with std::is_trivially_move_assignable; "
00406 "Standard: false, Implementation: true");
00407 static_assert(compliant || !std::is_trivially_move_assignable<T>::value,
00408 "Not compliant with std::is_trivially_move_assignable; "
00409 "Standard: true, Implementation: false");
00410 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00411 };
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 template <typename T>
00429 struct is_trivially_copy_assignable
00430 : std::integral_constant<
00431 bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
00432 absl::is_copy_assignable<T>::value> {
00433 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00434 private:
00435 static constexpr bool compliant =
00436 std::is_trivially_copy_assignable<T>::value ==
00437 is_trivially_copy_assignable::value;
00438 static_assert(compliant || std::is_trivially_copy_assignable<T>::value,
00439 "Not compliant with std::is_trivially_copy_assignable; "
00440 "Standard: false, Implementation: true");
00441 static_assert(compliant || !std::is_trivially_copy_assignable<T>::value,
00442 "Not compliant with std::is_trivially_copy_assignable; "
00443 "Standard: true, Implementation: false");
00444 #endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
00445 };
00446
00447 namespace type_traits_internal {
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 template <typename T>
00464 class is_trivially_copyable_impl {
00465 using ExtentsRemoved = typename std::remove_all_extents<T>::type;
00466 static constexpr bool kIsCopyOrMoveConstructible =
00467 std::is_copy_constructible<ExtentsRemoved>::value ||
00468 std::is_move_constructible<ExtentsRemoved>::value;
00469 static constexpr bool kIsCopyOrMoveAssignable =
00470 absl::is_copy_assignable<ExtentsRemoved>::value ||
00471 absl::is_move_assignable<ExtentsRemoved>::value;
00472
00473 public:
00474 static constexpr bool kValue =
00475 (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
00476 (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
00477 (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
00478 is_trivially_destructible<ExtentsRemoved>::value &&
00479
00480
00481 !std::is_reference<ExtentsRemoved>::value;
00482 };
00483
00484 template <typename T>
00485 struct is_trivially_copyable
00486 : std::integral_constant<
00487 bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
00488 }
00489
00490
00491
00492
00493
00494 template <typename T>
00495 using remove_cv_t = typename std::remove_cv<T>::type;
00496
00497 template <typename T>
00498 using remove_const_t = typename std::remove_const<T>::type;
00499
00500 template <typename T>
00501 using remove_volatile_t = typename std::remove_volatile<T>::type;
00502
00503 template <typename T>
00504 using add_cv_t = typename std::add_cv<T>::type;
00505
00506 template <typename T>
00507 using add_const_t = typename std::add_const<T>::type;
00508
00509 template <typename T>
00510 using add_volatile_t = typename std::add_volatile<T>::type;
00511
00512 template <typename T>
00513 using remove_reference_t = typename std::remove_reference<T>::type;
00514
00515 template <typename T>
00516 using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
00517
00518 template <typename T>
00519 using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
00520
00521 template <typename T>
00522 using remove_pointer_t = typename std::remove_pointer<T>::type;
00523
00524 template <typename T>
00525 using add_pointer_t = typename std::add_pointer<T>::type;
00526
00527 template <typename T>
00528 using make_signed_t = typename std::make_signed<T>::type;
00529
00530 template <typename T>
00531 using make_unsigned_t = typename std::make_unsigned<T>::type;
00532
00533 template <typename T>
00534 using remove_extent_t = typename std::remove_extent<T>::type;
00535
00536 template <typename T>
00537 using remove_all_extents_t = typename std::remove_all_extents<T>::type;
00538
00539 template <size_t Len, size_t Align = type_traits_internal::
00540 default_alignment_of_aligned_storage<Len>::value>
00541 using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
00542
00543 template <typename T>
00544 using decay_t = typename std::decay<T>::type;
00545
00546 template <bool B, typename T = void>
00547 using enable_if_t = typename std::enable_if<B, T>::type;
00548
00549 template <bool B, typename T, typename F>
00550 using conditional_t = typename std::conditional<B, T, F>::type;
00551
00552 template <typename... T>
00553 using common_type_t = typename std::common_type<T...>::type;
00554
00555 template <typename T>
00556 using underlying_type_t = typename std::underlying_type<T>::type;
00557
00558 template <typename T>
00559 using result_of_t = typename std::result_of<T>::type;
00560
00561 namespace type_traits_internal {
00562
00563
00564
00565
00566 #if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
00567 _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
00568 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
00569 #else
00570 #define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
00571 #endif
00572
00573 #if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00574 template <typename Key, typename = size_t>
00575 struct IsHashable : std::true_type {};
00576 #else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00577 template <typename Key, typename = void>
00578 struct IsHashable : std::false_type {};
00579
00580 template <typename Key>
00581 struct IsHashable<
00582 Key,
00583 absl::enable_if_t<std::is_convertible<
00584 decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
00585 std::size_t>::value>> : std::true_type {};
00586 #endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
00587
00588 struct AssertHashEnabledHelper {
00589 private:
00590 static void Sink(...) {}
00591 struct NAT {};
00592
00593 template <class Key>
00594 static auto GetReturnType(int)
00595 -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
00596 template <class Key>
00597 static NAT GetReturnType(...);
00598
00599 template <class Key>
00600 static std::nullptr_t DoIt() {
00601 static_assert(IsHashable<Key>::value,
00602 "std::hash<Key> does not provide a call operator");
00603 static_assert(
00604 std::is_default_constructible<std::hash<Key>>::value,
00605 "std::hash<Key> must be default constructible when it is enabled");
00606 static_assert(
00607 std::is_copy_constructible<std::hash<Key>>::value,
00608 "std::hash<Key> must be copy constructible when it is enabled");
00609 static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
00610 "std::hash<Key> must be copy assignable when it is enabled");
00611
00612
00613 using ReturnType = decltype(GetReturnType<Key>(0));
00614 static_assert(std::is_same<ReturnType, NAT>::value ||
00615 std::is_same<ReturnType, size_t>::value,
00616 "std::hash<Key> must return size_t");
00617 return nullptr;
00618 }
00619
00620 template <class... Ts>
00621 friend void AssertHashEnabled();
00622 };
00623
00624 template <class... Ts>
00625 inline void AssertHashEnabled() {
00626 using Helper = AssertHashEnabledHelper;
00627 Helper::Sink(Helper::DoIt<Ts>()...);
00628 }
00629
00630 }
00631
00632
00633
00634 namespace swap_internal {
00635
00636
00637 using std::swap;
00638
00639
00640
00641 void swap();
00642
00643 template <class T>
00644 using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
00645
00646
00647 template <class T,
00648 class IsNoexcept = std::integral_constant<
00649 bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
00650 using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
00651
00652
00653
00654
00655
00656 template <class T>
00657 struct IsSwappable
00658 : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
00659
00660
00661
00662
00663
00664 template <class T>
00665 struct IsNothrowSwappable
00666 : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
00667
00668
00669
00670
00671
00672 template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
00673 void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
00674 swap(lhs, rhs);
00675 }
00676
00677
00678
00679
00680
00681
00682 using StdSwapIsUnconstrained = IsSwappable<void()>;
00683
00684 }
00685
00686 namespace type_traits_internal {
00687
00688
00689 using swap_internal::IsNothrowSwappable;
00690 using swap_internal::IsSwappable;
00691 using swap_internal::Swap;
00692 using swap_internal::StdSwapIsUnconstrained;
00693
00694 }
00695 }
00696
00697 #endif // ABSL_META_TYPE_TRAITS_H_