about summary refs log tree commit diff
path: root/absl/types/optional.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/types/optional.h')
-rw-r--r--absl/types/optional.h38
1 files changed, 29 insertions, 9 deletions
diff --git a/absl/types/optional.h b/absl/types/optional.h
index 5099d4899d6d..3e010bd5d0cf 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -439,6 +439,33 @@ struct is_constructible_convertible_assignable_from_optional
 // for checking whether an expression is convertible to bool.
 bool convertible_to_bool(bool);
 
+// Base class for std::hash<absl::optional<T>>:
+// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
+// compute the hash; Otherwise, it is disabled.
+// Reference N4659 23.14.15 [unord.hash].
+template <typename T, typename = size_t>
+struct optional_hash_base {
+  optional_hash_base() = delete;
+  optional_hash_base(const optional_hash_base&) = delete;
+  optional_hash_base(optional_hash_base&&) = delete;
+  optional_hash_base& operator=(const optional_hash_base&) = delete;
+  optional_hash_base& operator=(optional_hash_base&&) = delete;
+};
+
+template <typename T>
+struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
+                                 std::declval<absl::remove_const_t<T> >()))> {
+  using argument_type = absl::optional<T>;
+  using result_type = size_t;
+  size_t operator()(const absl::optional<T>& opt) const {
+    if (opt) {
+      return std::hash<absl::remove_const_t<T> >()(*opt);
+    } else {
+      return static_cast<size_t>(0x297814aaad196e6dULL);
+    }
+  }
+};
+
 }  // namespace optional_internal
 
 // -----------------------------------------------------------------------------
@@ -1072,15 +1099,8 @@ namespace std {
 
 // std::hash specialization for absl::optional.
 template <typename T>
-struct hash<absl::optional<T>> {
-  size_t operator()(const absl::optional<T>& opt) const {
-    if (opt) {
-      return hash<T>()(*opt);
-    } else {
-      return static_cast<size_t>(0x297814aaad196e6dULL);
-    }
-  }
-};
+struct hash<absl::optional<T> >
+    : absl::optional_internal::optional_hash_base<T> {};
 
 }  // namespace std