aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
set_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Implementation of the Set.
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #include <agrum/tools/core/set.h>
30 
31 namespace gum {
32 
33  // ===========================================================================
34  // === SAFE SET ITERATORS ===
35  // ===========================================================================
36 
37  // default constructor: the iterator points toward nothing
38  template < typename Key >
39  INLINE SetIteratorSafe< Key >::SetIteratorSafe() {
41  }
42 
43  // creates an iterator for a given set
44  template < typename Key >
45  template < typename Alloc >
48  : set._inside_.cbeginSafe()} {
50  }
51 
52  // copy constructor
53  template < typename Key >
57  }
58 
59  // copy constructor
60  template < typename Key >
64  }
65 
66  // move constructor
67  template < typename Key >
71  }
72 
73  // destructor
74  template < typename Key >
77  }
78 
79  // assignment operator
80  template < typename Key >
84  return *this;
85  }
86 
87  // assignment operator
88  template < typename Key >
91  return *this;
92  }
93 
94  // move operator
95  template < typename Key >
99  return *this;
100  }
101 
102  // increments the iterator
103  template < typename Key >
105  // note that, if the hashtable's iterator points toward nothing, the
106  // hashtable's iterator incrementation will do nothing. In particular, it
107  // will not segfault.
108  ++_ht_iter_;
109  return *this;
110  }
111 
112  // makes the iterator point to i elements further in the set
113  template < typename Key >
115  _ht_iter_ += nb;
116  return *this;
117  }
118 
119  // returns a new iterator
120  template < typename Key >
122  return SetIteratorSafe< Key >{*this} += nb;
123  }
124 
125  // indicates whether two iterators point to different elements or sets
126  template < typename Key >
127  INLINE bool
128  SetIteratorSafe< Key >::operator!=(const SetIteratorSafe< Key >& from) const noexcept {
129  return _ht_iter_ != from._ht_iter_;
130  }
131 
132  // indicates whether two iterators point toward the same element of a same
133  // set
134  template < typename Key >
135  INLINE bool
136  SetIteratorSafe< Key >::operator==(const SetIteratorSafe< Key >& from) const noexcept {
137  return _ht_iter_ == from._ht_iter_;
138  }
139 
140  // returns the element pointed to by the iterator
141  template < typename Key >
142  INLINE const Key& SetIteratorSafe< Key >::operator*() const {
143  // note that, if the hashtable's iterator points toward nothing, it will
144  // raise an UndefinedIteratorValue exception
145  return _ht_iter_.key();
146  }
147 
148  // returns aointer to the element pointed to by the iterator
149  template < typename Key >
150  INLINE const Key* SetIteratorSafe< Key >::operator->() const {
151  // note that, if the hashtable's iterator points toward nothing, it will
152  // raise an UndefinedIteratorValue exception
153  return &(_ht_iter_.key());
154  }
155 
156  // @brief makes the iterator point toward nothing (in particular, it is not
157  // related anymore to its current set) */
158  template < typename Key >
159  INLINE void SetIteratorSafe< Key >::clear() noexcept {
160  _ht_iter_.clear();
161  }
162 
163  // ===========================================================================
164  // === UNSAFE SET ITERATORS ===
165  // ===========================================================================
166 
167  // default constructor: the iterator points toward nothing
168  template < typename Key >
171  }
172 
173  // creates an iterator for a given set
174  template < typename Key >
175  template < typename Alloc >
179  }
180 
181  // copy constructor
182  template < typename Key >
186  }
187 
188  // move constructor
189  template < typename Key >
193  }
194 
195  // destructor
196  template < typename Key >
197  INLINE SetIterator< Key >::~SetIterator() noexcept {
199  }
200 
201  // assignment operator
202  template < typename Key >
204  SetIterator< Key >::operator=(const SetIterator< Key >& from) noexcept {
206  return *this;
207  }
208 
209  // move operator
210  template < typename Key >
213  return *this;
214  }
215 
216  // increments the iterator
217  template < typename Key >
218  INLINE SetIterator< Key >& SetIterator< Key >::operator++() noexcept {
219  // note that, if the hashtable's iterator points toward nothing, the
220  // hashtable's iterator incrementation will do nothing. In particular, it
221  // will not segfault.
222  ++_ht_iter_;
223  return *this;
224  }
225 
226  // makes the iterator point to i elements further in the set
227  template < typename Key >
229  _ht_iter_ += nb;
230  return *this;
231  }
232 
233  // returns a new iterator
234  template < typename Key >
235  INLINE SetIterator< Key > SetIterator< Key >::operator+(Size nb) const noexcept {
236  return SetIterator< Key >{*this} += nb;
237  }
238 
239  // indicates whether two iterators point to different elements or sets
240  template < typename Key >
241  INLINE bool SetIterator< Key >::operator!=(const SetIterator< Key >& from) const noexcept {
242  return _ht_iter_ != from._ht_iter_;
243  }
244 
245  // indicates whether two iterators point toward the same element of a same
246  // set
247  template < typename Key >
248  INLINE bool SetIterator< Key >::operator==(const SetIterator< Key >& from) const noexcept {
249  return _ht_iter_ == from._ht_iter_;
250  }
251 
252  // returns the element pointed to by the iterator
253  template < typename Key >
254  INLINE const Key& SetIterator< Key >::operator*() const {
255  // note that, if the hashtable's iterator points toward nothing, it will
256  // raise an UndefinedIteratorValue exception
257  return _ht_iter_.key();
258  }
259 
260  // returns aointer to the element pointed to by the iterator
261  template < typename Key >
262  INLINE const Key* SetIterator< Key >::operator->() const {
263  // note that, if the hashtable's iterator points toward nothing, it will
264  // raise an UndefinedIteratorValue exception
265  return &(_ht_iter_.key());
266  }
267 
268  // @brief makes the iterator point toward nothing (in particular, it is not
269  // related anymore to its current set) */
270  template < typename Key >
271  INLINE void SetIterator< Key >::clear() noexcept {
272  _ht_iter_.clear();
273  }
274 
275  // ===========================================================================
276  // === SETS ===
277  // ===========================================================================
278 
279  // returns the end iterator for other classes' statics
280  template < typename Key, typename Alloc >
282  return *(
283  reinterpret_cast< const SetIteratorSafe< Key >* >(SetIteratorStaticEnd::endSafe4Statics()));
284  }
285 
286  // returns the end iterator for other classes' statics
287  template < typename Key, typename Alloc >
289  return *(reinterpret_cast< const SetIteratorSafe< Key >* >(
291  }
292 
293  // returns the end iterator for other classes' statics
294  template < typename Key, typename Alloc >
296  return *(reinterpret_cast< const SetIterator< Key >* >(SetIteratorStaticEnd::end4Statics()));
297  }
298 
299  // returns the end iterator for other classes' statics
300  template < typename Key, typename Alloc >
302  return *(
303  reinterpret_cast< const SetIterator< Key >* >(SetIteratorStaticEnd::constEnd4Statics()));
304  }
305 
306  // default constructor
307  template < typename Key, typename Alloc >
309  // create the hash table without key uniqueness policy (as we will
310  // check
311  // ourselves the uniqueness of Keys before inserting new elements)
312  _inside_(capacity, resize_policy, false) {
314 
315  // make sure the end() iterator is constructed properly
316  endSafe4Statics();
317  end4Statics();
318  }
319 
320  // initializer list constructor
321  template < typename Key, typename Alloc >
323  _inside_(Size(list.size()) / 2, true, false) {
325  for (const auto& elt: list) {
326  insert(elt);
327  }
328 
329  // make sure the end() iterator is constructed properly
330  endSafe4Statics();
331  end4Statics();
332  }
333 
334  // copy constructor
335  template < typename Key, typename Alloc >
336  INLINE Set< Key, Alloc >::Set(const Set< Key, Alloc >& s) : _inside_(s._inside_) {
337  GUM_CONS_CPY(Set);
338  }
339 
340  // generalized copy constructor
341  template < typename Key, typename Alloc >
342  template < typename OtherAlloc >
344  GUM_CONS_CPY(Set);
345  }
346 
347  // move constructor
348  template < typename Key, typename Alloc >
350  GUM_CONS_MOV(Set);
351  }
352 
353  // destructor
354  template < typename Key, typename Alloc >
355  INLINE Set< Key, Alloc >::Set::~Set() {
357  }
358 
359  // removes all the elements, if any, from the set
360  template < typename Key, typename Alloc >
361  INLINE void Set< Key, Alloc >::clear() {
362  // first we remove all the elements from the hashtable actually containing
363  // the elements of the set. Note that, doing so, all the hashtable iterators
364  // will be updated as well. In turn, this will imply that, whenever an
365  // operation will be performed on a SetIteratorSafe, this will raise an
366  // exception.
367  _inside_.clear();
368 
369  // Note that actually there is no need to update the end iterator as this
370  // one
371  // is not affected by changes within hashtables (adding/deleting elements).
372  // Hence, for speedup, we do not update the end iterator
373  }
374 
375  // copy operator
376  template < typename Key, typename Alloc >
377  Set< Key, Alloc >& Set< Key, Alloc >::operator=(const Set< Key, Alloc >& s) {
378  // avoid self assignment
379  if (&s != this) {
380  // remove the old content of the set. Actually, we remove all the elements
381  // from the underlying hashtable. Note that, doing so, all the hashtable
382  // iterators will be updated as well. In turn, this will imply that,
383  // whenever
384  // an operation will be performed on a SetIteratorSafe, this will raise an
385  // exception.
386  clear();
387 
388  // prepare the set for its new data
389  resize(s.capacity());
391 
392  // copy the set
393  _inside_ = s._inside_;
394 
395  // Note that actually there is no need to update the end iterator as this
396  // one
397  // is not affected by changes within hashtables (adding/deleting
398  // elements).
399  // Hence, for speedup, we do not update the end iterator
400  }
401 
402  return *this;
403  }
404 
405  // generalized copy operator
406  template < typename Key, typename Alloc >
407  template < typename OtherAlloc >
408  Set< Key, Alloc >& Set< Key, Alloc >::operator=(const Set< Key, OtherAlloc >& s) {
409  // avoid self assignment
410  if (this != reinterpret_cast< const Set< Key, Alloc >* >(&s)) {
411  // remove the old content of the set. Actually, we remove all the elements
412  // from the underlying hashtable. Note that, doing so, all the hashtable
413  // iterators will be updated as well. In turn, this will imply that,
414  // whenever
415  // an operation will be performed on a SetIteratorSafe, this will raise an
416  // exception.
417  clear();
418 
419  // prepare the set for its new data
420  resize(s.capacity());
422 
423  // copy the set
424  _inside_ = s._inside_;
425 
426  // Note that actually there is no need to update the end iterator as this
427  // one
428  // is not affected by changes within hashtables (adding/deleting
429  // elements).
430  // Hence, for speedup, we do not update the end iterator
431  }
432 
433  return *this;
434  }
435 
436  // move operator
437  template < typename Key, typename Alloc >
438  Set< Key, Alloc >& Set< Key, Alloc >::operator=(Set< Key, Alloc >&& from) {
440  return *this;
441  }
442 
443  // mathematical equality between two sets
444  template < typename Key, typename Alloc >
445  template < typename OtherAlloc >
446  bool Set< Key, Alloc >::operator==(const Set< Key, OtherAlloc >& s2) const {
447  const HashTable< Key, bool, OtherAlloc >& h2 = s2._inside_;
448 
449  // check whether both sets have the same number of elements
450  if (size() != h2.size()) return false;
451 
452  // check the content of the sets
454  ++iter) {
455  if (!h2.exists(iter.key())) return false;
456  }
457 
458  return true;
459  }
460 
461  // mathematical inequality between two sets
462  template < typename Key, typename Alloc >
463  template < typename OtherAlloc >
464  INLINE bool Set< Key, Alloc >::operator!=(const Set< Key, OtherAlloc >& s2) const {
465  return !(operator==(s2));
466  }
467 
468  // the usual begin iterator to parse the set
469  template < typename Key, typename Alloc >
470  INLINE typename Set< Key, Alloc >::iterator_safe Set< Key, Alloc >::beginSafe() const {
471  return SetIteratorSafe< Key >{*this};
472  }
473 
474  // the usual begin iterator to parse the set
475  template < typename Key, typename Alloc >
477  return SetIteratorSafe< Key >{*this};
478  }
479 
480  // the usual end iterator to parse the set
481  template < typename Key, typename Alloc >
482  INLINE const typename Set< Key, Alloc >::iterator_safe&
483  Set< Key, Alloc >::endSafe() const noexcept {
484  return *(
485  reinterpret_cast< const SetIteratorSafe< Key >* >(SetIteratorStaticEnd::_SetIterEndSafe_));
486  }
487 
488  // the usual end iterator to parse the set
489  template < typename Key, typename Alloc >
490  INLINE const typename Set< Key, Alloc >::const_iterator_safe&
491  Set< Key, Alloc >::cendSafe() const noexcept {
492  return *(
493  reinterpret_cast< const SetIteratorSafe< Key >* >(SetIteratorStaticEnd::_SetIterEndSafe_));
494  }
495 
496  // the usual begin iterator to parse the set
497  template < typename Key, typename Alloc >
498  INLINE typename Set< Key, Alloc >::iterator Set< Key, Alloc >::begin() const {
499  return SetIterator< Key >{*this};
500  }
501 
502  // the usual begin iterator to parse the set
503  template < typename Key, typename Alloc >
504  INLINE typename Set< Key, Alloc >::const_iterator Set< Key, Alloc >::cbegin() const {
505  return SetIterator< Key >{*this};
506  }
507 
508  // the usual end iterator to parse the set
509  template < typename Key, typename Alloc >
510  INLINE const typename Set< Key, Alloc >::iterator& Set< Key, Alloc >::end() const noexcept {
511  return *(reinterpret_cast< const SetIterator< Key >* >(SetIteratorStaticEnd::_SetIterEnd_));
512  }
513 
514  // the usual end iterator to parse the set
515  template < typename Key, typename Alloc >
516  INLINE const typename Set< Key, Alloc >::const_iterator&
517  Set< Key, Alloc >::cend() const noexcept {
518  return *(reinterpret_cast< const SetIterator< Key >* >(SetIteratorStaticEnd::_SetIterEnd_));
519  }
520 
521  // returns the size of the underlying hashtable containing the set
522  template < typename Key, typename Alloc >
523  INLINE Size Set< Key, Alloc >::capacity() const {
524  return _inside_.capacity();
525  }
526 
527  // changes the size of the underlying hashtable
528  template < typename Key, typename Alloc >
531 
532  // Note that actually there is no need to update the end iterator as this
533  // one
534  // is not affected by changes within hashtables (adding/deleting elements).
535  // Hence, for speedup, we do not update the end iterator
536  }
537 
538  // enables the user to change dynamically the resizing policy of the
539  // underlying hashtable
540  template < typename Key, typename Alloc >
541  INLINE void Set< Key, Alloc >::setResizePolicy(const bool new_policy) {
543 
544  // Note that actually there is no need to update the end iterator as this
545  // one
546  // is not affected by changes within hashtables (adding/deleting elements).
547  // Hence, for speedup, we do not update the end iterator
548  }
549 
550  // returns the current resizing policy of the underlying hashtable
551  template < typename Key, typename Alloc >
552  INLINE bool Set< Key, Alloc >::resizePolicy() const {
553  return _inside_.resizePolicy();
554  }
555 
556  // indicates whether a given elements belong to the set
557  template < typename Key, typename Alloc >
558  INLINE bool Set< Key, Alloc >::contains(const Key& k) const {
559  return _inside_.exists(k);
560  }
561 
562 
563  template < typename Key, typename Alloc >
564  template < typename OtherAlloc >
565  INLINE bool Set< Key, Alloc >::isProperSubsetOf(const Set< Key, OtherAlloc >& s) const {
566  if (this->size() >= s.size()) { return false; }
567 
568  for (const auto& elt: *this) {
569  if (!s.contains(elt)) { return false; }
570  }
571  return true;
572  }
573 
574  template < typename Key, typename Alloc >
575  template < typename OtherAlloc >
576  INLINE bool Set< Key, Alloc >::isProperSupersetOf(const Set< Key, OtherAlloc >& s) const {
577  return s.isProperSubsetOf(*this);
578  }
579 
580 
581  template < typename Key, typename Alloc >
582  template < typename OtherAlloc >
583  INLINE bool Set< Key, Alloc >::isSubsetOrEqual(const Set< Key, OtherAlloc >& s) const {
584  if (this->size() > s.size()) { return false; }
585 
586  for (const auto& elt: *this) {
587  if (!s.contains(elt)) { return false; }
588  }
589  return true;
590  }
591 
592  template < typename Key, typename Alloc >
593  template < typename OtherAlloc >
594  INLINE bool Set< Key, Alloc >::isSupersetOrEqual(const Set< Key, OtherAlloc >& s) const {
595  return s.isSubsetOrEqual(*this);
596  }
597 
598  // indicates whether a given elements belong to the set
599  template < typename Key, typename Alloc >
600  INLINE bool Set< Key, Alloc >::exists(const Key& k) const {
601  return _inside_.exists(k);
602  }
603 
604  // inserts a new element in the set
605  template < typename Key, typename Alloc >
606  INLINE void Set< Key, Alloc >::insert(const Key& k) {
607  // WARNING: we shall always test whether k already belongs to the set before
608  // trying to insert it because we set _inside_'s key uniqueness policy to
609  // false
610  if (!contains(k)) {
611  // insert the element
612  _inside_.insert(k, true);
613 
614  // Note that actually there is no need to update the end iterator as this
615  // one
616  // is not affected by changes within hashtables (adding/deleting
617  // elements).
618  // Hence, for speedup, we do not update the end iterator
619  }
620  }
621 
622  // inserts a new element in the set
623  template < typename Key, typename Alloc >
624  INLINE void Set< Key, Alloc >::insert(Key&& k) {
625  // WARNING: we shall always test whether k already belongs to the set before
626  // trying to insert it because we set _inside_'s key uniqueness policy to
627  // false
628  if (!contains(k)) {
629  // insert the element
630  _inside_.insert(std::move(k), true);
631 
632  // Note that actually there is no need to update the end iterator as this
633  // one
634  // is not affected by changes within hashtables (adding/deleting
635  // elements).
636  // Hence, for speedup, we do not update the end iterator
637  }
638  }
639 
640  // emplace a new element in the set
641  template < typename Key, typename Alloc >
642  template < typename... Args >
643  INLINE void Set< Key, Alloc >::emplace(Args&&... args) {
644  insert(std::move(Key(std::forward< Args >(args)...)));
645  }
646 
647  // erases an element from the set
648  template < typename Key, typename Alloc >
649  INLINE void Set< Key, Alloc >::erase(const Key& k) {
650  // erase the element (if it exists)
651  _inside_.erase(k);
652 
653  // Note that actually there is no need to update the end iterator as this
654  // one
655  // is not affected by changes within hashtables (adding/deleting elements).
656  // Hence, for speedup, we do not update the end iterator
657  }
658 
659  // erases an element from the set
660  template < typename Key, typename Alloc >
661  INLINE void Set< Key, Alloc >::erase(const SetIteratorSafe< Key >& iter) {
662  // erase the element
664 
665  // Note that actually there is no need to update the end iterator as this
666  // one
667  // is not affected by changes within hashtables (adding/deleting elements).
668  // Hence, for speedup, we do not update the end iterator
669  }
670 
671  // adds a new element to the set
672  template < typename Key, typename Alloc >
673  INLINE Set< Key, Alloc >& Set< Key, Alloc >::operator<<(const Key& k) {
674  insert(k);
675  return *this;
676  }
677 
678  // adds a new element to the set
679  template < typename Key, typename Alloc >
681  insert(std::move(k));
682  return *this;
683  }
684 
685  // removes an element from the set
686  template < typename Key, typename Alloc >
687  INLINE Set< Key, Alloc >& Set< Key, Alloc >::operator>>(const Key& k) {
688  erase(k);
689  return *this;
690  }
691 
692  // returns the number of elements in the set
693  template < typename Key, typename Alloc >
694  INLINE Size Set< Key, Alloc >::size() const noexcept {
695  return _inside_.size();
696  }
697 
698  // indicates whether the set is the empty set
699  template < typename Key, typename Alloc >
700  INLINE bool Set< Key, Alloc >::empty() const noexcept {
701  return _inside_.empty();
702  }
703 
704  // Intersection operator
705  template < typename Key, typename Alloc >
706  template < typename OtherAlloc >
707  Set< Key, Alloc > Set< Key, Alloc >::operator*(const Set< Key, OtherAlloc >& s2) const {
708  Set< Key, Alloc > res;
709  const HashTable< Key, bool, OtherAlloc >& h2 = s2._inside_;
710  HashTable< Key, bool, Alloc >& h_r = res._inside_;
711 
712  if (size() < h2.size()) {
714  ++iter) {
715  if (h2.exists(iter.key())) h_r.insert(iter.key(), true);
716  }
717  } else {
718  for (HashTableConstIterator< Key, bool > iter = h2.cbegin(); iter != h2.cend(); ++iter) {
719  if (_inside_.exists(iter.key())) h_r.insert(iter.key(), true);
720  }
721  }
722 
723  return res;
724  }
725 
726 
727  // Intersection update operator
728  template < typename Key, typename Alloc >
729  template < typename OtherAlloc >
730  const Set< Key, Alloc >& Set< Key, Alloc >::operator*=(const Set< Key, OtherAlloc >& s2) {
731  if (&s2 != this) {
732  const HashTable< Key, bool, OtherAlloc >& h2 = s2._inside_;
733  for (auto iter = _inside_.beginSafe(); iter != _inside_.endSafe(); ++iter) {
734  if (!h2.exists(iter.key())) _inside_.erase(iter);
735  }
736  }
737 
738  return *this;
739  }
740 
741 
742  // Union update operator
743  template < typename Key, typename Alloc >
744  template < typename OtherAlloc >
745  const Set< Key, Alloc >& Set< Key, Alloc >::operator+=(const Set< Key, OtherAlloc >& s2) {
746  if (&s2 != this) {
747  for (auto pair: s2._inside_) {
749  }
750  }
751 
752  return *this;
753  }
754 
755 
756  // Union operator
757  template < typename Key, typename Alloc >
758  template < typename OtherAlloc >
759  Set< Key, Alloc > Set< Key, Alloc >::operator+(const Set< Key, OtherAlloc >& s2) const {
760  Set< Key, Alloc > res = *this;
761  const HashTable< Key, bool, OtherAlloc >& h2 = s2._inside_;
762  HashTable< Key, bool, Alloc >& h_r = res._inside_;
763 
764  for (HashTableConstIterator< Key, bool > iter = h2.cbegin(); iter != h2.cend(); ++iter) {
765  if (!h_r.exists(iter.key())) h_r.insert(iter.key(), true);
766  }
767 
768  return res;
769  }
770 
771 
772  // Disjunction operator
773  template < typename Key, typename Alloc >
774  template < typename OtherAlloc >
775  Set< Key, Alloc > Set< Key, Alloc >::operator-(const Set< Key, OtherAlloc >& s2) const {
776  Set< Key, Alloc > res;
777  const HashTable< Key, bool, OtherAlloc >& h2 = s2._inside_;
778  HashTable< Key, bool, Alloc >& h_r = res._inside_;
779 
781  ++iter)
782  if (!h2.exists(iter.key())) h_r.insert(iter.key(), true);
783 
784  return res;
785  }
786 
787  // to display the content of the set
788  template < typename Key, typename Alloc >
791  bool first = true;
792  out << "{";
793 
794  for (iterator iter = begin(); iter != end(); ++iter) {
795  if (first) {
796  out << *iter;
797  first = false;
798  } else {
799  out << "," << *iter;
800  }
801  }
802 
803  out << "}";
804 
805  std::string res;
806  out >> res;
807  return res;
808  }
809 
810  // to friendly display the content of the set
811  template < typename Key, typename Alloc >
813  stream << set.toString();
814  return stream;
815  }
816 
817  // creates a hashtable of NewKey from the set
818  template < typename Key, typename Alloc >
819  template < typename NewKey, typename NewAlloc >
821  Size size) const {
822  // determine the proper size of the hashtable
823  // by default, the size of the table is set so that the table does not take
824  // too much space while allowing to add a few elements without resizing
825  if (size == 0) size = std::max(Size(2), _inside_.size() / 2);
826 
827  // create a new table
829 
830  // fill the new hash table
832  ++iter) {
833  table.insert(iter.key(), f(iter.key()));
834  }
835 
836  return table;
837  }
838 
839  // creates a hashtable of NewKey from the set
840  template < typename Key, typename Alloc >
841  template < typename NewKey, typename NewAlloc >
843  Size size) const {
844  // determine the proper size of the hashtable
845  // by default, the size of the table is set so that the table does not take
846  // too much space while allowing to add a few elements without resizing
847  if (size == 0) size = std::max(Size(2), _inside_.size() / 2);
848 
849  // create a new table
851 
852  // fill the new hash table
854  ++iter) {
855  table.insert(iter.key(), val);
856  }
857 
858  return table;
859  }
860 
861  // a method to create a list of NewKey from the set
862  template < typename Key, typename Alloc >
863  template < typename NewKey, typename NewAlloc >
864  List< NewKey, NewAlloc > Set< Key, Alloc >::listMap(NewKey (*f)(const Key&)) const {
865  // create a new list
866  List< NewKey, NewAlloc > list;
867 
868  // fill the new list
870  ++iter) {
871  list.pushBack(f(iter.key()));
872  }
873 
874  return list;
875  }
876 
877  // Returns the value of a key as a Size
878  template < typename T, typename Alloc >
880  Size h = Size(0);
881  for (const auto& k: key) {
882  const auto hs = HashFunc< T >::castToSize(k);
883  h += hs * (hs ^ HashFuncConst::gold);
884  }
885 
886  return h;
887  }
888 
889 
890  // Returns the hashed value of a key.
891  template < typename T, typename Alloc >
892  INLINE Size HashFunc< Set< T, Alloc > >::operator()(const Set< T, Alloc >& key) const {
893  return (castToSize(key) * HashFuncConst::gold) & this->hash_mask_;
894  }
895 
896 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643