summaryrefslogtreecommitdiff
path: root/absl/container/internal/hash_policy_traits.h
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-08-13 14:05:00 -0700
committerGravatar Gennadiy Rozental <rogeeff@google.com>2020-08-14 03:35:22 -0400
commitc6b3f2cf583d8fec124f9d70a172b513363506fe (patch)
tree25125e2b94f758297a9919288cbd95eda1bbc9e1 /absl/container/internal/hash_policy_traits.h
parent1beb3191c20ea315186dc761540d25c4939f1892 (diff)
Export of internal Abseil changes
-- 0c8282d75798c77733eee6167870bcc6acc0bfc1 by Evan Brown <ezb@google.com>: Provide mutable access to the key in node handles using std::launder when compiled with C++17 or later. Also, document why we can't provide mutable access to the key without C++17. Note: we use Policy::mutable_key() because btree already uses Policy::key() internally to get const key access, and we want to avoid calling std::launder unless we need mutable access to the key. PiperOrigin-RevId: 326519000 -- 8018d0c3044400f0a731b0d2d00b606742c98818 by Xiaoyi Zhang <zhangxy@google.com>: Move `Status` internal symbols from the public header into an internal header file. PiperOrigin-RevId: 326471847 -- 87a7644864ba7c003b0611898aaba1b71c840376 by Abseil Team <absl-team@google.com>: Avoid a costly divide (the division accounts for 10% of the time spent in the function). When the division is signed, the compiler has to generate a div. When it is unsigned, it can generate a shift: https://godbolt.org/z/vGfTv4. As per the test above the div, we know that the value is unsigned. PiperOrigin-RevId: 326453275 GitOrigin-RevId: 0c8282d75798c77733eee6167870bcc6acc0bfc1 Change-Id: I0a953558358055ab3dc6a533d8930698509b1195
Diffstat (limited to 'absl/container/internal/hash_policy_traits.h')
-rw-r--r--absl/container/internal/hash_policy_traits.h31
1 files changed, 24 insertions, 7 deletions
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index 3e1209c6..46c97b18 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -17,6 +17,7 @@
#include <cstddef>
#include <memory>
+#include <new>
#include <type_traits>
#include <utility>
@@ -29,15 +30,34 @@ namespace container_internal {
// Defines how slots are initialized/destroyed/moved.
template <class Policy, class = void>
struct hash_policy_traits {
+ // The type of the keys stored in the hashtable.
+ using key_type = typename Policy::key_type;
+
private:
struct ReturnKey {
- // We return `Key` here.
+ // When C++17 is available, we can use std::launder to provide mutable
+ // access to the key for use in node handle.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+ template <class Key,
+ absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
+ static key_type& Impl(Key&& k, int) {
+ return *std::launder(
+ const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
+ }
+#endif
+
+ template <class Key>
+ static Key Impl(Key&& k, char) {
+ return std::forward<Key>(k);
+ }
+
// When Key=T&, we forward the lvalue reference.
// When Key=T, we return by value to avoid a dangling reference.
// eg, for string_hash_map.
template <class Key, class... Args>
- Key operator()(Key&& k, const Args&...) const {
- return std::forward<Key>(k);
+ auto operator()(Key&& k, const Args&...) const
+ -> decltype(Impl(std::forward<Key>(k), 0)) {
+ return Impl(std::forward<Key>(k), 0);
}
};
@@ -52,9 +72,6 @@ struct hash_policy_traits {
// The actual object stored in the hash table.
using slot_type = typename Policy::slot_type;
- // The type of the keys stored in the hashtable.
- using key_type = typename Policy::key_type;
-
// The argument type for insertions into the hashtable. This is different
// from value_type for increased performance. See initializer_list constructor
// and insert() member functions for more details.
@@ -156,7 +173,7 @@ struct hash_policy_traits {
// Returns the "key" portion of the slot.
// Used for node handle manipulation.
template <class P = Policy>
- static auto key(slot_type* slot)
+ static auto mutable_key(slot_type* slot)
-> decltype(P::apply(ReturnKey(), element(slot))) {
return P::apply(ReturnKey(), element(slot));
}