Loading...
Searching...
No Matches
robin_set.h
1
24#ifndef PXR_TSL_ROBIN_SET_H
25#define PXR_TSL_ROBIN_SET_H
26
27#include <cstddef>
28#include <functional>
29#include <initializer_list>
30#include <memory>
31#include <type_traits>
32#include <utility>
33
34#include "robin_hash.h"
35
36// Pixar modification, modify namespace for isolation.
37#include "pxr/pxr.h"
38
39PXR_NAMESPACE_OPEN_SCOPE
40
41namespace pxr_tsl {
42
91template <class Key, class Hash = std::hash<Key>,
92 class KeyEqual = std::equal_to<Key>,
93 class Allocator = std::allocator<Key>, bool StoreHash = false,
94 class GrowthPolicy = pxr_tsl::rh::power_of_two_growth_policy<2>>
95class robin_set {
96 private:
97 template <typename U>
98 using has_is_transparent = pxr_tsl::detail_robin_hash::has_is_transparent<U>;
99
100 class KeySelect {
101 public:
102 using key_type = Key;
103
104 const key_type& operator()(const Key& key) const noexcept { return key; }
105
106 key_type& operator()(Key& key) noexcept { return key; }
107 };
108
109 using ht = detail_robin_hash::robin_hash<Key, KeySelect, void, Hash, KeyEqual,
110 Allocator, StoreHash, GrowthPolicy>;
111
112 public:
113 using key_type = typename ht::key_type;
114 using value_type = typename ht::value_type;
115 using size_type = typename ht::size_type;
116 using difference_type = typename ht::difference_type;
117 using hasher = typename ht::hasher;
118 using key_equal = typename ht::key_equal;
119 using allocator_type = typename ht::allocator_type;
120 using reference = typename ht::reference;
121 using const_reference = typename ht::const_reference;
122 using pointer = typename ht::pointer;
123 using const_pointer = typename ht::const_pointer;
124 using iterator = typename ht::iterator;
125 using const_iterator = typename ht::const_iterator;
126
127 /*
128 * Constructors
129 */
130 robin_set() : robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {}
131
132 explicit robin_set(size_type bucket_count, const Hash& hash = Hash(),
133 const KeyEqual& equal = KeyEqual(),
134 const Allocator& alloc = Allocator())
135 : m_ht(bucket_count, hash, equal, alloc) {}
136
137 robin_set(size_type bucket_count, const Allocator& alloc)
138 : robin_set(bucket_count, Hash(), KeyEqual(), alloc) {}
139
140 robin_set(size_type bucket_count, const Hash& hash, const Allocator& alloc)
141 : robin_set(bucket_count, hash, KeyEqual(), alloc) {}
142
143 explicit robin_set(const Allocator& alloc)
144 : robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {}
145
146 template <class InputIt>
147 robin_set(InputIt first, InputIt last,
148 size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
149 const Hash& hash = Hash(), const KeyEqual& equal = KeyEqual(),
150 const Allocator& alloc = Allocator())
151 : robin_set(bucket_count, hash, equal, alloc) {
152 insert(first, last);
153 }
154
155 template <class InputIt>
156 robin_set(InputIt first, InputIt last, size_type bucket_count,
157 const Allocator& alloc)
158 : robin_set(first, last, bucket_count, Hash(), KeyEqual(), alloc) {}
159
160 template <class InputIt>
161 robin_set(InputIt first, InputIt last, size_type bucket_count,
162 const Hash& hash, const Allocator& alloc)
163 : robin_set(first, last, bucket_count, hash, KeyEqual(), alloc) {}
164
165 robin_set(std::initializer_list<value_type> init,
166 size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
167 const Hash& hash = Hash(), const KeyEqual& equal = KeyEqual(),
168 const Allocator& alloc = Allocator())
169 : robin_set(init.begin(), init.end(), bucket_count, hash, equal, alloc) {}
170
171 robin_set(std::initializer_list<value_type> init, size_type bucket_count,
172 const Allocator& alloc)
173 : robin_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(),
174 alloc) {}
175
176 robin_set(std::initializer_list<value_type> init, size_type bucket_count,
177 const Hash& hash, const Allocator& alloc)
178 : robin_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(),
179 alloc) {}
180
181 robin_set& operator=(std::initializer_list<value_type> ilist) {
182 m_ht.clear();
183
184 m_ht.reserve(ilist.size());
185 m_ht.insert(ilist.begin(), ilist.end());
186
187 return *this;
188 }
189
190 allocator_type get_allocator() const { return m_ht.get_allocator(); }
191
192 /*
193 * Iterators
194 */
195 iterator begin() noexcept { return m_ht.begin(); }
196 const_iterator begin() const noexcept { return m_ht.begin(); }
197 const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
198
199 iterator end() noexcept { return m_ht.end(); }
200 const_iterator end() const noexcept { return m_ht.end(); }
201 const_iterator cend() const noexcept { return m_ht.cend(); }
202
203 /*
204 * Capacity
205 */
206 bool empty() const noexcept { return m_ht.empty(); }
207 size_type size() const noexcept { return m_ht.size(); }
208 size_type max_size() const noexcept { return m_ht.max_size(); }
209
210 /*
211 * Modifiers
212 */
213 void clear() noexcept { m_ht.clear(); }
214
215 std::pair<iterator, bool> insert(const value_type& value) {
216 return m_ht.insert(value);
217 }
218
219 std::pair<iterator, bool> insert(value_type&& value) {
220 return m_ht.insert(std::move(value));
221 }
222
223 iterator insert(const_iterator hint, const value_type& value) {
224 return m_ht.insert_hint(hint, value);
225 }
226
227 iterator insert(const_iterator hint, value_type&& value) {
228 return m_ht.insert_hint(hint, std::move(value));
229 }
230
231 template <class InputIt>
232 void insert(InputIt first, InputIt last) {
233 m_ht.insert(first, last);
234 }
235
236 void insert(std::initializer_list<value_type> ilist) {
237 m_ht.insert(ilist.begin(), ilist.end());
238 }
239
247 template <class... Args>
248 std::pair<iterator, bool> emplace(Args&&... args) {
249 return m_ht.emplace(std::forward<Args>(args)...);
250 }
251
259 template <class... Args>
260 iterator emplace_hint(const_iterator hint, Args&&... args) {
261 return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
262 }
263
264 iterator erase(iterator pos) { return m_ht.erase(pos); }
265 iterator erase(const_iterator pos) { return m_ht.erase(pos); }
266 iterator erase(const_iterator first, const_iterator last) {
267 return m_ht.erase(first, last);
268 }
269 size_type erase(const key_type& key) { return m_ht.erase(key); }
270
276 size_type erase(const key_type& key, std::size_t precalculated_hash) {
277 return m_ht.erase(key, precalculated_hash);
278 }
279
285 template <
286 class K, class KE = KeyEqual,
287 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
288 size_type erase(const K& key) {
289 return m_ht.erase(key);
290 }
291
299 template <
300 class K, class KE = KeyEqual,
301 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
302 size_type erase(const K& key, std::size_t precalculated_hash) {
303 return m_ht.erase(key, precalculated_hash);
304 }
305
306 void swap(robin_set& other) { other.m_ht.swap(m_ht); }
307
308 /*
309 * Lookup
310 */
311 size_type count(const Key& key) const { return m_ht.count(key); }
312
318 size_type count(const Key& key, std::size_t precalculated_hash) const {
319 return m_ht.count(key, precalculated_hash);
320 }
321
327 template <
328 class K, class KE = KeyEqual,
329 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
330 size_type count(const K& key) const {
331 return m_ht.count(key);
332 }
333
341 template <
342 class K, class KE = KeyEqual,
343 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
344 size_type count(const K& key, std::size_t precalculated_hash) const {
345 return m_ht.count(key, precalculated_hash);
346 }
347
348 iterator find(const Key& key) { return m_ht.find(key); }
349
355 iterator find(const Key& key, std::size_t precalculated_hash) {
356 return m_ht.find(key, precalculated_hash);
357 }
358
359 const_iterator find(const Key& key) const { return m_ht.find(key); }
360
364 const_iterator find(const Key& key, std::size_t precalculated_hash) const {
365 return m_ht.find(key, precalculated_hash);
366 }
367
373 template <
374 class K, class KE = KeyEqual,
375 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
376 iterator find(const K& key) {
377 return m_ht.find(key);
378 }
379
387 template <
388 class K, class KE = KeyEqual,
389 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
390 iterator find(const K& key, std::size_t precalculated_hash) {
391 return m_ht.find(key, precalculated_hash);
392 }
393
397 template <
398 class K, class KE = KeyEqual,
399 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
400 const_iterator find(const K& key) const {
401 return m_ht.find(key);
402 }
403
411 template <
412 class K, class KE = KeyEqual,
413 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
414 const_iterator find(const K& key, std::size_t precalculated_hash) const {
415 return m_ht.find(key, precalculated_hash);
416 }
417
418 bool contains(const Key& key) const { return m_ht.contains(key); }
419
425 bool contains(const Key& key, std::size_t precalculated_hash) const {
426 return m_ht.contains(key, precalculated_hash);
427 }
428
434 template <
435 class K, class KE = KeyEqual,
436 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
437 bool contains(const K& key) const {
438 return m_ht.contains(key);
439 }
440
448 template <
449 class K, class KE = KeyEqual,
450 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
451 bool contains(const K& key, std::size_t precalculated_hash) const {
452 return m_ht.contains(key, precalculated_hash);
453 }
454
455 std::pair<iterator, iterator> equal_range(const Key& key) {
456 return m_ht.equal_range(key);
457 }
458
464 std::pair<iterator, iterator> equal_range(const Key& key,
465 std::size_t precalculated_hash) {
466 return m_ht.equal_range(key, precalculated_hash);
467 }
468
469 std::pair<const_iterator, const_iterator> equal_range(const Key& key) const {
470 return m_ht.equal_range(key);
471 }
472
476 std::pair<const_iterator, const_iterator> equal_range(
477 const Key& key, std::size_t precalculated_hash) const {
478 return m_ht.equal_range(key, precalculated_hash);
479 }
480
486 template <
487 class K, class KE = KeyEqual,
488 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
489 std::pair<iterator, iterator> equal_range(const K& key) {
490 return m_ht.equal_range(key);
491 }
492
500 template <
501 class K, class KE = KeyEqual,
502 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
503 std::pair<iterator, iterator> equal_range(const K& key,
504 std::size_t precalculated_hash) {
505 return m_ht.equal_range(key, precalculated_hash);
506 }
507
511 template <
512 class K, class KE = KeyEqual,
513 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
514 std::pair<const_iterator, const_iterator> equal_range(const K& key) const {
515 return m_ht.equal_range(key);
516 }
517
521 template <
522 class K, class KE = KeyEqual,
523 typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
524 std::pair<const_iterator, const_iterator> equal_range(
525 const K& key, std::size_t precalculated_hash) const {
526 return m_ht.equal_range(key, precalculated_hash);
527 }
528
529 /*
530 * Bucket interface
531 */
532 size_type bucket_count() const { return m_ht.bucket_count(); }
533 size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
534
535 /*
536 * Hash policy
537 */
538 float load_factor() const { return m_ht.load_factor(); }
539
540 float min_load_factor() const { return m_ht.min_load_factor(); }
541 float max_load_factor() const { return m_ht.max_load_factor(); }
542
552 void min_load_factor(float ml) { m_ht.min_load_factor(ml); }
553 void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
554
555 void rehash(size_type count_) { m_ht.rehash(count_); }
556 void reserve(size_type count_) { m_ht.reserve(count_); }
557
558 /*
559 * Observers
560 */
561 hasher hash_function() const { return m_ht.hash_function(); }
562 key_equal key_eq() const { return m_ht.key_eq(); }
563
564 /*
565 * Other
566 */
567
571 iterator mutable_iterator(const_iterator pos) {
572 return m_ht.mutable_iterator(pos);
573 }
574
575 friend bool operator==(const robin_set& lhs, const robin_set& rhs) {
576 if (lhs.size() != rhs.size()) {
577 return false;
578 }
579
580 for (const auto& element_lhs : lhs) {
581 const auto it_element_rhs = rhs.find(element_lhs);
582 if (it_element_rhs == rhs.cend()) {
583 return false;
584 }
585 }
586
587 return true;
588 }
589
603 template <class Serializer>
604 void serialize(Serializer& serializer) const {
605 m_ht.serialize(serializer);
606 }
607
634 template <class Deserializer>
635 static robin_set deserialize(Deserializer& deserializer,
636 bool hash_compatible = false) {
637 robin_set set(0);
638 set.m_ht.deserialize(deserializer, hash_compatible);
639
640 return set;
641 }
642
643 friend bool operator!=(const robin_set& lhs, const robin_set& rhs) {
644 return !operator==(lhs, rhs);
645 }
646
647 friend void swap(robin_set& lhs, robin_set& rhs) { lhs.swap(rhs); }
648
649 private:
650 ht m_ht;
651};
652
657template <class Key, class Hash = std::hash<Key>,
658 class KeyEqual = std::equal_to<Key>,
659 class Allocator = std::allocator<Key>, bool StoreHash = false>
660using robin_pg_set = robin_set<Key, Hash, KeyEqual, Allocator, StoreHash,
662
663} // end namespace pxr_tsl
664
665PXR_NAMESPACE_CLOSE_SCOPE
666
667#endif
The 'operator*()' and 'operator->()' methods return a const reference and const pointer respectively ...
Definition: robin_hash.h:448
Internal common class used by robin_map and robin_set.
Definition: robin_hash.h:354
iterator erase(iterator pos)
Here to avoid template<class K> size_type erase(const K& key) being used when we use an iterator inst...
Definition: robin_hash.h:824
Grow the hash table by using prime numbers as bucket count.
Implementation of a hash set using open-addressing and the robin hood hashing algorithm with backward...
Definition: robin_set.h:95
std::pair< iterator, iterator > equal_range(const Key &key, std::size_t precalculated_hash)
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_set.h:464
bool contains(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_set.h:425
const_iterator find(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:414
const_iterator find(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_set.h:364
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:514
std::pair< const_iterator, const_iterator > equal_range(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_set.h:476
std::pair< iterator, iterator > equal_range(const K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:489
bool contains(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:451
void min_load_factor(float ml)
Set the min_load_factor to ml.
Definition: robin_set.h:552
size_type count(const Key &key, std::size_t precalculated_hash) const
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_set.h:318
const_iterator find(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:400
std::pair< const_iterator, const_iterator > equal_range(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:524
size_type erase(const key_type &key, std::size_t precalculated_hash)
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_set.h:276
iterator find(const Key &key, std::size_t precalculated_hash)
Use the hash value 'precalculated_hash' instead of hashing the key.
Definition: robin_set.h:355
iterator mutable_iterator(const_iterator pos)
Convert a const_iterator to an iterator.
Definition: robin_set.h:571
iterator emplace_hint(const_iterator hint, Args &&... args)
Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
Definition: robin_set.h:260
iterator find(const K &key, std::size_t precalculated_hash)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:390
bool contains(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:437
size_type count(const K &key) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:330
std::pair< iterator, bool > emplace(Args &&... args)
Due to the way elements are stored, emplace will need to move or copy the key-value once.
Definition: robin_set.h:248
static robin_set deserialize(Deserializer &deserializer, bool hash_compatible=false)
Deserialize a previously serialized set through the deserializer parameter.
Definition: robin_set.h:635
size_type erase(const K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:288
iterator find(const K &key)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:376
size_type erase(const K &key, std::size_t precalculated_hash)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:302
std::pair< iterator, iterator > equal_range(const K &key, std::size_t precalculated_hash)
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:503
size_type count(const K &key, std::size_t precalculated_hash) const
This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent ex...
Definition: robin_set.h:344
void serialize(Serializer &serializer) const
Serialize the set through the serializer parameter.
Definition: robin_set.h:604
MIT License.