File indexing completed on 2025-01-18 09:27:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_
0016 #define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_
0017
0018 #include <cstddef>
0019 #include <memory>
0020 #include <new>
0021 #include <type_traits>
0022 #include <utility>
0023
0024 #include "absl/container/internal/common_policy_traits.h"
0025 #include "absl/meta/type_traits.h"
0026
0027 namespace absl {
0028 ABSL_NAMESPACE_BEGIN
0029 namespace container_internal {
0030
0031
0032 template <class Policy, class = void>
0033 struct hash_policy_traits : common_policy_traits<Policy> {
0034
0035 using key_type = typename Policy::key_type;
0036
0037 private:
0038 struct ReturnKey {
0039
0040
0041 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
0042 template <class Key,
0043 absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
0044 static key_type& Impl(Key&& k, int) {
0045 return *std::launder(
0046 const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
0047 }
0048 #endif
0049
0050 template <class Key>
0051 static Key Impl(Key&& k, char) {
0052 return std::forward<Key>(k);
0053 }
0054
0055
0056
0057
0058 template <class Key, class... Args>
0059 auto operator()(Key&& k, const Args&...) const
0060 -> decltype(Impl(std::forward<Key>(k), 0)) {
0061 return Impl(std::forward<Key>(k), 0);
0062 }
0063 };
0064
0065 template <class P = Policy, class = void>
0066 struct ConstantIteratorsImpl : std::false_type {};
0067
0068 template <class P>
0069 struct ConstantIteratorsImpl<P, absl::void_t<typename P::constant_iterators>>
0070 : P::constant_iterators {};
0071
0072 public:
0073
0074 using slot_type = typename Policy::slot_type;
0075
0076
0077
0078
0079 using init_type = typename Policy::init_type;
0080
0081 using reference = decltype(Policy::element(std::declval<slot_type*>()));
0082 using pointer = typename std::remove_reference<reference>::type*;
0083 using value_type = typename std::remove_reference<reference>::type;
0084
0085
0086
0087
0088
0089 using constant_iterators = ConstantIteratorsImpl<>;
0090
0091
0092
0093
0094
0095
0096
0097 template <class P = Policy>
0098 static size_t space_used(const slot_type* slot) {
0099 return P::space_used(slot);
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 template <class F, class... Ts, class P = Policy>
0132 static auto apply(F&& f, Ts&&... ts)
0133 -> decltype(P::apply(std::forward<F>(f), std::forward<Ts>(ts)...)) {
0134 return P::apply(std::forward<F>(f), std::forward<Ts>(ts)...);
0135 }
0136
0137
0138
0139 template <class P = Policy>
0140 static auto mutable_key(slot_type* slot)
0141 -> decltype(P::apply(ReturnKey(), hash_policy_traits::element(slot))) {
0142 return P::apply(ReturnKey(), hash_policy_traits::element(slot));
0143 }
0144
0145
0146
0147 template <class T, class P = Policy>
0148 static auto value(T* elem) -> decltype(P::value(elem)) {
0149 return P::value(elem);
0150 }
0151
0152 using HashSlotFn = size_t (*)(const void* hash_fn, void* slot);
0153
0154 template <class Hash>
0155 static constexpr HashSlotFn get_hash_slot_fn() {
0156
0157
0158 #if defined(__GNUC__) && !defined(__clang__)
0159 #pragma GCC diagnostic push
0160
0161 #pragma GCC diagnostic ignored "-Waddress"
0162 #endif
0163 return Policy::template get_hash_slot_fn<Hash>() == nullptr
0164 ? &hash_slot_fn_non_type_erased<Hash>
0165 : Policy::template get_hash_slot_fn<Hash>();
0166 #if defined(__GNUC__) && !defined(__clang__)
0167 #pragma GCC diagnostic pop
0168 #endif
0169 }
0170
0171
0172 static constexpr bool soo_enabled() { return soo_enabled_impl(Rank1{}); }
0173
0174 private:
0175 template <class Hash>
0176 struct HashElement {
0177 template <class K, class... Args>
0178 size_t operator()(const K& key, Args&&...) const {
0179 return h(key);
0180 }
0181 const Hash& h;
0182 };
0183
0184 template <class Hash>
0185 static size_t hash_slot_fn_non_type_erased(const void* hash_fn, void* slot) {
0186 return Policy::apply(HashElement<Hash>{*static_cast<const Hash*>(hash_fn)},
0187 Policy::element(static_cast<slot_type*>(slot)));
0188 }
0189
0190
0191 struct Rank0 {};
0192 struct Rank1 : Rank0 {};
0193
0194
0195 template <class P = Policy>
0196 static constexpr auto soo_enabled_impl(Rank1) -> decltype(P::soo_enabled()) {
0197 return P::soo_enabled();
0198 }
0199
0200 static constexpr bool soo_enabled_impl(Rank0) { return true; }
0201 };
0202
0203 }
0204 ABSL_NAMESPACE_END
0205 }
0206
0207 #endif