From a4cb1c8ba61531a63f9d309eea01ac1d43d8371d Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 30 Jan 2019 10:59:43 -0800 Subject: Export of internal Abseil changes. -- 6fdf24a197b964f9bacbebd0ceca305aef1654fc by Shaindel Schwartz : Internal change PiperOrigin-RevId: 231627312 -- 65f7faf52bff01384171efb85fee159378dedf70 by CJ Johnson : Relocates the definitions of the InputIterator-accepting parts of the InlinedVector API into the top-level. The removed functions had no other callers so there was no reason to keep the layer of indirection in the form of the function call. PiperOrigin-RevId: 231527459 -- 30e105b749b5ecc50fdaf26c7da589617efce425 by CJ Johnson : Relocates closing brace for absl namespace in InlinedVector to the correct end location PiperOrigin-RevId: 231477871 -- 063c1e8b9d1f032662c46d574e20ecc357b87d0c by Eric Fiselier : Cleanup std::hash probing metafunctions. Previously there were two different ways to probe for std::hash. One in hash.h and another in type_traits.h, and they were both implemented differently, and neither correctly worked around bad STL implementations. This patch unifies the implementations into a single IsHashable trait. It also: * Correctly checks for old libc++ versions where this won't work. * Avoids undefined behavior which resulted from calling std::is_constructible incomplete types. * Unifies the feature test macro used in the headers and the tests. Additionally it also slightly changes the behavior of when absl::variant is hashable. Previously we disable hashing when std::hash()(key) was formed but when std::hash couldn't be destructed. This seems wrong. If a user provides a evil specialization of std::hash, then it's OK for variant's hash to blow up. PiperOrigin-RevId: 231468345 -- 05d75dd4b07c893de9b104731644d0d207b01253 by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 231397518 -- a0ee9032f9e04039f3410ed17fcf45ae1a3868f5 by CJ Johnson : Remove unused EnableIfAtLeastInputIterator from InlinedVector PiperOrigin-RevId: 231348903 -- 4dcd4e9a6780a81d7a6974c7bf22a037e6482b49 by Abseil Team : Remove unnecessary register keyword from absl/base/internal/endian.h. PiperOrigin-RevId: 231316570 -- c8584836caa3a10f90a8604a85d4b831310b72ee by Abseil Team : Fix hashtablez_sampler compilation on older Android NDK builds PiperOrigin-RevId: 231283542 GitOrigin-RevId: 6fdf24a197b964f9bacbebd0ceca305aef1654fc Change-Id: I185b12fb8347e3ad0ffcb2cbb83a53450e5eb938 --- absl/meta/type_traits.h | 72 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 10 deletions(-) (limited to 'absl/meta/type_traits.h') diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 23ebd6ed..88853974 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -413,21 +413,73 @@ template using result_of_t = typename std::result_of::type; namespace type_traits_internal { +// In MSVC we can't probe std::hash or stdext::hash because it triggers a +// static_assert instead of failing substitution. Libc++ prior to 4.0 +// also used a static_assert. +// +#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \ + _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11) +#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0 +#else +#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1 +#endif + +#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ template +struct IsHashable : std::true_type {}; +#else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ +template struct IsHashable : std::false_type {}; template -struct IsHashable>()(std::declval()))> - : std::true_type {}; +struct IsHashable< + Key, + absl::enable_if_t&>()(std::declval())), + std::size_t>::value>> : std::true_type {}; +#endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ + +struct AssertHashEnabledHelper { + private: + static void Sink(...) {} + struct NAT {}; + + template + static auto GetReturnType(int) + -> decltype(std::declval>()(std::declval())); + template + static NAT GetReturnType(...); + + template + static std::nullptr_t DoIt() { + static_assert(IsHashable::value, + "std::hash does not provide a call operator"); + static_assert( + std::is_default_constructible>::value, + "std::hash must be default constructible when it is enabled"); + static_assert( + std::is_copy_constructible>::value, + "std::hash must be copy constructible when it is enabled"); + static_assert(absl::is_copy_assignable>::value, + "std::hash must be copy assignable when it is enabled"); + // is_destructible is unchecked as it's implied by each of the + // is_constructible checks. + using ReturnType = decltype(GetReturnType(0)); + static_assert(std::is_same::value || + std::is_same::value, + "std::hash must return size_t"); + return nullptr; + } + + template + friend void AssertHashEnabled(); +}; -template -struct IsHashEnabled - : absl::conjunction>, - std::is_copy_constructible>, - std::is_destructible>, - absl::is_copy_assignable>, - IsHashable> {}; +template +inline void AssertHashEnabled() { + using Helper = AssertHashEnabledHelper; + Helper::Sink(Helper::DoIt()...); +} } // namespace type_traits_internal -- cgit v1.2.3