robin-map
robin_set.h
Go to the documentation of this file.
1 /**
2  * MIT License
3  *
4  * Copyright (c) 2017 Tessil
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef TSL_ROBIN_SET_H
25 #define TSL_ROBIN_SET_H
26 
27 
28 #include <cstddef>
29 #include <functional>
30 #include <initializer_list>
31 #include <memory>
32 #include <type_traits>
33 #include <utility>
34 #include "robin_hash.h"
35 
36 
37 namespace tsl {
38 
39 
40 /**
41  * Implementation of a hash set using open-adressing and the robin hood hashing algorithm with backward shift deletion.
42  *
43  * For operations modifying the hash set (insert, erase, rehash, ...), the strong exception guarantee
44  * is only guaranteed when the expression `std::is_nothrow_swappable<Key>::value &&
45  * std::is_nothrow_move_constructible<Key>::value` is true, otherwise if an exception
46  * is thrown during the swap or the move, the hash set may end up in a undefined state. Per the standard
47  * a `Key` with a noexcept copy constructor and no move constructor also satisfies the
48  * `std::is_nothrow_move_constructible<Key>::value` criterion (and will thus guarantee the
49  * strong exception for the set).
50  *
51  * When `StoreHash` is true, 32 bits of the hash are stored alongside the values. It can improve
52  * the performance during lookups if the `KeyEqual` function takes time (or engenders a cache-miss for example)
53  * as we then compare the stored hashes before comparing the keys. When `tsl::rh::power_of_two_growth_policy` is used
54  * as `GrowthPolicy`, it may also speed-up the rehash process as we can avoid to recalculate the hash.
55  * When it is detected that storing the hash will not incur any memory penality due to alignement (i.e.
56  * `sizeof(tsl::detail_robin_hash::bucket_entry<ValueType, true>) ==
57  * sizeof(tsl::detail_robin_hash::bucket_entry<ValueType, false>)`) and `tsl::rh::power_of_two_growth_policy` is
58  * used, the hash will be stored even if `StoreHash` is false so that we can speed-up the rehash (but it will
59  * not be used on lookups unless `StoreHash` is true).
60  *
61  * `GrowthPolicy` defines how the set grows and consequently how a hash value is mapped to a bucket.
62  * By default the set uses `tsl::rh::power_of_two_growth_policy`. This policy keeps the number of buckets
63  * to a power of two and uses a mask to set the hash to a bucket instead of the slow modulo.
64  * Other growth policies are available and you may define your own growth policy,
65  * check `tsl::rh::power_of_two_growth_policy` for the interface.
66  *
67  * `Key` must be swappable.
68  *
69  * `Key` must be copy and/or move constructible.
70  *
71  * If the destructor of `Key` throws an exception, the behaviour of the class is undefined.
72  *
73  * Iterators invalidation:
74  * - clear, operator=, reserve, rehash: always invalidate the iterators.
75  * - insert, emplace, emplace_hint, operator[]: if there is an effective insert, invalidate the iterators.
76  * - erase: always invalidate the iterators.
77  */
78 template<class Key,
79  class Hash = std::hash<Key>,
80  class KeyEqual = std::equal_to<Key>,
81  class Allocator = std::allocator<Key>,
82  bool StoreHash = false,
83  class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>>
84 class robin_set {
85 private:
86  template<typename U>
87  using has_is_transparent = tsl::detail_robin_hash::has_is_transparent<U>;
88 
89  class KeySelect {
90  public:
91  using key_type = Key;
92 
93  const key_type& operator()(const Key& key) const noexcept {
94  return key;
95  }
96 
97  key_type& operator()(Key& key) noexcept {
98  return key;
99  }
100  };
101 
102  using ht = detail_robin_hash::robin_hash<Key, KeySelect, void,
103  Hash, KeyEqual, Allocator, StoreHash, GrowthPolicy>;
104 
105 public:
106  using key_type = typename ht::key_type;
107  using value_type = typename ht::value_type;
108  using size_type = typename ht::size_type;
109  using difference_type = typename ht::difference_type;
110  using hasher = typename ht::hasher;
111  using key_equal = typename ht::key_equal;
112  using allocator_type = typename ht::allocator_type;
113  using reference = typename ht::reference;
114  using const_reference = typename ht::const_reference;
115  using pointer = typename ht::pointer;
116  using const_pointer = typename ht::const_pointer;
117  using iterator = typename ht::iterator;
118  using const_iterator = typename ht::const_iterator;
119 
120 
121  /*
122  * Constructors
123  */
124  robin_set(): robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {
125  }
126 
127  explicit robin_set(size_type bucket_count,
128  const Hash& hash = Hash(),
129  const KeyEqual& equal = KeyEqual(),
130  const Allocator& alloc = Allocator()):
131  m_ht(bucket_count, hash, equal, alloc)
132  {
133  }
134 
135  robin_set(size_type bucket_count,
136  const Allocator& alloc): robin_set(bucket_count, Hash(), KeyEqual(), alloc)
137  {
138  }
139 
140  robin_set(size_type bucket_count,
141  const Hash& hash,
142  const Allocator& alloc): robin_set(bucket_count, hash, KeyEqual(), alloc)
143  {
144  }
145 
146  explicit robin_set(const Allocator& alloc): robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
147  }
148 
149  template<class InputIt>
150  robin_set(InputIt first, InputIt last,
151  size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
152  const Hash& hash = Hash(),
153  const KeyEqual& equal = KeyEqual(),
154  const Allocator& alloc = Allocator()): robin_set(bucket_count, hash, equal, alloc)
155  {
156  insert(first, last);
157  }
158 
159  template<class InputIt>
160  robin_set(InputIt first, InputIt last,
161  size_type bucket_count,
162  const Allocator& alloc): robin_set(first, last, bucket_count, Hash(), KeyEqual(), alloc)
163  {
164  }
165 
166  template<class InputIt>
167  robin_set(InputIt first, InputIt last,
168  size_type bucket_count,
169  const Hash& hash,
170  const Allocator& alloc): robin_set(first, last, bucket_count, hash, KeyEqual(), alloc)
171  {
172  }
173 
174  robin_set(std::initializer_list<value_type> init,
175  size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
176  const Hash& hash = Hash(),
177  const KeyEqual& equal = KeyEqual(),
178  const Allocator& alloc = Allocator()):
179  robin_set(init.begin(), init.end(), bucket_count, hash, equal, alloc)
180  {
181  }
182 
183  robin_set(std::initializer_list<value_type> init,
184  size_type bucket_count,
185  const Allocator& alloc):
186  robin_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
187  {
188  }
189 
190  robin_set(std::initializer_list<value_type> init,
191  size_type bucket_count,
192  const Hash& hash,
193  const Allocator& alloc):
194  robin_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
195  {
196  }
197 
198 
199  robin_set& operator=(std::initializer_list<value_type> ilist) {
200  m_ht.clear();
201 
202  m_ht.reserve(ilist.size());
203  m_ht.insert(ilist.begin(), ilist.end());
204 
205  return *this;
206  }
207 
208  allocator_type get_allocator() const { return m_ht.get_allocator(); }
209 
210 
211  /*
212  * Iterators
213  */
214  iterator begin() noexcept { return m_ht.begin(); }
215  const_iterator begin() const noexcept { return m_ht.begin(); }
216  const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
217 
218  iterator end() noexcept { return m_ht.end(); }
219  const_iterator end() const noexcept { return m_ht.end(); }
220  const_iterator cend() const noexcept { return m_ht.cend(); }
221 
222 
223  /*
224  * Capacity
225  */
226  bool empty() const noexcept { return m_ht.empty(); }
227  size_type size() const noexcept { return m_ht.size(); }
228  size_type max_size() const noexcept { return m_ht.max_size(); }
229 
230  /*
231  * Modifiers
232  */
233  void clear() noexcept { m_ht.clear(); }
234 
235 
236 
237 
238  std::pair<iterator, bool> insert(const value_type& value) {
239  return m_ht.insert(value);
240  }
241 
242  std::pair<iterator, bool> insert(value_type&& value) {
243  return m_ht.insert(std::move(value));
244  }
245 
246  iterator insert(const_iterator hint, const value_type& value) {
247  return m_ht.insert_hint(hint, value);
248  }
249 
250  iterator insert(const_iterator hint, value_type&& value) {
251  return m_ht.insert_hint(hint, std::move(value));
252  }
253 
254  template<class InputIt>
255  void insert(InputIt first, InputIt last) {
256  m_ht.insert(first, last);
257  }
258 
259  void insert(std::initializer_list<value_type> ilist) {
260  m_ht.insert(ilist.begin(), ilist.end());
261  }
262 
263 
264 
265 
266  /**
267  * Due to the way elements are stored, emplace will need to move or copy the key-value once.
268  * The method is equivalent to insert(value_type(std::forward<Args>(args)...));
269  *
270  * Mainly here for compatibility with the std::unordered_map interface.
271  */
272  template<class... Args>
273  std::pair<iterator, bool> emplace(Args&&... args) {
274  return m_ht.emplace(std::forward<Args>(args)...);
275  }
276 
277 
278 
279  /**
280  * Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
281  * The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
282  *
283  * Mainly here for compatibility with the std::unordered_map interface.
284  */
285  template<class... Args>
286  iterator emplace_hint(const_iterator hint, Args&&... args) {
287  return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
288  }
289 
290 
291 
292  iterator erase(iterator pos) { return m_ht.erase(pos); }
293  iterator erase(const_iterator pos) { return m_ht.erase(pos); }
294  iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
295  size_type erase(const key_type& key) { return m_ht.erase(key); }
296 
297  /**
298  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
299  * as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
300  */
301  size_type erase(const key_type& key, std::size_t precalculated_hash) {
302  return m_ht.erase(key, precalculated_hash);
303  }
304 
305  /**
306  * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
307  * If so, K must be hashable and comparable to Key.
308  */
309  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
310  size_type erase(const K& key) { return m_ht.erase(key); }
311 
312  /**
313  * @copydoc erase(const K& key)
314  *
315  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
316  * as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
317  */
318  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
319  size_type erase(const K& key, std::size_t precalculated_hash) {
320  return m_ht.erase(key, precalculated_hash);
321  }
322 
323 
324 
325  void swap(robin_set& other) { other.m_ht.swap(m_ht); }
326 
327 
328 
329  /*
330  * Lookup
331  */
332  size_type count(const Key& key) const { return m_ht.count(key); }
333 
334  /**
335  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
336  * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
337  */
338  size_type count(const Key& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
339 
340  /**
341  * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
342  * If so, K must be hashable and comparable to Key.
343  */
344  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
345  size_type count(const K& key) const { return m_ht.count(key); }
346 
347  /**
348  * @copydoc count(const K& key) const
349  *
350  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
351  * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
352  */
353  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
354  size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
355 
356 
357 
358 
359  iterator find(const Key& key) { return m_ht.find(key); }
360 
361  /**
362  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
363  * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
364  */
365  iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
366 
367  const_iterator find(const Key& key) const { return m_ht.find(key); }
368 
369  /**
370  * @copydoc find(const Key& key, std::size_t precalculated_hash)
371  */
372  const_iterator find(const Key& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
373 
374  /**
375  * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
376  * If so, K must be hashable and comparable to Key.
377  */
378  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
379  iterator find(const K& key) { return m_ht.find(key); }
380 
381  /**
382  * @copydoc find(const K& key)
383  *
384  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
385  * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
386  */
387  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
388  iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
389 
390  /**
391  * @copydoc find(const K& key)
392  */
393  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
394  const_iterator find(const K& key) const { return m_ht.find(key); }
395 
396  /**
397  * @copydoc find(const K& key)
398  *
399  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
400  * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
401  */
402  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
403  const_iterator find(const K& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
404 
405 
406 
407 
408  std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
409 
410  /**
411  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
412  * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
413  */
414  std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
415  return m_ht.equal_range(key, precalculated_hash);
416  }
417 
418  std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
419 
420  /**
421  * @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
422  */
423  std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
424  return m_ht.equal_range(key, precalculated_hash);
425  }
426 
427  /**
428  * This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
429  * If so, K must be hashable and comparable to Key.
430  */
431  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
432  std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
433 
434  /**
435  * @copydoc equal_range(const K& key)
436  *
437  * Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
438  * as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
439  */
440  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
441  std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
442  return m_ht.equal_range(key, precalculated_hash);
443  }
444 
445  /**
446  * @copydoc equal_range(const K& key)
447  */
448  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
449  std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
450 
451  /**
452  * @copydoc equal_range(const K& key, std::size_t precalculated_hash)
453  */
454  template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
455  std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
456  return m_ht.equal_range(key, precalculated_hash);
457  }
458 
459 
460 
461 
462  /*
463  * Bucket interface
464  */
465  size_type bucket_count() const { return m_ht.bucket_count(); }
466  size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
467 
468 
469  /*
470  * Hash policy
471  */
472  float load_factor() const { return m_ht.load_factor(); }
473 
474  float min_load_factor() const { return m_ht.min_load_factor(); }
475  float max_load_factor() const { return m_ht.max_load_factor(); }
476 
477  /**
478  * Set the `min_load_factor` to `ml`. When the `load_factor` of the set goes
479  * below `min_load_factor` after some erase operations, the set will be
480  * shrunk when an insertion occurs. The erase method itself never shrinks
481  * the set.
482  *
483  * The default value of `min_load_factor` is 0.0f, the set never shrinks by default.
484  */
485  void min_load_factor(float ml) { m_ht.min_load_factor(ml); }
486  void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
487 
488  void rehash(size_type count) { m_ht.rehash(count); }
489  void reserve(size_type count) { m_ht.reserve(count); }
490 
491 
492  /*
493  * Observers
494  */
495  hasher hash_function() const { return m_ht.hash_function(); }
496  key_equal key_eq() const { return m_ht.key_eq(); }
497 
498 
499  /*
500  * Other
501  */
502 
503  /**
504  * Convert a const_iterator to an iterator.
505  */
506  iterator mutable_iterator(const_iterator pos) {
507  return m_ht.mutable_iterator(pos);
508  }
509 
510  friend bool operator==(const robin_set& lhs, const robin_set& rhs) {
511  if(lhs.size() != rhs.size()) {
512  return false;
513  }
514 
515  for(const auto& element_lhs: lhs) {
516  const auto it_element_rhs = rhs.find(element_lhs);
517  if(it_element_rhs == rhs.cend()) {
518  return false;
519  }
520  }
521 
522  return true;
523  }
524 
525  friend bool operator!=(const robin_set& lhs, const robin_set& rhs) {
526  return !operator==(lhs, rhs);
527  }
528 
529  friend void swap(robin_set& lhs, robin_set& rhs) {
530  lhs.swap(rhs);
531  }
532 
533 private:
534  ht m_ht;
535 };
536 
537 
538 /**
539  * Same as `tsl::robin_set<Key, Hash, KeyEqual, Allocator, StoreHash, tsl::rh::prime_growth_policy>`.
540  */
541 template<class Key,
542  class Hash = std::hash<Key>,
543  class KeyEqual = std::equal_to<Key>,
544  class Allocator = std::allocator<Key>,
545  bool StoreHash = false>
546 using robin_pg_set = robin_set<Key, Hash, KeyEqual, Allocator, StoreHash, tsl::rh::prime_growth_policy>;
547 
548 } // end namespace tsl
549 
550 #endif
const_iterator find(const Key &key) const
Definition: robin_set.h:367
size_type erase(const key_type &key, std::size_t precalculated_hash)
Definition: robin_set.h:301
size_type count(const K &key, std::size_t precalculated_hash) const
Definition: robin_set.h:354
std::pair< iterator, bool > insert(value_type &&value)
Definition: robin_set.h:242
iterator mutable_iterator(const_iterator pos)
Definition: robin_set.h:506
const_iterator begin() const noexcept
Definition: robin_set.h:215
const_iterator find(const K &key, std::size_t precalculated_hash) const
Definition: robin_set.h:403
Definition: robin_growth_policy.h:69
iterator find(const K &key, std::size_t precalculated_hash)
Definition: robin_set.h:388
iterator insert(const_iterator hint, value_type &&value)
Definition: robin_set.h:250
iterator end() noexcept
Definition: robin_set.h:218
robin_set(size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition: robin_set.h:140
robin_set(size_type bucket_count, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition: robin_set.h:127
std::pair< iterator, iterator > equal_range(const Key &key, std::size_t precalculated_hash)
Definition: robin_set.h:414
size_type erase(const key_type &key)
Definition: robin_set.h:295
iterator insert(const_iterator hint, const value_type &value)
Definition: robin_set.h:246
Definition: robin_growth_policy.h:68
size_type size() const noexcept
Definition: robin_set.h:227
std::pair< iterator, bool > emplace(Args &&... args)
Definition: robin_set.h:273
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition: robin_set.h:286
std::pair< iterator, bool > insert(const value_type &value)
Definition: robin_set.h:238
robin_set(InputIt first, InputIt last, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition: robin_set.h:167
hasher hash_function() const
Definition: robin_set.h:495
size_type bucket_count() const
Definition: robin_set.h:465
iterator erase(const_iterator first, const_iterator last)
Definition: robin_set.h:294
const_iterator cend() const noexcept
Definition: robin_set.h:220
void max_load_factor(float ml)
Definition: robin_set.h:486
friend void swap(robin_set &lhs, robin_set &rhs)
Definition: robin_set.h:529
std::pair< const_iterator, const_iterator > equal_range(const Key &key, std::size_t precalculated_hash) const
Definition: robin_set.h:423
float min_load_factor() const
Definition: robin_set.h:474
size_type erase(const K &key)
Definition: robin_set.h:310
iterator find(const K &key)
Definition: robin_set.h:379
iterator erase(const_iterator pos)
Definition: robin_set.h:293
bool empty() const noexcept
Definition: robin_set.h:226
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t precalculated_hash) const
Definition: robin_set.h:455
std::pair< iterator, iterator > equal_range(const K &key, std::size_t precalculated_hash)
Definition: robin_set.h:441
key_equal key_eq() const
Definition: robin_set.h:496
robin_set()
Definition: robin_set.h:124
const_iterator find(const Key &key, std::size_t precalculated_hash) const
Definition: robin_set.h:372
iterator erase(iterator pos)
Definition: robin_set.h:292
const_iterator find(const K &key) const
Definition: robin_set.h:394
robin_set(const Allocator &alloc)
Definition: robin_set.h:146
size_type count(const Key &key) const
Definition: robin_set.h:332
std::pair< const_iterator, const_iterator > equal_range(const Key &key) const
Definition: robin_set.h:418
robin_set(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc)
Definition: robin_set.h:160
size_type count(const K &key) const
Definition: robin_set.h:345
allocator_type get_allocator() const
Definition: robin_set.h:208
const_iterator cbegin() const noexcept
Definition: robin_set.h:216
Definition: robin_set.h:84
void min_load_factor(float ml)
Definition: robin_set.h:485
void rehash(size_type count)
Definition: robin_set.h:488
robin_set(InputIt first, InputIt last, size_type bucket_count=ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition: robin_set.h:150
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
Definition: robin_set.h:449
robin_set & operator=(std::initializer_list< value_type > ilist)
Definition: robin_set.h:199
std::pair< iterator, iterator > equal_range(const Key &key)
Definition: robin_set.h:408
Definition: robin_growth_policy.h:276
size_type count(const Key &key, std::size_t precalculated_hash) const
Definition: robin_set.h:338
friend bool operator==(const robin_set &lhs, const robin_set &rhs)
Definition: robin_set.h:510
void reserve(size_type count)
Definition: robin_set.h:489
size_type max_bucket_count() const
Definition: robin_set.h:466
robin_set(std::initializer_list< value_type > init, size_type bucket_count=ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash=Hash(), const KeyEqual &equal=KeyEqual(), const Allocator &alloc=Allocator())
Definition: robin_set.h:174
size_type erase(const K &key, std::size_t precalculated_hash)
Definition: robin_set.h:319
Definition: robin_hash.h:317
float load_factor() const
Definition: robin_set.h:472
iterator find(const Key &key)
Definition: robin_set.h:359
friend bool operator!=(const robin_set &lhs, const robin_set &rhs)
Definition: robin_set.h:525
void clear() noexcept
Definition: robin_set.h:233
const_iterator end() const noexcept
Definition: robin_set.h:219
void insert(std::initializer_list< value_type > ilist)
Definition: robin_set.h:259
std::pair< iterator, iterator > equal_range(const K &key)
Definition: robin_set.h:432
iterator find(const Key &key, std::size_t precalculated_hash)
Definition: robin_set.h:365
void insert(InputIt first, InputIt last)
Definition: robin_set.h:255
Definition: robin_growth_policy.h:78
size_type max_size() const noexcept
Definition: robin_set.h:228
void swap(robin_set &other)
Definition: robin_set.h:325
robin_set(size_type bucket_count, const Allocator &alloc)
Definition: robin_set.h:135
robin_set(std::initializer_list< value_type > init, size_type bucket_count, const Allocator &alloc)
Definition: robin_set.h:183
robin_set(std::initializer_list< value_type > init, size_type bucket_count, const Hash &hash, const Allocator &alloc)
Definition: robin_set.h:190
iterator begin() noexcept
Definition: robin_set.h:214
Definition: robin_hash.h:47
float max_load_factor() const
Definition: robin_set.h:475