aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
set_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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 >
47  Position pos) :
49  : set.inside__.cbeginSafe()} {
51  }
52 
53  // copy constructor
54  template < typename Key >
55  INLINE
59  }
60 
61  // copy constructor
62  template < typename Key >
66  }
67 
68  // move constructor
69  template < typename Key >
73  }
74 
75  // destructor
76  template < typename Key >
79  }
80 
81  // assignment operator
82  template < typename Key >
86  return *this;
87  }
88 
89  // assignment operator
90  template < typename Key >
94  return *this;
95  }
96 
97  // move operator
98  template < typename Key >
102  return *this;
103  }
104 
105  // increments the iterator
106  template < typename Key >
108  // note that, if the hashtable's iterator points toward nothing, the
109  // hashtable's iterator incrementation will do nothing. In particular, it
110  // will not segfault.
111  ++ht_iter__;
112  return *this;
113  }
114 
115  // makes the iterator point to i elements further in the set
116  template < typename Key >
118  SetIteratorSafe< Key >::operator+=(Size nb) noexcept {
119  ht_iter__ += nb;
120  return *this;
121  }
122 
123  // returns a new iterator
124  template < typename Key >
126  return SetIteratorSafe< Key >{*this} += nb;
127  }
128 
129  // indicates whether two iterators point to different elements or sets
130  template < typename Key >
132  const SetIteratorSafe< Key >& from) const noexcept {
133  return ht_iter__ != from.ht_iter__;
134  }
135 
136  // indicates whether two iterators point toward the same element of a same
137  // set
138  template < typename Key >
140  const SetIteratorSafe< Key >& from) const noexcept {
141  return ht_iter__ == from.ht_iter__;
142  }
143 
144  // returns the element pointed to by the iterator
145  template < typename Key >
146  INLINE const Key& SetIteratorSafe< Key >::operator*() const {
147  // note that, if the hashtable's iterator points toward nothing, it will
148  // raise an UndefinedIteratorValue exception
149  return ht_iter__.key();
150  }
151 
152  // returns aointer to the element pointed to by the iterator
153  template < typename Key >
154  INLINE const Key* SetIteratorSafe< Key >::operator->() const {
155  // note that, if the hashtable's iterator points toward nothing, it will
156  // raise an UndefinedIteratorValue exception
157  return &(ht_iter__.key());
158  }
159 
160  // @brief makes the iterator point toward nothing (in particular, it is not
161  // related anymore to its current set) */
162  template < typename Key >
163  INLINE void SetIteratorSafe< Key >::clear() noexcept {
164  ht_iter__.clear();
165  }
166 
167  // ===========================================================================
168  // === UNSAFE SET ITERATORS ===
169  // ===========================================================================
170 
171  // default constructor: the iterator points toward nothing
172  template < typename Key >
175  }
176 
177  // creates an iterator for a given set
178  template < typename Key >
179  template < typename Alloc >
181  Position pos) :
183  : set.inside__.cbegin()} {
185  }
186 
187  // copy constructor
188  template < typename Key >
192  }
193 
194  // move constructor
195  template < typename Key >
199  }
200 
201  // destructor
202  template < typename Key >
203  INLINE SetIterator< Key >::~SetIterator() noexcept {
205  }
206 
207  // assignment operator
208  template < typename Key >
210  SetIterator< Key >::operator=(const SetIterator< Key >& from) noexcept {
212  return *this;
213  }
214 
215  // move operator
216  template < typename Key >
218  SetIterator< Key >::operator=(SetIterator< Key >&& from) noexcept {
220  return *this;
221  }
222 
223  // increments the iterator
224  template < typename Key >
225  INLINE SetIterator< Key >& SetIterator< Key >::operator++() noexcept {
226  // note that, if the hashtable's iterator points toward nothing, the
227  // hashtable's iterator incrementation will do nothing. In particular, it
228  // will not segfault.
229  ++ht_iter__;
230  return *this;
231  }
232 
233  // makes the iterator point to i elements further in the set
234  template < typename Key >
236  ht_iter__ += nb;
237  return *this;
238  }
239 
240  // returns a new iterator
241  template < typename Key >
242  INLINE SetIterator< Key > SetIterator< Key >::operator+(Size nb) const noexcept {
243  return SetIterator< Key >{*this} += nb;
244  }
245 
246  // indicates whether two iterators point to different elements or sets
247  template < typename Key >
249  const SetIterator< Key >& from) const noexcept {
250  return ht_iter__ != from.ht_iter__;
251  }
252 
253  // indicates whether two iterators point toward the same element of a same
254  // set
255  template < typename Key >
257  const SetIterator< Key >& from) const noexcept {
258  return ht_iter__ == from.ht_iter__;
259  }
260 
261  // returns the element pointed to by the iterator
262  template < typename Key >
263  INLINE const Key& SetIterator< Key >::operator*() const {
264  // note that, if the hashtable's iterator points toward nothing, it will
265  // raise an UndefinedIteratorValue exception
266  return ht_iter__.key();
267  }
268 
269  // returns aointer to the element pointed to by the iterator
270  template < typename Key >
271  INLINE const Key* SetIterator< Key >::operator->() const {
272  // note that, if the hashtable's iterator points toward nothing, it will
273  // raise an UndefinedIteratorValue exception
274  return &(ht_iter__.key());
275  }
276 
277  // @brief makes the iterator point toward nothing (in particular, it is not
278  // related anymore to its current set) */
279  template < typename Key >
280  INLINE void SetIterator< Key >::clear() noexcept {
281  ht_iter__.clear();
282  }
283 
284  // ===========================================================================
285  // === SETS ===
286  // ===========================================================================
287 
288  // returns the end iterator for other classes' statics
289  template < typename Key, typename Alloc >
291  return *(reinterpret_cast< const SetIteratorSafe< Key >* >(
293  }
294 
295  // returns the end iterator for other classes' statics
296  template < typename Key, typename Alloc >
298  return *(reinterpret_cast< const SetIteratorSafe< Key >* >(
300  }
301 
302  // returns the end iterator for other classes' statics
303  template < typename Key, typename Alloc >
305  return *(reinterpret_cast< const SetIterator< Key >* >(
307  }
308 
309  // returns the end iterator for other classes' statics
310  template < typename Key, typename Alloc >
312  return *(reinterpret_cast< const SetIterator< Key >* >(
314  }
315 
316  // default constructor
317  template < typename Key, typename Alloc >
319  // create the hash table without key uniqueness policy (as we will
320  // check
321  // ourselves the uniqueness of Keys before inserting new elements)
322  inside__(capacity, resize_policy, false) {
324 
325  // make sure the end() iterator is constructed properly
326  endSafe4Statics();
327  end4Statics();
328  }
329 
330  // initializer list constructor
331  template < typename Key, typename Alloc >
333  inside__(Size(list.size()) / 2, true, false) {
335  for (const auto& elt: list) {
336  insert(elt);
337  }
338 
339  // make sure the end() iterator is constructed properly
340  endSafe4Statics();
341  end4Statics();
342  }
343 
344  // copy constructor
345  template < typename Key, typename Alloc >
346  INLINE Set< Key, Alloc >::Set(const Set< Key, Alloc >& s) :
347  inside__(s.inside__) {
348  GUM_CONS_CPY(Set);
349  }
350 
351  // generalized copy constructor
352  template < typename Key, typename Alloc >
353  template < typename OtherAlloc >
354  INLINE Set< Key, Alloc >::Set(const Set< Key, OtherAlloc >& s) :
355  inside__(s.inside__) {
356  GUM_CONS_CPY(Set);
357  }
358 
359  // move constructor
360  template < typename Key, typename Alloc >
361  INLINE Set< Key, Alloc >::Set(Set< Key, Alloc >&& s) :
362  inside__(std::move(s.inside__)) {
363  GUM_CONS_MOV(Set);
364  }
365 
366  // destructor
367  template < typename Key, typename Alloc >
368  INLINE Set< Key, Alloc >::Set::~Set() {
370  }
371 
372  // removes all the elements, if any, from the set
373  template < typename Key, typename Alloc >
374  INLINE void Set< Key, Alloc >::clear() {
375  // first we remove all the elements from the hashtable actually containing
376  // the elements of the set. Note that, doing so, all the hashtable iterators
377  // will be updated as well. In turn, this will imply that, whenever an
378  // operation will be performed on a SetIteratorSafe, this will raise an
379  // exception.
380  inside__.clear();
381 
382  // Note that actually there is no need to update the end iterator as this
383  // one
384  // is not affected by changes within hashtables (adding/deleting elements).
385  // Hence, for speedup, we do not update the end iterator
386  }
387 
388  // copy operator
389  template < typename Key, typename Alloc >
390  Set< Key, Alloc >& Set< Key, Alloc >::operator=(const Set< Key, Alloc >& s) {
391  // avoid self assignment
392  if (&s != this) {
393  // remove the old content of the set. Actually, we remove all the elements
394  // from the underlying hashtable. Note that, doing so, all the hashtable
395  // iterators will be updated as well. In turn, this will imply that,
396  // whenever
397  // an operation will be performed on a SetIteratorSafe, this will raise an
398  // exception.
399  clear();
400 
401  // prepare the set for its new data
402  resize(s.capacity());
404 
405  // copy the set
406  inside__ = s.inside__;
407 
408  // Note that actually there is no need to update the end iterator as this
409  // one
410  // is not affected by changes within hashtables (adding/deleting
411  // elements).
412  // Hence, for speedup, we do not update the end iterator
413  }
414 
415  return *this;
416  }
417 
418  // generalized copy operator
419  template < typename Key, typename Alloc >
420  template < typename OtherAlloc >
421  Set< Key, Alloc >&
422  Set< Key, Alloc >::operator=(const Set< Key, OtherAlloc >& s) {
423  // avoid self assignment
424  if (this != reinterpret_cast< const Set< Key, Alloc >* >(&s)) {
425  // remove the old content of the set. Actually, we remove all the elements
426  // from the underlying hashtable. Note that, doing so, all the hashtable
427  // iterators will be updated as well. In turn, this will imply that,
428  // whenever
429  // an operation will be performed on a SetIteratorSafe, this will raise an
430  // exception.
431  clear();
432 
433  // prepare the set for its new data
434  resize(s.capacity());
436 
437  // copy the set
438  inside__ = s.inside__;
439 
440  // Note that actually there is no need to update the end iterator as this
441  // one
442  // is not affected by changes within hashtables (adding/deleting
443  // elements).
444  // Hence, for speedup, we do not update the end iterator
445  }
446 
447  return *this;
448  }
449 
450  // move operator
451  template < typename Key, typename Alloc >
452  Set< Key, Alloc >& Set< Key, Alloc >::operator=(Set< Key, Alloc >&& from) {
454  return *this;
455  }
456 
457  // mathematical equality between two sets
458  template < typename Key, typename Alloc >
459  template < typename OtherAlloc >
460  bool Set< Key, Alloc >::operator==(const Set< Key, OtherAlloc >& s2) const {
461  const HashTable< Key, bool, OtherAlloc >& h2 = s2.inside__;
462 
463  // check whether both sets have the same number of elements
464  if (size() != h2.size()) return false;
465 
466  // check the content of the sets
467  for (HashTableConstIterator< Key, bool > iter = inside__.cbegin();
468  iter != inside__.cend();
469  ++iter) {
470  if (!h2.exists(iter.key())) return false;
471  }
472 
473  return true;
474  }
475 
476  // mathematical inequality between two sets
477  template < typename Key, typename Alloc >
478  template < typename OtherAlloc >
479  INLINE bool
480  Set< Key, Alloc >::operator!=(const Set< Key, OtherAlloc >& s2) const {
481  return !(operator==(s2));
482  }
483 
484  // the usual begin iterator to parse the set
485  template < typename Key, typename Alloc >
486  INLINE typename Set< Key, Alloc >::iterator_safe
487  Set< Key, Alloc >::beginSafe() const {
488  return SetIteratorSafe< Key >{*this};
489  }
490 
491  // the usual begin iterator to parse the set
492  template < typename Key, typename Alloc >
493  INLINE typename Set< Key, Alloc >::const_iterator_safe
494  Set< Key, Alloc >::cbeginSafe() const {
495  return SetIteratorSafe< Key >{*this};
496  }
497 
498  // the usual end iterator to parse the set
499  template < typename Key, typename Alloc >
500  INLINE const typename Set< Key, Alloc >::iterator_safe&
501  Set< Key, Alloc >::endSafe() const noexcept {
502  return *(reinterpret_cast< const SetIteratorSafe< Key >* >(
504  }
505 
506  // the usual end iterator to parse the set
507  template < typename Key, typename Alloc >
508  INLINE const typename Set< Key, Alloc >::const_iterator_safe&
509  Set< Key, Alloc >::cendSafe() const noexcept {
510  return *(reinterpret_cast< const SetIteratorSafe< Key >* >(
512  }
513 
514  // the usual begin iterator to parse the set
515  template < typename Key, typename Alloc >
516  INLINE typename Set< Key, Alloc >::iterator Set< Key, Alloc >::begin() const {
517  return SetIterator< Key >{*this};
518  }
519 
520  // the usual begin iterator to parse the set
521  template < typename Key, typename Alloc >
522  INLINE typename Set< Key, Alloc >::const_iterator
523  Set< Key, Alloc >::cbegin() const {
524  return SetIterator< Key >{*this};
525  }
526 
527  // the usual end iterator to parse the set
528  template < typename Key, typename Alloc >
529  INLINE const typename Set< Key, Alloc >::iterator&
530  Set< Key, Alloc >::end() const noexcept {
531  return *(reinterpret_cast< const SetIterator< Key >* >(
533  }
534 
535  // the usual end iterator to parse the set
536  template < typename Key, typename Alloc >
537  INLINE const typename Set< Key, Alloc >::const_iterator&
538  Set< Key, Alloc >::cend() const noexcept {
539  return *(reinterpret_cast< const SetIterator< Key >* >(
541  }
542 
543  // returns the size of the underlying hashtable containing the set
544  template < typename Key, typename Alloc >
545  INLINE Size Set< Key, Alloc >::capacity() const {
546  return inside__.capacity();
547  }
548 
549  // changes the size of the underlying hashtable
550  template < typename Key, typename Alloc >
553 
554  // Note that actually there is no need to update the end iterator as this
555  // one
556  // is not affected by changes within hashtables (adding/deleting elements).
557  // Hence, for speedup, we do not update the end iterator
558  }
559 
560  // enables the user to change dynamically the resizing policy of the
561  // underlying hashtable
562  template < typename Key, typename Alloc >
563  INLINE void Set< Key, Alloc >::setResizePolicy(const bool new_policy) {
565 
566  // Note that actually there is no need to update the end iterator as this
567  // one
568  // is not affected by changes within hashtables (adding/deleting elements).
569  // Hence, for speedup, we do not update the end iterator
570  }
571 
572  // returns the current resizing policy of the underlying hashtable
573  template < typename Key, typename Alloc >
574  INLINE bool Set< Key, Alloc >::resizePolicy() const {
575  return inside__.resizePolicy();
576  }
577 
578  // indicates whether a given elements belong to the set
579  template < typename Key, typename Alloc >
580  INLINE bool Set< Key, Alloc >::contains(const Key& k) const {
581  return inside__.exists(k);
582  }
583 
584 
585  template < typename Key, typename Alloc >
586  template < typename OtherAlloc >
587  INLINE bool
588  Set< Key, Alloc >::isProperSubsetOf(const Set< Key, OtherAlloc >& s) const {
589  if (this->size() >= s.size()) { return false; }
590 
591  for (const auto& elt: *this) {
592  if (!s.contains(elt)) { return false; }
593  }
594  return true;
595  }
596 
597  template < typename Key, typename Alloc >
598  template < typename OtherAlloc >
599  INLINE bool
600  Set< Key, Alloc >::isProperSupersetOf(const Set< Key, OtherAlloc >& s) const {
601  return s.isProperSubsetOf(*this);
602  }
603 
604 
605  template < typename Key, typename Alloc >
606  template < typename OtherAlloc >
607  INLINE bool
608  Set< Key, Alloc >::isSubsetOrEqual(const Set< Key, OtherAlloc >& s) const {
609  if (this->size() > s.size()) { return false; }
610 
611  for (const auto& elt: *this) {
612  if (!s.contains(elt)) { return false; }
613  }
614  return true;
615  }
616 
617  template < typename Key, typename Alloc >
618  template < typename OtherAlloc >
619  INLINE bool
620  Set< Key, Alloc >::isSupersetOrEqual(const Set< Key, OtherAlloc >& s) const {
621  return s.isSubsetOrEqual(*this);
622  }
623 
624  // indicates whether a given elements belong to the set
625  template < typename Key, typename Alloc >
626  INLINE bool Set< Key, Alloc >::exists(const Key& k) const {
627  return inside__.exists(k);
628  }
629 
630  // inserts a new element in the set
631  template < typename Key, typename Alloc >
632  INLINE void Set< Key, Alloc >::insert(const Key& k) {
633  // WARNING: we shall always test whether k already belongs to the set before
634  // trying to insert it because we set inside__'s key uniqueness policy to
635  // false
636  if (!contains(k)) {
637  // insert the element
638  inside__.insert(k, true);
639 
640  // Note that actually there is no need to update the end iterator as this
641  // one
642  // is not affected by changes within hashtables (adding/deleting
643  // elements).
644  // Hence, for speedup, we do not update the end iterator
645  }
646  }
647 
648  // inserts a new element in the set
649  template < typename Key, typename Alloc >
650  INLINE void Set< Key, Alloc >::insert(Key&& k) {
651  // WARNING: we shall always test whether k already belongs to the set before
652  // trying to insert it because we set inside__'s key uniqueness policy to
653  // false
654  if (!contains(k)) {
655  // insert the element
656  inside__.insert(std::move(k), true);
657 
658  // Note that actually there is no need to update the end iterator as this
659  // one
660  // is not affected by changes within hashtables (adding/deleting
661  // elements).
662  // Hence, for speedup, we do not update the end iterator
663  }
664  }
665 
666  // emplace a new element in the set
667  template < typename Key, typename Alloc >
668  template < typename... Args >
669  INLINE void Set< Key, Alloc >::emplace(Args&&... args) {
670  insert(std::move(Key(std::forward< Args >(args)...)));
671  }
672 
673  // erases an element from the set
674  template < typename Key, typename Alloc >
675  INLINE void Set< Key, Alloc >::erase(const Key& k) {
676  // erase the element (if it exists)
677  inside__.erase(k);
678 
679  // Note that actually there is no need to update the end iterator as this
680  // one
681  // is not affected by changes within hashtables (adding/deleting elements).
682  // Hence, for speedup, we do not update the end iterator
683  }
684 
685  // erases an element from the set
686  template < typename Key, typename Alloc >
687  INLINE void Set< Key, Alloc >::erase(const SetIteratorSafe< Key >& iter) {
688  // erase the element
690 
691  // Note that actually there is no need to update the end iterator as this
692  // one
693  // is not affected by changes within hashtables (adding/deleting elements).
694  // Hence, for speedup, we do not update the end iterator
695  }
696 
697  // adds a new element to the set
698  template < typename Key, typename Alloc >
699  INLINE Set< Key, Alloc >& Set< Key, Alloc >::operator<<(const Key& k) {
700  insert(k);
701  return *this;
702  }
703 
704  // adds a new element to the set
705  template < typename Key, typename Alloc >
707  insert(std::move(k));
708  return *this;
709  }
710 
711  // removes an element from the set
712  template < typename Key, typename Alloc >
713  INLINE Set< Key, Alloc >& Set< Key, Alloc >::operator>>(const Key& k) {
714  erase(k);
715  return *this;
716  }
717 
718  // returns the number of elements in the set
719  template < typename Key, typename Alloc >
720  INLINE Size Set< Key, Alloc >::size() const noexcept {
721  return inside__.size();
722  }
723 
724  // indicates whether the set is the empty set
725  template < typename Key, typename Alloc >
726  INLINE bool Set< Key, Alloc >::empty() const noexcept {
727  return inside__.empty();
728  }
729 
730  // Intersection operator
731  template < typename Key, typename Alloc >
732  template < typename OtherAlloc >
733  Set< Key, Alloc >
734  Set< Key, Alloc >::operator*(const Set< Key, OtherAlloc >& s2) const {
735  Set< Key, Alloc > res;
736  const HashTable< Key, bool, OtherAlloc >& h2 = s2.inside__;
737  HashTable< Key, bool, Alloc >& h_r = res.inside__;
738 
739  if (size() < h2.size()) {
740  for (HashTableConstIterator< Key, bool > iter = inside__.cbegin();
741  iter != inside__.cend();
742  ++iter) {
743  if (h2.exists(iter.key())) h_r.insert(iter.key(), true);
744  }
745  } else {
746  for (HashTableConstIterator< Key, bool > iter = h2.cbegin();
747  iter != h2.cend();
748  ++iter) {
749  if (inside__.exists(iter.key())) h_r.insert(iter.key(), true);
750  }
751  }
752 
753  return res;
754  }
755 
756 
757  // Intersection update operator
758  template < typename Key, typename Alloc >
759  template < typename OtherAlloc >
760  const Set< Key, Alloc >&
761  Set< Key, Alloc >::operator*=(const Set< Key, OtherAlloc >& s2) {
762  if (&s2 != this) {
763  const HashTable< Key, bool, OtherAlloc >& h2 = s2.inside__;
764  for (auto iter = inside__.beginSafe(); iter != inside__.endSafe(); ++iter) {
765  if (!h2.exists(iter.key())) inside__.erase(iter);
766  }
767  }
768 
769  return *this;
770  }
771 
772 
773  // Union update operator
774  template < typename Key, typename Alloc >
775  template < typename OtherAlloc >
776  const Set< Key, Alloc >&
777  Set< Key, Alloc >::operator+=(const Set< Key, OtherAlloc >& s2) {
778  if (&s2 != this) {
779  for (auto pair: s2.inside__) {
781  }
782  }
783 
784  return *this;
785  }
786 
787 
788  // Union operator
789  template < typename Key, typename Alloc >
790  template < typename OtherAlloc >
791  Set< Key, Alloc >
792  Set< Key, Alloc >::operator+(const Set< Key, OtherAlloc >& s2) const {
793  Set< Key, Alloc > res = *this;
794  const HashTable< Key, bool, OtherAlloc >& h2 = s2.inside__;
795  HashTable< Key, bool, Alloc >& h_r = res.inside__;
796 
797  for (HashTableConstIterator< Key, bool > iter = h2.cbegin(); iter != h2.cend();
798  ++iter) {
799  if (!h_r.exists(iter.key())) h_r.insert(iter.key(), true);
800  }
801 
802  return res;
803  }
804 
805 
806  // Disjunction operator
807  template < typename Key, typename Alloc >
808  template < typename OtherAlloc >
809  Set< Key, Alloc >
810  Set< Key, Alloc >::operator-(const Set< Key, OtherAlloc >& s2) const {
811  Set< Key, Alloc > res;
812  const HashTable< Key, bool, OtherAlloc >& h2 = s2.inside__;
813  HashTable< Key, bool, Alloc >& h_r = res.inside__;
814 
815  for (HashTableConstIterator< Key, bool > iter = inside__.cbegin();
816  iter != inside__.cend();
817  ++iter)
818  if (!h2.exists(iter.key())) h_r.insert(iter.key(), true);
819 
820  return res;
821  }
822 
823  // to display the content of the set
824  template < typename Key, typename Alloc >
827  bool first = true;
828  out << "{";
829 
830  for (iterator iter = begin(); iter != end(); ++iter) {
831  if (first) {
832  out << *iter;
833  first = false;
834  } else {
835  out << "," << *iter;
836  }
837  }
838 
839  out << "}";
840 
841  std::string res;
842  out >> res;
843  return res;
844  }
845 
846  // to friendly display the content of the set
847  template < typename Key, typename Alloc >
849  stream << set.toString();
850  return stream;
851  }
852 
853  // creates a hashtable of NewKey from the set
854  template < typename Key, typename Alloc >
855  template < typename NewKey, typename NewAlloc >
857  Set< Key, Alloc >::hashMap(NewKey (*f)(const Key&), Size size) const {
858  // determine the proper size of the hashtable
859  // by default, the size of the table is set so that the table does not take
860  // too much space while allowing to add a few elements without resizing
861  if (size == 0) size = std::max(Size(2), inside__.size() / 2);
862 
863  // create a new table
865 
866  // fill the new hash table
867  for (HashTableConstIterator< Key, bool > iter = inside__.cbegin();
868  iter != inside__.cend();
869  ++iter) {
870  table.insert(iter.key(), f(iter.key()));
871  }
872 
873  return table;
874  }
875 
876  // creates a hashtable of NewKey from the set
877  template < typename Key, typename Alloc >
878  template < typename NewKey, typename NewAlloc >
880  Size size) const {
881  // determine the proper size of the hashtable
882  // by default, the size of the table is set so that the table does not take
883  // too much space while allowing to add a few elements without resizing
884  if (size == 0) size = std::max(Size(2), inside__.size() / 2);
885 
886  // create a new table
888 
889  // fill the new hash table
890  for (HashTableConstIterator< Key, bool > iter = inside__.cbegin();
891  iter != inside__.cend();
892  ++iter) {
893  table.insert(iter.key(), val);
894  }
895 
896  return table;
897  }
898 
899  // a method to create a list of NewKey from the set
900  template < typename Key, typename Alloc >
901  template < typename NewKey, typename NewAlloc >
902  List< NewKey, NewAlloc >
903  Set< Key, Alloc >::listMap(NewKey (*f)(const Key&)) const {
904  // create a new list
905  List< NewKey, NewAlloc > list;
906 
907  // fill the new list
908  for (HashTableConstIterator< Key, bool > iter = inside__.cbegin();
909  iter != inside__.cend();
910  ++iter) {
911  list.pushBack(f(iter.key()));
912  }
913 
914  return list;
915  }
916 
917  // Returns the value of a key as a Size
918  template < typename T, typename Alloc >
920  Size h = Size(0);
921  for (const auto& k: key) {
922  const auto hs = HashFunc< T >::castToSize(k);
923  h += hs * (hs ^ HashFuncConst::gold);
924  }
925 
926  return h;
927  }
928 
929 
930  // Returns the hashed value of a key.
931  template < typename T, typename Alloc >
932  INLINE Size
933  HashFunc< Set< T, Alloc > >::operator()(const Set< T, Alloc >& key) const {
934  return (castToSize(key) * HashFuncConst::gold) & this->hash_mask_;
935  }
936 
937 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669