Blender V5.0
BLI_set.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
57
58#include "BLI_array.hh"
59#include "BLI_hash.hh"
60#include "BLI_hash_tables.hh"
62#include "BLI_set_slots.hh"
63
64namespace blender {
65
66template<
71 typename Key,
77 int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key)),
81 typename ProbingStrategy = DefaultProbingStrategy,
86 typename Hash = DefaultHash<Key>,
91 typename IsEqual = DefaultEquality<Key>,
100 typename Slot = typename DefaultSetSlot<Key>::type,
105 typename Allocator = GuardedAllocator>
106class Set {
107 public:
108 class Iterator;
110 using pointer = Key *;
111 using const_pointer = const Key *;
112 using reference = Key &;
113 using const_reference = const Key &;
114 using iterator = Iterator;
116
117 private:
122 int64_t removed_slots_;
123 int64_t occupied_and_removed_slots_;
124
129 int64_t usable_slots_;
130
135 uint64_t slot_mask_;
136
138 BLI_NO_UNIQUE_ADDRESS Hash hash_;
139
141 BLI_NO_UNIQUE_ADDRESS IsEqual is_equal_;
142
144#define LOAD_FACTOR 1, 2
145 static constexpr LoadFactor max_load_factor_ = LoadFactor(LOAD_FACTOR);
146 using SlotArray =
147 Array<Slot, LoadFactor::compute_total_slots(InlineBufferCapacity, LOAD_FACTOR), Allocator>;
148#undef LOAD_FACTOR
149
154 SlotArray slots_;
155
157#define SET_SLOT_PROBING_BEGIN(HASH, R_SLOT) \
158 SLOT_PROBING_BEGIN (ProbingStrategy, HASH, slot_mask_, SLOT_INDEX) \
159 auto &R_SLOT = slots_[SLOT_INDEX];
160#define SET_SLOT_PROBING_END() SLOT_PROBING_END()
161
162 public:
168 Set(Allocator allocator = {}) noexcept
169 : removed_slots_(0),
170 occupied_and_removed_slots_(0),
171 usable_slots_(0),
172 slot_mask_(0),
173 slots_(1, allocator)
174 {
175 }
176
177 Set(NoExceptConstructor, Allocator allocator = {}) noexcept : Set(allocator) {}
178
179 Set(Span<Key> values, Allocator allocator = {}) : Set(NoExceptConstructor(), allocator)
180 {
181 this->add_multiple(values);
182 }
183
187 Set(const std::initializer_list<Key> &values) : Set(Span<Key>(values)) {}
188
189 ~Set() = default;
190
191 Set(const Set &other) = default;
192
193 Set(Set &&other) noexcept(std::is_nothrow_move_constructible_v<SlotArray>)
194 : Set(NoExceptConstructor(), other.slots_.allocator())
195
196 {
197 if constexpr (std::is_nothrow_move_constructible_v<SlotArray>) {
198 slots_ = std::move(other.slots_);
199 }
200 else {
201 try {
202 slots_ = std::move(other.slots_);
203 }
204 catch (...) {
205 other.noexcept_reset();
206 throw;
207 }
208 }
209 removed_slots_ = other.removed_slots_;
210 occupied_and_removed_slots_ = other.occupied_and_removed_slots_;
211 usable_slots_ = other.usable_slots_;
212 slot_mask_ = other.slot_mask_;
213 hash_ = std::move(other.hash_);
214 is_equal_ = std::move(other.is_equal_);
215 other.noexcept_reset();
216 }
217
218 Set &operator=(const Set &other)
219 {
220 return copy_assign_container(*this, other);
221 }
222
223 Set &operator=(Set &&other)
224 {
225 return move_assign_container(*this, std::move(other));
226 }
227
233 void add_new(const Key &key)
234 {
235 this->add_new__impl(key, hash_(key));
236 }
237 void add_new(Key &&key)
238 {
239 this->add_new__impl(std::move(key), hash_(key));
240 }
241
248 bool add(const Key &key)
249 {
250 return this->add_as(key);
251 }
252 bool add(Key &&key)
253 {
254 return this->add_as(std::move(key));
255 }
256 template<typename ForwardKey> bool add_as(ForwardKey &&key)
257 {
258 return this->add__impl(std::forward<ForwardKey>(key), hash_(key));
259 }
260
267 bool add_overwrite(const Key &key)
268 {
269 return this->add_overwrite_as(key);
270 }
271 bool add_overwrite(Key &&key)
272 {
273 return this->add_overwrite_as(std::move(key));
274 }
275 template<typename ForwardKey> bool add_overwrite_as(ForwardKey &&key)
276 {
277 return this->add_overwrite__impl(std::forward<ForwardKey>(key), hash_(key));
278 }
279
288 {
289 for (const Key &key : keys) {
290 this->add(key);
291 }
292 }
293
299 {
300 for (const Key &key : keys) {
301 this->add_new(key);
302 }
303 }
304
310 bool contains(const Key &key) const
311 {
312 return this->contains_as(key);
313 }
314 template<typename ForwardKey> bool contains_as(const ForwardKey &key) const
315 {
316 return this->contains__impl(key, hash_(key));
317 }
318
323 const Key &lookup_key(const Key &key) const
324 {
325 return this->lookup_key_as(key);
326 }
327 template<typename ForwardKey> const Key &lookup_key_as(const ForwardKey &key) const
328 {
329 return this->lookup_key__impl(key, hash_(key));
330 }
331
336 const Key &lookup_key_default(const Key &key, const Key &default_value) const
337 {
338 return this->lookup_key_default_as(key, default_value);
339 }
340 template<typename ForwardKey>
341 const Key &lookup_key_default_as(const ForwardKey &key, const Key &default_key) const
342 {
343 const Key *ptr = this->lookup_key_ptr__impl(key, hash_(key));
344 if (ptr == nullptr) {
345 return default_key;
346 }
347 return *ptr;
348 }
349
354 const Key *lookup_key_ptr(const Key &key) const
355 {
356 return this->lookup_key_ptr_as(key);
357 }
358 template<typename ForwardKey> const Key *lookup_key_ptr_as(const ForwardKey &key) const
359 {
360 return this->lookup_key_ptr__impl(key, hash_(key));
361 }
362
367 const Key &lookup_key_or_add(const Key &key)
368 {
369 return this->lookup_key_or_add_as(key);
370 }
372 {
373 return this->lookup_key_or_add_as(std::move(key));
374 }
375 template<typename ForwardKey> const Key &lookup_key_or_add_as(ForwardKey &&key)
376 {
377 return this->lookup_key_or_add__impl(std::forward<ForwardKey>(key), hash_(key));
378 }
379
385 bool remove(const Key &key)
386 {
387 return this->remove_as(key);
388 }
389 template<typename ForwardKey> bool remove_as(const ForwardKey &key)
390 {
391 return this->remove__impl(key, hash_(key));
392 }
393
397 void remove_contained(const Key &key)
398 {
399 this->remove_contained_as(key);
400 }
401 template<typename ForwardKey> void remove_contained_as(const ForwardKey &key)
402 {
403 this->remove_contained__impl(key, hash_(key));
404 }
405
413 class Iterator {
414 public:
415 using iterator_category = std::forward_iterator_tag;
417 using pointer = const Key *;
418 using reference = const Key &;
419 using difference_type = std::ptrdiff_t;
420
421 private:
422 const Slot *slots_;
423 int64_t total_slots_;
424 int64_t current_slot_;
425
426 friend Set;
427
428 public:
429 Iterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
430 : slots_(slots), total_slots_(total_slots), current_slot_(current_slot)
431 {
432 }
433
435 {
436 while (++current_slot_ < total_slots_) {
437 if (slots_[current_slot_].is_occupied()) {
438 break;
439 }
440 }
441 return *this;
442 }
443
445 {
446 Iterator copied_iterator = *this;
447 ++(*this);
448 return copied_iterator;
449 }
450
451 const Key &operator*() const
452 {
453 return *slots_[current_slot_].key();
454 }
455
456 const Key *operator->() const
457 {
458 return slots_[current_slot_].key();
459 }
460
461 friend bool operator!=(const Iterator &a, const Iterator &b)
462 {
463 BLI_assert(a.slots_ == b.slots_);
464 BLI_assert(a.total_slots_ == b.total_slots_);
465 return a.current_slot_ != b.current_slot_;
466 }
467
468 friend bool operator==(const Iterator &a, const Iterator &b)
469 {
470 return !(a != b);
471 }
472
473 protected:
474 const Slot &current_slot() const
475 {
476 return slots_[current_slot_];
477 }
478 };
479
480 Iterator begin() const
481 {
482 for (int64_t i = 0; i < slots_.size(); i++) {
483 if (slots_[i].is_occupied()) {
484 return Iterator(slots_.data(), slots_.size(), i);
485 }
486 }
487 return this->end();
488 }
489
490 Iterator end() const
491 {
492 return Iterator(slots_.data(), slots_.size(), slots_.size());
493 }
494
500 void remove(const Iterator &it)
501 {
502 /* The const cast is valid because this method itself is not const. */
503 Slot &slot = const_cast<Slot &>(it.current_slot());
504 BLI_assert(slot.is_occupied());
505 slot.remove();
506 removed_slots_++;
507 }
508
515 template<typename Predicate> int64_t remove_if(Predicate &&predicate)
516 {
517 const int64_t prev_size = this->size();
518 for (Slot &slot : slots_) {
519 if (slot.is_occupied()) {
520 const Key &key = *slot.key();
521 if (predicate(key)) {
522 slot.remove();
523 removed_slots_++;
524 }
525 }
526 }
527 return prev_size - this->size();
528 }
529
533 void print_stats(const char *name) const
534 {
535 HashTableStats stats(*this, *this);
536 stats.print(name);
537 }
538
543 int64_t count_collisions(const Key &key) const
544 {
545 return this->count_collisions__impl(key, hash_(key));
546 }
547
551 void clear()
552 {
553 std::destroy_at(this);
554 new (this) Set(NoExceptConstructor{});
555 }
556
565 {
566 for (Slot &slot : slots_) {
567 slot.~Slot();
568 new (&slot) Slot();
569 }
570
571 removed_slots_ = 0;
572 occupied_and_removed_slots_ = 0;
573 }
574
579 void rehash()
580 {
581 this->realloc_and_reinsert(this->size());
582 }
583
587 int64_t size() const
588 {
589 return occupied_and_removed_slots_ - removed_slots_;
590 }
591
595 bool is_empty() const
596 {
597 return occupied_and_removed_slots_ == removed_slots_;
598 }
599
604 {
605 return slots_.size();
606 }
607
612 {
613 return removed_slots_;
614 }
615
620 {
621 return sizeof(Slot);
622 }
623
629 {
630 return sizeof(Slot) * slots_.size();
631 }
632
637 void reserve(const int64_t n)
638 {
639 if (usable_slots_ < n) {
640 this->realloc_and_reinsert(n);
641 }
642 }
643
647 static bool Intersects(const Set &a, const Set &b)
648 {
649 /* Make sure we iterate over the shorter set. */
650 if (a.size() > b.size()) {
651 return Intersects(b, a);
652 }
653
654 for (const Key &key : a) {
655 if (b.contains(key)) {
656 return true;
657 }
658 }
659 return false;
660 }
661
665 static bool Disjoint(const Set &a, const Set &b)
666 {
667 return !Intersects(a, b);
668 }
669
670 friend bool operator==(const Set &a, const Set &b)
671 {
672 if (a.size() != b.size()) {
673 return false;
674 }
675 for (const Key &key : a) {
676 if (!b.contains(key)) {
677 return false;
678 }
679 }
680 return true;
681 }
682
683 friend bool operator!=(const Set &a, const Set &b)
684 {
685 return !(a == b);
686 }
687
688 private:
689 BLI_NOINLINE void realloc_and_reinsert(const int64_t min_usable_slots)
690 {
691 int64_t total_slots, usable_slots;
692 max_load_factor_.compute_total_and_usable_slots(
693 SlotArray::inline_buffer_capacity(), min_usable_slots, &total_slots, &usable_slots);
694 BLI_assert(total_slots >= 1);
695 const uint64_t new_slot_mask = uint64_t(total_slots) - 1;
696
700 if (this->size() == 0) {
701 try {
702 slots_.reinitialize(total_slots);
703 }
704 catch (...) {
705 this->noexcept_reset();
706 throw;
707 }
708 removed_slots_ = 0;
709 occupied_and_removed_slots_ = 0;
710 usable_slots_ = usable_slots;
711 slot_mask_ = new_slot_mask;
712 return;
713 }
714
715 /* The grown array that we insert the keys into. */
716 SlotArray new_slots(total_slots);
717
718 try {
719 for (Slot &slot : slots_) {
720 if (slot.is_occupied()) {
721 this->add_after_grow(slot, new_slots, new_slot_mask);
722 slot.remove();
723 }
724 }
725 slots_ = std::move(new_slots);
726 }
727 catch (...) {
728 this->noexcept_reset();
729 throw;
730 }
731
732 occupied_and_removed_slots_ -= removed_slots_;
733 usable_slots_ = usable_slots;
734 removed_slots_ = 0;
735 slot_mask_ = new_slot_mask;
736 }
737
738 void add_after_grow(Slot &old_slot, SlotArray &new_slots, const uint64_t new_slot_mask)
739 {
740 const uint64_t hash = old_slot.get_hash(Hash());
741
742 SLOT_PROBING_BEGIN (ProbingStrategy, hash, new_slot_mask, slot_index) {
743 Slot &slot = new_slots[slot_index];
744 if (slot.is_empty()) {
745 slot.occupy(std::move(*old_slot.key()), hash);
746 return;
747 }
748 }
750 }
751
756 void noexcept_reset() noexcept
757 {
758 Allocator allocator = slots_.allocator();
759 this->~Set();
760 new (this) Set(NoExceptConstructor(), allocator);
761 }
762
763 template<typename ForwardKey>
764 bool contains__impl(const ForwardKey &key, const uint64_t hash) const
765 {
767 if (slot.is_empty()) {
768 return false;
769 }
770 if (slot.contains(key, is_equal_, hash)) {
771 return true;
772 }
773 }
775 }
776
777 template<typename ForwardKey>
778 const Key &lookup_key__impl(const ForwardKey &key, const uint64_t hash) const
779 {
780 BLI_assert(this->contains_as(key));
781
783 if (slot.contains(key, is_equal_, hash)) {
784 return *slot.key();
785 }
786 }
788 }
789
790 template<typename ForwardKey>
791 const Key *lookup_key_ptr__impl(const ForwardKey &key, const uint64_t hash) const
792 {
794 if (slot.contains(key, is_equal_, hash)) {
795 return slot.key();
796 }
797 if (slot.is_empty()) {
798 return nullptr;
799 }
800 }
802 }
803
804 template<typename ForwardKey> void add_new__impl(ForwardKey &&key, const uint64_t hash)
805 {
806 BLI_assert(!this->contains_as(key));
807
808 this->ensure_can_add();
809
811 if (slot.is_empty()) {
812 slot.occupy(std::forward<ForwardKey>(key), hash);
813 BLI_assert(hash_(*slot.key()) == hash);
814 occupied_and_removed_slots_++;
815 return;
816 }
817 }
819 }
820
821 template<typename ForwardKey> bool add__impl(ForwardKey &&key, const uint64_t hash)
822 {
823 this->ensure_can_add();
824
826 if (slot.is_empty()) {
827 slot.occupy(std::forward<ForwardKey>(key), hash);
828 BLI_assert(hash_(*slot.key()) == hash);
829 occupied_and_removed_slots_++;
830 return true;
831 }
832 if (slot.contains(key, is_equal_, hash)) {
833 return false;
834 }
835 }
837 }
838
839 template<typename ForwardKey> bool add_overwrite__impl(ForwardKey &&key, const uint64_t hash)
840 {
841 this->ensure_can_add();
842
844 if (slot.is_empty()) {
845 slot.occupy(std::forward<ForwardKey>(key), hash);
846 BLI_assert(hash_(*slot.key()) == hash);
847 occupied_and_removed_slots_++;
848 return true;
849 }
850 if (slot.contains(key, is_equal_, hash)) {
851 Key &stored_key = *slot.key();
852 stored_key = std::forward<ForwardKey>(key);
853 BLI_assert(hash_(stored_key) == hash);
854 return false;
855 }
856 }
858 }
859
860 template<typename ForwardKey> bool remove__impl(const ForwardKey &key, const uint64_t hash)
861 {
863 if (slot.contains(key, is_equal_, hash)) {
864 slot.remove();
865 removed_slots_++;
866 return true;
867 }
868 if (slot.is_empty()) {
869 return false;
870 }
871 }
873 }
874
875 template<typename ForwardKey>
876 void remove_contained__impl(const ForwardKey &key, const uint64_t hash)
877 {
878 BLI_assert(this->contains_as(key));
879
881 if (slot.contains(key, is_equal_, hash)) {
882 slot.remove();
883 removed_slots_++;
884 return;
885 }
886 }
888 }
889
890 template<typename ForwardKey>
891 const Key &lookup_key_or_add__impl(ForwardKey &&key, const uint64_t hash)
892 {
893 this->ensure_can_add();
894
896 if (slot.contains(key, is_equal_, hash)) {
897 return *slot.key();
898 }
899 if (slot.is_empty()) {
900 slot.occupy(std::forward<ForwardKey>(key), hash);
901 BLI_assert(hash_(*slot.key()) == hash);
902 occupied_and_removed_slots_++;
903 return *slot.key();
904 }
905 }
907 }
908
909 template<typename ForwardKey>
910 int64_t count_collisions__impl(const ForwardKey &key, const uint64_t hash) const
911 {
912 int64_t collisions = 0;
913
915 if (slot.contains(key, is_equal_, hash)) {
916 return collisions;
917 }
918 if (slot.is_empty()) {
919 return collisions;
920 }
921 collisions++;
922 }
924 }
925
926 void ensure_can_add()
927 {
928 if (occupied_and_removed_slots_ >= usable_slots_) {
929 this->realloc_and_reinsert(this->size() + 1);
930 BLI_assert(occupied_and_removed_slots_ < usable_slots_);
931 }
932 }
933};
934
939template<typename Key,
940 int64_t InlineBufferCapacity = default_inline_buffer_capacity(sizeof(Key)),
941 typename ProbingStrategy = DefaultProbingStrategy,
942 typename Hash = DefaultHash<Key>,
943 typename IsEqual = DefaultEquality<Key>,
944 typename Slot = typename DefaultSetSlot<Key>::type>
946
947} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_NOINLINE
#define LOAD_FACTOR
Definition BLI_map.hh:162
#define SLOT_PROBING_BEGIN(PROBING_STRATEGY, HASH, MASK, R_SLOT_INDEX)
#define SLOT_PROBING_END()
#define SET_SLOT_PROBING_END()
Definition BLI_set.hh:160
#define SET_SLOT_PROBING_BEGIN(HASH, R_SLOT)
Definition BLI_set.hh:157
#define BLI_NO_UNIQUE_ADDRESS
struct Key Key
long long int int64_t
unsigned long long int uint64_t
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:419
void print(const char *name) const
constexpr void compute_total_and_usable_slots(int64_t min_total_slots, int64_t min_usable_slots, int64_t *r_total_slots, int64_t *r_usable_slots) const
static constexpr int64_t compute_total_slots(int64_t min_usable_slots, uint8_t numerator, uint8_t denominator)
Iterator operator++(int)
Definition BLI_set.hh:444
std::ptrdiff_t difference_type
Definition BLI_set.hh:419
friend bool operator!=(const Iterator &a, const Iterator &b)
Definition BLI_set.hh:461
Iterator & operator++()
Definition BLI_set.hh:434
const Key * operator->() const
Definition BLI_set.hh:456
std::forward_iterator_tag iterator_category
Definition BLI_set.hh:415
const Key & operator*() const
Definition BLI_set.hh:451
const Key & reference
Definition BLI_set.hh:418
const Slot & current_slot() const
Definition BLI_set.hh:474
friend bool operator==(const Iterator &a, const Iterator &b)
Definition BLI_set.hh:468
const Key * pointer
Definition BLI_set.hh:417
Iterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
Definition BLI_set.hh:429
Set(NoExceptConstructor, Allocator allocator={}) noexcept
Definition BLI_set.hh:177
const Key & lookup_key_or_add_as(ForwardKey &&key)
Definition BLI_set.hh:375
void remove(const Iterator &it)
Definition BLI_set.hh:500
const std::string & const_reference
Definition BLI_set.hh:113
int64_t size_per_element() const
Definition BLI_set.hh:619
const Key & lookup_key_default(const Key &key, const Key &default_value) const
Definition BLI_set.hh:336
bool remove_as(const ForwardKey &key)
Definition BLI_set.hh:389
bool add_overwrite_as(ForwardKey &&key)
Definition BLI_set.hh:275
Set(const std::initializer_list< Key > &values)
Definition BLI_set.hh:187
int64_t size_in_bytes() const
Definition BLI_set.hh:628
void clear_and_keep_capacity()
Definition BLI_set.hh:564
~Set()=default
Set(const Set &other)=default
Iterator begin() const
Definition BLI_set.hh:480
const Key & lookup_key_or_add(const Key &key)
Definition BLI_set.hh:367
void add_multiple_new(Span< Key > keys)
Definition BLI_set.hh:298
const Key & lookup_key(const Key &key) const
Definition BLI_set.hh:323
void print_stats(const char *name) const
Definition BLI_set.hh:533
static bool Disjoint(const Set &a, const Set &b)
Definition BLI_set.hh:665
bool add(Key &&key)
Definition BLI_set.hh:252
const Key & lookup_key_as(const ForwardKey &key) const
Definition BLI_set.hh:327
int64_t size() const
Definition BLI_set.hh:587
bool add_as(ForwardKey &&key)
Definition BLI_set.hh:256
int64_t removed_amount() const
Definition BLI_set.hh:611
bool contains_as(const ForwardKey &key) const
Definition BLI_set.hh:314
void reserve(const int64_t n)
Definition BLI_set.hh:637
const Key & lookup_key_default_as(const ForwardKey &key, const Key &default_key) const
Definition BLI_set.hh:341
Iterator end() const
Definition BLI_set.hh:490
Set(Span< Key > values, Allocator allocator={})
Definition BLI_set.hh:179
void remove_contained(const Key &key)
Definition BLI_set.hh:397
const std::string * const_pointer
Definition BLI_set.hh:111
friend bool operator!=(const Set &a, const Set &b)
Definition BLI_set.hh:683
bool contains(const Key &key) const
Definition BLI_set.hh:310
static bool Intersects(const Set &a, const Set &b)
Definition BLI_set.hh:647
int64_t capacity() const
Definition BLI_set.hh:603
int64_t count_collisions(const Key &key) const
Definition BLI_set.hh:543
friend bool operator==(const Set &a, const Set &b)
Definition BLI_set.hh:670
bool add_overwrite(Key &&key)
Definition BLI_set.hh:271
bool add(const Key &key)
Definition BLI_set.hh:248
Set & operator=(const Set &other)
Definition BLI_set.hh:218
bool is_empty() const
Definition BLI_set.hh:595
Set & operator=(Set &&other)
Definition BLI_set.hh:223
void add_multiple(Span< Key > keys)
Definition BLI_set.hh:287
const Key * lookup_key_ptr_as(const ForwardKey &key) const
Definition BLI_set.hh:358
Set(Set &&other) noexcept(std::is_nothrow_move_constructible_v< SlotArray >)
Definition BLI_set.hh:193
void add_new(const Key &key)
Definition BLI_set.hh:233
bool add_overwrite(const Key &key)
Definition BLI_set.hh:267
const Key & lookup_key_or_add(Key &&key)
Definition BLI_set.hh:371
Set(Allocator allocator={}) noexcept
Definition BLI_set.hh:168
int64_t remove_if(Predicate &&predicate)
Definition BLI_set.hh:515
void clear()
Definition BLI_set.hh:551
void remove_contained_as(const ForwardKey &key)
Definition BLI_set.hh:401
const Key * lookup_key_ptr(const Key &key) const
Definition BLI_set.hh:354
bool remove(const Key &key)
Definition BLI_set.hh:385
void rehash()
Definition BLI_set.hh:579
void add_new(Key &&key)
Definition BLI_set.hh:237
Container & copy_assign_container(Container &dst, const Container &src)
Set< Key, InlineBufferCapacity, ProbingStrategy, Hash, IsEqual, Slot, RawAllocator > RawSet
Definition BLI_set.hh:945
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
constexpr int64_t default_inline_buffer_capacity(size_t element_size)
PythonProbingStrategy<> DefaultProbingStrategy
#define hash
Definition noise_c.cc:154
const char * name
SimpleSetSlot< Key > type
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4238