about summary refs log tree commit diff
path: root/absl/meta/type_traits.h
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2019-01-30T18·59-0800
committerAshley Hedberg <ahedberg@google.com>2019-01-30T19·24-0500
commita4cb1c8ba61531a63f9d309eea01ac1d43d8371d (patch)
tree4cd407a27c50ef86e2644af93f117cf5eb2b7bd3 /absl/meta/type_traits.h
parent540e2537b92cd4abfae6ceddfe24304345461f32 (diff)
Export of internal Abseil changes.
--
6fdf24a197b964f9bacbebd0ceca305aef1654fc by Shaindel Schwartz <shaindel@google.com>:

Internal change

PiperOrigin-RevId: 231627312

--
65f7faf52bff01384171efb85fee159378dedf70 by CJ Johnson <johnsoncj@google.com>:

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 <johnsoncj@google.com>:

Relocates closing brace for absl namespace in InlinedVector to the correct end location

PiperOrigin-RevId: 231477871

--
063c1e8b9d1f032662c46d574e20ecc357b87d0c by Eric Fiselier <ericwf@google.com>:

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<T>()(key) was
formed but when std::hash<T> 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 <absl-team@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 231397518

--
a0ee9032f9e04039f3410ed17fcf45ae1a3868f5 by CJ Johnson <johnsoncj@google.com>:

Remove unused EnableIfAtLeastInputIterator from InlinedVector

PiperOrigin-RevId: 231348903

--
4dcd4e9a6780a81d7a6974c7bf22a037e6482b49 by Abseil Team <absl-team@google.com>:

Remove unnecessary register keyword from absl/base/internal/endian.h.

PiperOrigin-RevId: 231316570

--
c8584836caa3a10f90a8604a85d4b831310b72ee by Abseil Team <absl-team@google.com>:

Fix hashtablez_sampler compilation on older Android NDK builds

PiperOrigin-RevId: 231283542
GitOrigin-RevId: 6fdf24a197b964f9bacbebd0ceca305aef1654fc
Change-Id: I185b12fb8347e3ad0ffcb2cbb83a53450e5eb938
Diffstat (limited to 'absl/meta/type_traits.h')
-rw-r--r--absl/meta/type_traits.h72
1 files changed, 62 insertions, 10 deletions
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 23ebd6ed09..8885397448 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -413,21 +413,73 @@ template <typename T>
 using result_of_t = typename std::result_of<T>::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 <typename Key, typename = size_t>
+struct IsHashable : std::true_type {};
+#else   // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+template <typename Key, typename = void>
 struct IsHashable : std::false_type {};
 
 template <typename Key>
-struct IsHashable<Key,
-                  decltype(std::declval<std::hash<Key>>()(std::declval<Key>()))>
-    : std::true_type {};
+struct IsHashable<
+    Key,
+    absl::enable_if_t<std::is_convertible<
+        decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
+        std::size_t>::value>> : std::true_type {};
+#endif  // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+
+struct AssertHashEnabledHelper {
+ private:
+  static void Sink(...) {}
+  struct NAT {};
+
+  template <class Key>
+  static auto GetReturnType(int)
+      -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
+  template <class Key>
+  static NAT GetReturnType(...);
+
+  template <class Key>
+  static std::nullptr_t DoIt() {
+    static_assert(IsHashable<Key>::value,
+                  "std::hash<Key> does not provide a call operator");
+    static_assert(
+        std::is_default_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be default constructible when it is enabled");
+    static_assert(
+        std::is_copy_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be copy constructible when it is enabled");
+    static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
+                  "std::hash<Key> 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<Key>(0));
+    static_assert(std::is_same<ReturnType, NAT>::value ||
+                      std::is_same<ReturnType, size_t>::value,
+                  "std::hash<Key> must return size_t");
+    return nullptr;
+  }
+
+  template <class... Ts>
+  friend void AssertHashEnabled();
+};
 
-template <typename Key>
-struct IsHashEnabled
-    : absl::conjunction<std::is_default_constructible<std::hash<Key>>,
-                        std::is_copy_constructible<std::hash<Key>>,
-                        std::is_destructible<std::hash<Key>>,
-                        absl::is_copy_assignable<std::hash<Key>>,
-                        IsHashable<Key>> {};
+template <class... Ts>
+inline void AssertHashEnabled() {
+  using Helper = AssertHashEnabledHelper;
+  Helper::Sink(Helper::DoIt<Ts>()...);
+}
 
 }  // namespace type_traits_internal