1#ifndef GIMBAL_HASHSET_HPP
2#define GIMBAL_HASHSET_HPP
6#include "../objects/gimbal_context.hpp"
15
16
17
18
19
20
21
23template<
typename K =
void*,
24 typename H = std::hash<K>,
25 typename P = std::equal_to<K>>
28template<
typename K =
void*>
33struct HashSetIterator;
35template<
typename CRTP,
typename K=
void*>
41 using DerivedType = CRTP;
43 using key_type = KeyType;
44 using value_type = KeyType;
45 using reference = value_type&;
46 using const_reference =
const value_type&;
47 using pointer = value_type*;
48 using const_pointer =
const value_type*;
52 using difference_type = ptrdiff_t;
56 operator
const GblHashSet*()
const;
58 decltype(
auto) getSet (
void)
const;
59 decltype(
auto) getSet (
void);
61 size_type size (
void)
const noexcept;
62 size_type bucket_count(
void)
const noexcept;
63 size_type bucket_size (
void)
const noexcept;
64 bool empty (
void)
const noexcept;
65 GblContext* context (
void)
const noexcept;
67 const_pointer get (
const key_type& key)
const noexcept;
69 const_reference at (
const key_type& key)
const;
71 size_type count (
const key_type& key)
const noexcept;
72 bool contains (
const key_type& key)
const noexcept;
73 const_pointer probe (size_type position)
const noexcept;
74 const_iterator find (
const key_type& key)
const noexcept;
80 const_iterator next(const_iterator* pPrev)
const;
82 const_iterator cbegin(
void)
const;
83 auto begin(
void)
const;
85 const_iterator cend(
void)
const;
92class HashSetView final:
public HashSetBase<HashSetView<K>, K> {
95 const GblHashSet* pGblHashSet_ =
nullptr;
97 const GblHashSet* set_ (
void)
const;
99 HashSetView (
void) =
default;
100 HashSetView (
const GblHashSet& gblHashSet);
101 HashSetView (
const GblHashSet* pGblHashSet);
103 bool isValid (
void)
const;
110HashSetView(HashSet<K, H, P> base) -> HashSetView<K>;
124 using reference =
typename BaseType::reference;
125 using const_reference =
typename BaseType::const_reference;
126 using pointer =
typename BaseType::pointer;
127 using const_pointer =
typename BaseType::const_pointer;
128 using size_type =
typename BaseType::size_type;
129 using key_type =
typename BaseType::key_type;
130 using value_type =
typename BaseType::value_type;
133 using iterator = HashSetIterator<HashSet<K, H, P>, K>;
135 const hasher& hasher_;
136 const key_equal& comparator_;
138 static Hash hasherCb_ (
const GblHashSet* pSet,
const void* pKey);
139 static Bool comparatorCb_ (
const GblHashSet* pSet,
const void* pKey1,
const void* pKey2);
140 static void destructCb_ (
const GblHashSet* pSet,
void* pKey);
148 HashSet (size_type capacity,
151 Context* pCtx =
nullptr);
152 HashSet (size_type capacity,
155 HashSet (size_type capacity,
159 HashSet (type_compatible_container_readable<value_type>
auto&& init,
160 size_type capacity = 0,
161 const H hasher = H(),
163 Context* pCtx =
nullptr);
164 HashSet (type_compatible_container_readable<value_type>
auto&& init,
168 HashSet (type_compatible_container_readable<value_type>
auto&& init,
172 HashSet (type_compatible_iterator_readable<value_type>
auto first,
173 type_compatible_iterator_readable<value_type>
auto last,
174 size_type capacity = 0,
177 Context* pCtx =
nullptr);
179 HashSet (type_compatible_iterator_readable<value_type>
auto first,
180 type_compatible_iterator_readable<value_type>
auto last,
185 HashSet (type_compatible_iterator_readable<value_type>
auto first,
186 type_compatible_iterator_readable<value_type>
auto last,
190 HashSet (HashSet& other);
191 HashSet (HashSet& other, Context* pCtx);
193 HashSet (HashSet&& other);
194 HashSet (HashSet&& other, Context* pCtx);
198 HashSet& operator= (
const HashSet& other);
199 HashSet& operator= (
const HashSet&& other);
200 HashSet& operator= (type_compatible_container_readable<value_type>
auto&& init);
202 pointer get (
const key_type& key)
noexcept;
203 reference at (
const key_type& key);
204 iterator find (
const key_type& key)
noexcept;
206 pointer set (
const key_type& key)
noexcept;
208 bool insert (
const key_type& key)
noexcept;
209 void insert_or_assign(
const key_type& key)
noexcept;
211 bool erase (
const key_type& key)
noexcept;
212 pointer extract (
const key_type& key)
noexcept;
213 void clear (
void)
noexcept;
215 template<
typename... Args>
216 bool emplace (
const key_type& key, Args&&... args);
217 template<
typename... Args>
218 bool try_emplace (
const key_type& key, Args&&... args)
noexcept;
220 pointer probe (size_type position)
noexcept;
222 iterator next (iterator* pPrev);
224 iterator begin (
void);
230struct HashSetIterator:
231 public GblHashSetIter,
232 public std::iterator<std::forward_iterator_tag, K>
234 using object_type = C;
235 constexpr static bool is_const = std::is_const_v<C>;
236 using iterator_type = HashSetIterator<C, K>;
237 using const_iterator_type = HashSetIterator<std::add_const_t<C>, K>;
238 using nonconst_iterator_type = HashSetIterator<std::remove_const_t<C>, K>;
239 using value_type = K;
240 using reference = std::conditional_t<std::is_const_v<C>,
241 std::add_lvalue_reference_t<std::add_const_t<K>>,
242 std::add_lvalue_reference_t<K>>;
243 using const_reference = std::add_const_t<reference>;
244 using pointer = std::conditional_t<std::is_const_v<C>,
245 std::add_pointer_t<std::add_const_t<K>>,
246 std::add_pointer_t<K>>;
247 using difference_type = std::ptrdiff_t;
248 using iterator_category = std::forward_iterator_tag;
250 C* set(
void) {
return static_cast<C*>(
this->pSet); }
251 const C* set(
void)
const {
return static_cast<
const C*>(
this->pSet); }
253 reference operator*(
void) {
254 return *
reinterpret_cast<pointer>(set()->probe(
this->bucketIdx));
257 const_reference operator*(
void)
const {
258 return *
reinterpret_cast<
const pointer>(set()->probe(
this->bucketIdx));
261 pointer operator->(
void) {
262 return reinterpret_cast<pointer>(set()->probe(
this->bucketIdx));
265 const pointer operator->(
void)
const {
266 return reinterpret_cast<
const pointer>(set()->probe(
this->bucketIdx));
269 iterator_type& operator++ () {
270 auto nextIt = set()->next(
this);
271 this->bucketIdx = nextIt.bucketIdx;
275 iterator_type operator++ (
int) {
276 const auto temp(*
this);
281 bool operator== (
const iterator_type& rhs)
const {
return this->pSet == rhs.pSet &&
this->bucketIdx == rhs.bucketIdx; }
282 bool operator<= (
const iterator_type& rhs)
const {
return this->pSet == rhs.pSet &&
this->bucketIdx <= rhs.bucketIdx; }
283 bool operator< (
const iterator_type& rhs)
const {
return this->pSet == rhs.pSet &&
this->bucketIdx < rhs.bucketIdx; }
284 bool operator> (
const iterator_type& rhs)
const {
return this->pSet == rhs.pSet &&
this->bucketIdx > rhs.bucketIdx; }
285 bool operator>= (
const iterator_type& rhs)
const {
return this->pSet == rhs.pSet &&
this->bucketIdx >= rhs.bucketIdx; }
286 bool operator!= (
const iterator_type& rhs)
const {
return !(*
this == rhs); }
289 HashSetIterator(C* pCont=
nullptr, Size bucketIdx=-1):
293 HashSetIterator(
static_cast<C*>(gblIt.pSet), gblIt.bucketIdx) {}
295 HashSetIterator(
const const_iterator_type& rhs) requires is_const:
296 HashSetIterator(rhs.pSet, rhs.bucketIdx) {}
298 HashSetIterator(
const nonconst_iterator_type& rhs):
299 HashSetIterator(rhs.pSet, rhs.bucketIdx) {}
301 const C* getContainer(
void)
const {
return reinterpret_cast<C*>(GblHashSetIter_container(
this)); }
302 bool valid(
void)
const {
return GblHashSetIter_valid(
this); }
303 K& value(
void) {
return *
reinterpret_cast<K*>(GblHashSetIter_value(
this)); }
313template<
typename CRTP,
typename K>
314inline decltype(
auto)
HashSetBase<CRTP, K>::getSet(
void)
const {
return static_cast<
const CRTP*>(
this)->set_(); }
316template<
typename CRTP,
typename K>
317inline decltype(
auto)
HashSetBase<CRTP, K>::getSet(
void) {
return static_cast<CRTP*>(
this)->set_(); }
319template<
typename CRTP,
typename K>
320inline auto HashSetBase<CRTP, K>::size(
void)
const noexcept -> size_type {
return GblHashSet_size(getSet()); }
322template<
typename CRTP,
typename K>
323inline auto HashSetBase<CRTP, K>::bucket_count(
void)
const noexcept -> size_type {
return GblHashSet_bucketCount(getSet()); }
325template<
typename CRTP,
typename K>
326inline auto HashSetBase<CRTP, K>::bucket_size(
void)
const noexcept -> size_type {
return GblHashSet_bucketSize(getSet()); }
328template<
typename CRTP,
typename K>
329inline bool HashSetBase<CRTP, K>::empty(
void)
const noexcept {
return GblHashSet_empty(getSet()); }
331template<
typename CRTP,
typename K>
332inline GblContext*
HashSetBase<CRTP, K>::context(
void)
const noexcept {
return GblHashSet_context(getSet()); }
334template<
typename CRTP,
typename K>
335inline HashSetBase<CRTP, K>::operator
const GblHashSet*()
const {
return getSet(); }
337template<
typename CRTP,
typename K>
338inline auto HashSetBase<CRTP, K>::get(
const key_type& key)
const noexcept -> const_pointer {
339 return static_cast<const_pointer>(GblHashSet_get(getSet(), &key));
342template<
typename CRTP,
typename K>
343inline auto HashSetBase<CRTP, K>::at(
const key_type& key)
const -> const_reference {
345 const key_type* pKey =
nullptr;
346 GblThread_callRecordSet(NULL, NULL);
347 pKey =
reinterpret_cast<
const key_type*>(GblHashSet_at(getSet(), &key));
348 pRecord = GblThread_callRecord(NULL);
349 Exception::checkThrow(*pRecord);
353template<
typename CRTP,
typename K>
354inline auto HashSetBase<CRTP, K>::count(
const key_type& key)
const noexcept -> size_type {
355 return GblHashSet_count(getSet(), &key);
358template<
typename CRTP,
typename K>
359inline bool HashSetBase<CRTP, K>::contains(
const key_type& key)
const noexcept {
360 return GblHashSet_contains(getSet(), &key);
363template<
typename CRTP,
typename K>
364inline auto HashSetBase<CRTP, K>::find(
const key_type& key)
const noexcept -> const_iterator {
365 return GblHashSet_find(getSet(), &key);
368template<
typename CRTP,
typename K>
369inline auto HashSetBase<CRTP, K>::probe(size_type position)
const noexcept -> const_pointer {
370 return GblHashSet_probe(getSet(), position);
373template<
typename CRTP,
typename K>
375 requires std::is_invocable_r_v<
bool, F,
const K&>
376inline bool HashSetBase<CRTP, K>::for_each(F&& fn)
const noexcept {
377 return GblHashSet_foreach(getSet(), [](
const GblHashSet* pSelf,
382 auto* pFn =
static_cast<F*>(pUd);
383 return (*pFn)(*
static_cast<const_pointer>(pKey));
388template<
typename CRTP,
typename K>
389inline auto HashSetBase<CRTP, K>::next(const_iterator* pPrev)
const -> const_iterator {
390 return GblHashSet_next(getSet(), pPrev);
393template<
typename CRTP,
typename K>
394inline auto HashSetBase<CRTP, K>::cbegin(
void)
const -> const_iterator {
395 return GblHashSet_next(getSet(),
nullptr);
398template<
typename CRTP,
typename K>
399inline auto HashSetBase<CRTP, K>::begin(
void)
const {
return cbegin(); }
401template<
typename CRTP,
typename K>
402inline auto HashSetBase<CRTP, K>::cend(
void)
const -> const_iterator {
return const_iterator(
this, bucket_count()); }
404template<
typename CRTP,
typename K>
405inline auto HashSetBase<CRTP, K>::end(
void)
const {
return cend(); }
413inline const GblHashSet* HashSetView<K>::set_(
void)
const {
return pGblHashSet_; }
416inline HashSetView<K>::HashSetView(
const GblHashSet& gblHashSet):
417 pGblHashSet_(&gblHashSet) {}
420inline HashSetView<K>::HashSetView(
const GblHashSet* pGblHashSet):
421 pGblHashSet_(pGblHashSet) {}
424inline bool HashSetView<K>::isValid(
void)
const {
return pGblHashSet_; }
427template<
typename K,
typename H,
typename P>
428inline const GblHashSet* HashSet<K, H, P>::set_(
void)
const {
return static_cast<
const GblHashSet*>(
this); }
430template<
typename K,
typename H,
typename P>
431inline GblHashSet* HashSet<K, H, P>::set_(
void) {
return static_cast<
GblHashSet*>(
this); }
433template<
typename K,
typename H,
typename P>
434inline HashSet<K, H, P>::HashSet(size_type capacity,
451template<
typename K,
typename H,
typename P>
452inline HashSet<K, H, P>::HashSet(size_type capacity,
455 HashSet(capacity, hash, P(), pContext) {}
457template<
typename K,
typename H,
typename P>
458inline HashSet<K, H, P>::HashSet(size_type capacity,
460 HashSet(capacity, H(), pContext) {}
462template<
typename K,
typename H,
typename P>
463inline HashSet<K, H, P>::HashSet(
void):
466template<
typename K,
typename H,
typename P>
467inline HashSet<K, H, P>::HashSet(type_compatible_container_readable<value_type>
auto&& init,
472 HashSet(capacity, hasher, pred, pCtx)
474 for(
auto&& it: init) insert(std::forward<
decltype(it)>(it));
477template<
typename K,
typename H,
typename P>
478inline HashSet<K, H, P>::HashSet(type_compatible_container_readable<value_type>
auto&& init,
482 HashSet(std::forward<
decltype(init)>(init), capacity, hasher, P(), pCtx) {}
484template<
typename K,
typename H,
typename P>
485inline HashSet<K, H, P>::HashSet(type_compatible_container_readable<value_type>
auto&& init,
488 HashSet(std::forward<
decltype(init)>(init), capacity, H(), pCtx) {}
490template<
typename K,
typename H,
typename P>
491inline HashSet<K, H, P>::HashSet(type_compatible_iterator_readable<value_type>
auto first,
492 type_compatible_iterator_readable<value_type>
auto last,
497 HashSet(capacity, hash, pred, pCtx)
499 for(
auto it = first; it < last; ++it) {
504template<
typename K,
typename H,
typename P>
505inline HashSet<K, H, P>::HashSet(type_compatible_iterator_readable<value_type>
auto first,
506 type_compatible_iterator_readable<value_type>
auto last,
510 HashSet(std::move(first), std::move(last), capacity, hash, P(), pCtx) {}
512template<
typename K,
typename H,
typename P>
513inline HashSet<K, H, P>::HashSet(type_compatible_iterator_readable<value_type>
auto first,
514 type_compatible_iterator_readable<value_type>
auto last,
517 HashSet(std::move(first), std::move(last), capacity, H(), pCtx) {}
521template<
typename K,
typename H,
typename P>
522inline HashSet<K, H, P>::HashSet(HashSet& other, Context* pCtx) {
523 GblHashSet_clone(
this, &other, pCtx);
526template<
typename K,
typename H,
typename P>
527inline HashSet<K, H, P>::HashSet(HashSet& other):
528 HashSet(other, other.context()) {}
530template<
typename K,
typename H,
typename P>
531inline HashSet<K, H, P>::~HashSet(
void) {
532 GblHashSet_destruct(
this);
535template<
typename K,
typename H,
typename P>
536inline auto HashSet<K, H, P>::operator=(
const HashSet& other) -> HashSet& {
537 GblHashSet_assignClone(
this, &other);
541template<
typename K,
typename H,
typename P>
542inline auto HashSet<K, H, P>::operator=(
const HashSet&& other) -> HashSet& {
543 GblHashSet_assignMove(
this, &other);
547template<
typename K,
typename H,
typename P>
548inline auto HashSet<K, H, P>::operator=(type_compatible_container_readable<value_type>
auto&& init) -> HashSet& {
550 for(
auto&& it: init) insert(std::forward<
decltype(it)>(it));
554template<
typename K,
typename H,
typename P>
555inline auto HashSet<K, H, P>::get(
const key_type& key)
noexcept -> pointer {
556 return static_cast<pointer>(GblHashSet_get(
this, &key));
559template<
typename K,
typename H,
typename P>
560inline auto HashSet<K, H, P>::at(
const key_type& key) -> reference {
561 key_type* pKey =
nullptr;
562 GblThread_callRecordSet(NULL, NULL);
563 pKey =
reinterpret_cast<key_type*>(GblHashSet_at(
this, &key));
564 Exception::checkThrow(*GblThread_callRecord(NULL));
568template<
typename K,
typename H,
typename P>
569inline auto HashSet<K, H, P>::find(
const key_type& key)
noexcept -> iterator {
570 return GblHashSet_find(
this, &key);
573template<
typename K,
typename H,
typename P>
574inline auto HashSet<K, H, P>::set(
const key_type& key)
noexcept -> pointer {
575 return static_cast<pointer>(GblHashSet_set(
this, &key));
578template<
typename K,
typename H,
typename P>
579inline bool HashSet<K, H, P>::insert(
const key_type& key)
noexcept {
580 return GblHashSet_insert(
this, &key);
583template<
typename K,
typename H,
typename P>
584inline void HashSet<K, H, P>::insert_or_assign(
const key_type& key)
noexcept {
585 GblHashSet_insertOrAssign(
this, &key);
588template<
typename K,
typename H,
typename P>
589inline bool HashSet<K, H, P>::erase(
const key_type& key)
noexcept {
590 return GblHashSet_erase(
this, &key);
593template<
typename K,
typename H,
typename P>
594inline auto HashSet<K, H, P>::extract(
const key_type& key)
noexcept -> pointer {
595 return GblHashSet_extract(
this, &key);
598template<
typename K,
typename H,
typename P>
599inline void HashSet<K, H, P>::clear(
void)
noexcept {
600 GblHashSet_clear(
this);
603template<
typename K,
typename H,
typename P>
604inline auto HashSet<K, H, P>::probe(size_type position)
noexcept -> pointer {
605 return reinterpret_cast<pointer>(GblHashSet_probe(
this, position));
608template<
typename K,
typename H,
typename P>
609template<
typename... Args>
610inline bool HashSet<K, H, P>::try_emplace(
const key_type& key, Args&&... args)
noexcept {
611 pointer pData =
static_cast<pointer>(GblHashSet_emplace(
this, &key));
612 if(pData)
new (pData) key_type(std::forward<Args>(args)...);
616template<
typename K,
typename H,
typename P>
617template<
typename... Args>
618inline bool HashSet<K, H, P>::emplace(
const key_type& key, Args&&... args) {
619 pointer pData =
static_cast<pointer>(GblHashSet_emplace(
this, &key));
621 new (pData) key_type(std::forward<Args>(args)...);
625template<
typename K,
typename H,
typename P>
626inline auto HashSet<K, H, P>::next(iterator* pPrev) -> iterator {
627 return GblHashSet_next(
this, pPrev);
630template<
typename K,
typename H,
typename P>
631inline auto HashSet<K, H, P>::begin(
void) -> iterator {
632 return next(
nullptr);
635template<
typename K,
typename H,
typename P>
636inline auto HashSet<K, H, P>::end(
void) -> iterator {
637 return iterator(
this,
this->bucket_count());
640template<
typename K,
typename H,
typename P>
641inline Hash HashSet<K, H, P>::hasherCb_(
const GblHashSet* pSet,
const void* pKey) {
642 return static_cast<
const HashSet<K, H, P>*>(pSet)->hasher_(*
static_cast<
const K*>(pKey));
645template<
typename K,
typename H,
typename P>
646inline Bool HashSet<K, H, P>::comparatorCb_ (
const GblHashSet* pSet,
const void* pKey1,
const void* pKey2) {
647 return static_cast<
const HashSet<K, H, P>*>(pSet)->comparator_(*
static_cast<
const K*>(pKey1), *
static_cast<
const K*>(pKey2));
650template<
typename K,
typename H,
typename P>
651inline void HashSet<K, H, P>::destructCb_(
const GblHashSet* pSet,
void* pKey) {
653 static_cast<K*>(pKey)->~K();
#define GblHashSet_construct(...)
Captures a result, its stringified message, and a source context.
Hash-table based abstract associative container with C++-style STL std::unoredered_set API.
Iterator structure used for iterating over GblHashSet.