hash_policy_testing.h
Go to the documentation of this file.
1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Utilities to help tests verify that hash tables properly handle stateful
16 // allocators and hash functions.
17 
18 #ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
19 #define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
20 
21 #include <cstdlib>
22 #include <limits>
23 #include <memory>
24 #include <ostream>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28 
29 #include "absl/hash/hash.h"
31 
32 namespace absl {
33 namespace container_internal {
34 namespace hash_testing_internal {
35 
36 template <class Derived>
37 struct WithId {
38  WithId() : id_(next_id<Derived>()) {}
39  WithId(const WithId& that) : id_(that.id_) {}
40  WithId(WithId&& that) : id_(that.id_) { that.id_ = 0; }
41  WithId& operator=(const WithId& that) {
42  id_ = that.id_;
43  return *this;
44  }
45  WithId& operator=(WithId&& that) {
46  id_ = that.id_;
47  that.id_ = 0;
48  return *this;
49  }
50 
51  size_t id() const { return id_; }
52 
53  friend bool operator==(const WithId& a, const WithId& b) {
54  return a.id_ == b.id_;
55  }
56  friend bool operator!=(const WithId& a, const WithId& b) { return !(a == b); }
57 
58  protected:
59  explicit WithId(size_t id) : id_(id) {}
60 
61  private:
62  size_t id_;
63 
64  template <class T>
65  static size_t next_id() {
66  // 0 is reserved for moved from state.
67  static size_t gId = 1;
68  return gId++;
69  }
70 };
71 
72 } // namespace hash_testing_internal
73 
76  explicit NonStandardLayout(std::string s) : value(std::move(s)) {}
77  virtual ~NonStandardLayout() {}
78 
79  friend bool operator==(const NonStandardLayout& a,
80  const NonStandardLayout& b) {
81  return a.value == b.value;
82  }
83  friend bool operator!=(const NonStandardLayout& a,
84  const NonStandardLayout& b) {
85  return a.value != b.value;
86  }
87 
88  template <typename H>
89  friend H AbslHashValue(H h, const NonStandardLayout& v) {
90  return H::combine(std::move(h), v.value);
91  }
92 
93  std::string value;
94 };
95 
98  StatefulTestingHash> {
99  template <class T>
100  size_t operator()(const T& t) const {
101  return absl::Hash<T>{}(t);
102  }
103 };
104 
107  StatefulTestingEqual> {
108  template <class T, class U>
109  bool operator()(const T& t, const U& u) const {
110  return t == u;
111  }
112 };
113 
114 // It is expected that Alloc() == Alloc() for all allocators so we cannot use
115 // WithId base. We need to explicitly assign ids.
116 template <class T = int>
117 struct Alloc : std::allocator<T> {
118  using propagate_on_container_swap = std::true_type;
119 
120  // Using old paradigm for this to ensure compatibility.
121  explicit Alloc(size_t id = 0) : id_(id) {}
122 
123  Alloc(const Alloc&) = default;
124  Alloc& operator=(const Alloc&) = default;
125 
126  template <class U>
127  Alloc(const Alloc<U>& that) : std::allocator<T>(that), id_(that.id()) {}
128 
129  template <class U>
130  struct rebind {
131  using other = Alloc<U>;
132  };
133 
134  size_t id() const { return id_; }
135 
136  friend bool operator==(const Alloc& a, const Alloc& b) {
137  return a.id_ == b.id_;
138  }
139  friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); }
140 
141  private:
142  size_t id_ = (std::numeric_limits<size_t>::max)();
143 };
144 
145 template <class Map>
146 auto items(const Map& m) -> std::vector<
147  std::pair<typename Map::key_type, typename Map::mapped_type>> {
148  using std::get;
149  std::vector<std::pair<typename Map::key_type, typename Map::mapped_type>> res;
150  res.reserve(m.size());
151  for (const auto& v : m) res.emplace_back(get<0>(v), get<1>(v));
152  return res;
153 }
154 
155 template <class Set>
156 auto keys(const Set& s)
157  -> std::vector<typename std::decay<typename Set::key_type>::type> {
158  std::vector<typename std::decay<typename Set::key_type>::type> res;
159  res.reserve(s.size());
160  for (const auto& v : s) res.emplace_back(v);
161  return res;
162 }
163 
164 } // namespace container_internal
165 } // namespace absl
166 
167 // ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions
168 // where the unordered containers are missing certain constructors that
169 // take allocator arguments. This test is defined ad-hoc for the platforms
170 // we care about (notably Crosstool 17) because libstdcxx's useless
171 // versioning scheme precludes a more principled solution.
172 // From GCC-4.9 Changelog: (src: https://gcc.gnu.org/gcc-4.9/changes.html)
173 // "the unordered associative containers in <unordered_map> and <unordered_set>
174 // meet the allocator-aware container requirements;"
175 #if (defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425 ) || \
176 ( __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9 ))
177 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 0
178 #else
179 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 1
180 #endif
181 
182 #endif // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
int v
Definition: variant_test.cc:81
friend H AbslHashValue(H h, const NonStandardLayout &v)
friend bool operator!=(const Alloc &a, const Alloc &b)
auto items(const Map &m) -> std::vector< std::pair< typename Map::key_type, typename Map::mapped_type >>
auto keys(const Set &s) -> std::vector< typename std::decay< typename Set::key_type >::type >
friend bool operator!=(const WithId &a, const WithId &b)
Definition: algorithm.h:29
size_t value
friend bool operator==(const Alloc &a, const Alloc &b)
friend bool operator==(const WithId &a, const WithId &b)
friend bool operator==(const NonStandardLayout &a, const NonStandardLayout &b)
absl::string_view get(const Cont &c)
uint64_t b
Definition: layout_test.cc:50
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219
bool operator()(const T &t, const U &u) const
friend bool operator!=(const NonStandardLayout &a, const NonStandardLayout &b)


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:18