aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
set.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 Sets of elements (i.e. the mathematical notion of a set).
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27  */
28 #ifndef GUM_SET_H
29 #define GUM_SET_H
30 
31 #include <initializer_list>
32 #include <iostream>
33 #include <sstream>
34 #include <string>
35 
36 #include <agrum/tools/core/debug.h>
37 #include <agrum/tools/core/hashTable.h>
38 #include <agrum/tools/core/list.h>
39 
40 namespace gum {
41 
42 #ifndef DOXYGEN_SHOULD_SKIP_THIS
43 
44  template < typename Key >
45  class SetIteratorSafe;
46  template < typename Key >
47  class SetIterator;
48  template < typename Key, typename Alloc >
49  class Set;
50 
51  template < typename Key >
52  using SetConstIterator = SetIterator< Key >;
53  template < typename Key >
54  using SetConstIteratorSafe = SetIteratorSafe< Key >;
55 
56 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
57 
58  /**
59  * @class SetIteratorStaticEnd
60  * @headerfile set.h <agrum/tools/core/set.h>
61  * @brief A class used to create the static iterator used by Sets.
62  * @ingroup set_group
63  *
64  * The aim of using this class rather than just creating _SetIterEnd_ as a
65  * global variable is to prevent other classes to access and modify
66  * _SetIterEnd_.
67  */
68  class SetIteratorStaticEnd {
69  private:
70  /**
71  * @brief The safe iterator used by everyone.
72  * @return Returns the safe iterator used by everyone.
73  */
74  static const SetIteratorSafe< int >* _SetIterEndSafe_;
75 
76  /**
77  * @brief The unsafe iterator used by everyone.
78  * @return Returns the unsafe iterator used by everyone.
79  */
80  static const SetIterator< int >* _SetIterEnd_;
81 
82  /**
83  * @brief Creates (if needed) and returns the iterator _SetIterEndSafe_.
84  * @return Returns the iterator _SetIterEndSafe_.
85  */
86  static const SetIteratorSafe< int >* endSafe4Statics();
87 
88  /**
89  * @brief Creates (if needed) and returns the iterator _SetIterEndSafe_.
90  * @return Returns the iterator _SetIterEndSafe_.
91  */
92  static const SetIteratorSafe< int >* constEndSafe4Statics();
93 
94  /**
95  * @brief Creates (if needed) and returns the iterator _SetIterEnd_.
96  * @return Returns the iterator _SetIterEnd_.
97  */
98  static const SetIterator< int >* end4Statics();
99 
100  /**
101  * @brief Creates (if needed) and returns the iterator _SetIterEnd_.
102  * @return Returns the iterator _SetIterEnd_.
103  */
104  static const SetIterator< int >* constEnd4Statics();
105 
106  /// Friends that have access to the iterator.
107  template < typename Key, typename Alloc >
108  friend class Set;
109  };
110 
111 
112  // ===========================================================================
113  // === GUM_SET ===
114  // ===========================================================================
115 
116  /**
117  * @class Set
118  * @headerfile set.h <agrum/tools/core/set.h>
119  * @brief Representation of a set
120  * @ingroup basicstruct_group
121  * @ingroup set_group
122  *
123  * A Set is a structure that contains arbitrary elements. Note that, as in
124  * mathematics, an element cannot appear twice in a given set. Sets have
125  * unsafe and safe iterators. The safe iterators (SetIteratorSafe<> a.k.a.
126  * Set<>::iterator_safe are slightly slower than the unsafe ones
127  * (SetIterator<> a.k.a. Set<>::iterator) but they guarantee that even if
128  * they point to a deleted element, using their operators ++ or * cannot
129  * produce a segfault. In such cases, they simply raise an exception. On the
130  * contrary, unsafe iterators should @b never be used on elements that can be
131  * deleted because, as in the STL, they will most probably produce a
132  * segfault.
133  *
134  * @par Usage example:
135  * @code
136  * // creation of a set with 10 elements
137  * Set<int> set;
138  * for (int i = 0; i< 10; ++i)
139  * set<<i;
140  * Set<int> set2 { 1, 2, 3 };
141  *
142  * // parse the set
143  * for (const auto iter = set.begin (); iter != set.end (); ++iter) {
144  * // display the values
145  * cerr << *iter << endl;
146  * }
147  *
148  * // use an iterator to point the element we wish to erase
149  * Set<int>::iterator iter = set.begin ();
150  * set.erase ( iter );
151  *
152  * // check whether two iterators point toward the same element
153  * Set<int>::iterator iter1 = set.begin();
154  * Set<int>::iterator iter2 = set.end();
155  * if (iter1 != iter2)
156  * cerr << "iter1 and iter2 point toward different elements";
157  *
158  * @endcode
159  *
160  * @tparam Key The elements type.
161  * @tparam Alloc The elements allocator.
162  */
163  template < typename Key, typename Alloc = std::allocator< Key > >
164  class Set {
165  public:
166  /// Types for STL compliance.
167  /// @{
168  using value_type = Key;
169  using reference = Key&;
170  using const_reference = const Key&;
171  using pointer = Key*;
172  using const_pointer = const Key*;
173  using size_type = std::size_t;
174  using difference_type = std::ptrdiff_t;
175  using allocator_type = Alloc;
176  using iterator = SetIterator< Key >;
177  using const_iterator = SetIterator< Key >;
178  using iterator_safe = SetIteratorSafe< Key >;
179  using const_iterator_safe = SetIteratorSafe< Key >;
180  /// @}
181 
182  // ============================================================================
183  /// @name Constructors / Destructors
184  // ============================================================================
185  /// @{
186 
187  /**
188  * @brief Default constructor.
189  *
190  * Sets rely on hashtables to store their items. The optional parameters of
191  * this constructor enable a fine memory management of these hashtables.
192  *
193  * @param capacity The number of slots allocated to the hashtable (see the
194  * HashTable default constructor)
195  * @param resize_policy Enables the hashtable to resize itself
196  * automatically when its number of elements is sufficiently high that it
197  * induces slow retrievals of elements.
198  */
199  explicit Set(Size capacity = HashTableConst::default_size, bool resize_policy = true);
200 
201  /**
202  * @brief Initializer list constructor.
203  * @param list The initializer list.
204  */
205  Set(std::initializer_list< Key > list);
206 
207  /**
208  * @brief Copy constructor.
209  * @param aHT The gum::Set to copy.
210  */
211  Set(const Set< Key, Alloc >& aHT);
212 
213  /**
214  * @brief Generalized copy constructor.
215  * @param aHT The gum::Set to copy.
216  * @tparam OtherAlloc The other gum::Set allocator.
217  */
218  template < typename OtherAlloc >
219  Set(const Set< Key, OtherAlloc >& aHT);
220 
221  /**
222  * @brief Move constructor.
223  * @param aHT The gum::Set to move.
224  */
225  Set(Set< Key, Alloc >&& aHT);
226 
227  /**
228  * @brief Class destructor.
229  */
230  ~Set();
231 
232  /// @}
233  // ============================================================================
234  /// @name Operators
235  // ============================================================================
236  /// @{
237 
238  /**
239  * @brief Copy operator.
240  * @param from The gum::Set to copy.
241  * @return Returns this gum::Set.
242  */
243  Set< Key, Alloc >& operator=(const Set< Key, Alloc >& from);
244 
245  /**
246  * @brief Generalized copy operator.
247  * @param from The gum::Set to copy.
248  * @tparam OtherAlloc The other gum::Set allocator.
249  * @return Returns this gum::Set.
250  */
251  template < typename OtherAlloc >
252  Set< Key, Alloc >& operator=(const Set< Key, OtherAlloc >& from);
253 
254  /**
255  * @brief Move operator.
256  * @param from The gum::Set to move.
257  * @return Returns this gum::Set.
258  */
259  Set< Key, Alloc >& operator=(Set< Key, Alloc >&& from);
260 
261  /**
262  * @brief Mathematical equality between two sets.
263  * @param s2 The gum::Set to test for equality.
264  * @tparam OtherAlloc The other gum::Set allocator.
265  * @return Returns true if both gum::Set are equal.
266  */
267  template < typename OtherAlloc >
268  bool operator==(const Set< Key, OtherAlloc >& s2) const;
269 
270  /**
271  * @brief Mathematical inequality between two sets.
272  * @param s2 The gum::Set to test for inequality.
273  * @tparam OtherAlloc The other gum::Set allocator.
274  * @return Returns true if both gum::Set are not equal.
275  */
276  template < typename OtherAlloc >
277  bool operator!=(const Set< Key, OtherAlloc >& s2) const;
278 
279  /**
280  * @brief Intersection update operator
281  * @tparam OtherAlloc The other gum::Set allocator.
282  * @param s2 The gum::Set to intersect.
283  * @return Returns this. Now this contains the elements belonging
284  * both to this and s2.
285  */
286  template < typename OtherAlloc >
287  const Set< Key, Alloc >& operator*=(const Set< Key, OtherAlloc >& s2);
288 
289  /**
290  * @brief Intersection operator.
291  * @tparam OtherAlloc The other gum::Set allocator.
292  * @param s2 The gum::Set to intersect.
293  * @return Returns a Set containing the elements belonging both to this and
294  * s2.
295  */
296  template < typename OtherAlloc >
297  Set< Key, Alloc > operator*(const Set< Key, OtherAlloc >& s2) const;
298 
299  /**
300  * @brief Union update operator
301  * @tparam OtherAlloc The other gum::Set allocator.
302  * @param s2 The gum::Set to update
303  * @return Returns this. Now this contains the elements belonging
304  * both to this or to s2.
305  */
306  template < typename OtherAlloc >
307  const Set< Key, Alloc >& operator+=(const Set< Key, OtherAlloc >& s2);
308 
309  /**
310  * @brief Union operator.
311  * @tparam OtherAlloc The other gum::Set allocator.
312  * @param s2 The gum::Set to union.
313  * @return Returns a new Set containing the union of the elements of this
314  * and s2.
315  */
316  template < typename OtherAlloc >
317  Set< Key, Alloc > operator+(const Set< Key, OtherAlloc >& s2) const;
318 
319 
320  /**
321  * @brief Disjunction operator.
322  * @tparam OtherAlloc The other gum::Set allocator.
323  * @param s2 The gum::Set to disjunct.
324  * @return Returns a Set whose elements belong to this but not to s2.
325  * @warning Unlike + and *, the - operator is not commutative!
326  */
327  template < typename OtherAlloc >
328  Set< Key, Alloc > operator-(const Set< Key, OtherAlloc >& s2) const;
329 
330  /**
331  * @brief Adds a new element to the set (alias for insert).
332  * @param k The new element to add.
333  * @return Returns this gum::Set.
334  */
335  Set< Key, Alloc >& operator<<(const Key& k);
336 
337  /**
338  * @brief Adds a new element to the set (alias for insert).
339  * @param k The new element to add.
340  * @return Returns this gum::Set.
341  */
342  Set< Key, Alloc >& operator<<(Key&& k);
343 
344  /**
345  * @brief Removes an element from the set (alias for erase).
346  * @param k The element to remove.
347  * @return Return this gum::Set.
348  */
349  Set< Key, Alloc >& operator>>(const Key& k);
350 
351  /// @}
352  // ============================================================================
353  /// @name Accessors / Modifiers
354  // ============================================================================
355  /// @{
356 
357  /**
358  * @brief Inserts a new element into the set.
359  * @param k The new element to insert.
360  * @warning if the set already contains the element, nothing is done. In
361  * particular, it is not added to the set and no exception is thrown.
362  */
363  void insert(const Key& k);
364 
365  /**
366  * @brief Inserts a new element into the set.
367  * @param k The new element to insert.
368  * @warning if the set already contains the element, nothing is done. In
369  * particular, it is not added to the set and no exception is thrown.
370  */
371  void insert(Key&& k);
372 
373  /**
374  * @brief Emplace a new element in the set.
375  *
376  * Emplace is a method that allows to construct directly an element of type
377  * Key by passing to its constructor all the arguments it needs.
378  *
379  * @param args the arguments passed to the constructor
380  * @warning if the set already contains the element, nothing is done. In
381  * particular, it is not added to the set and no exception is thrown.
382  */
383  template < typename... Args >
384  void emplace(Args&&... args);
385 
386  /**
387  * @brief Erases an element from the set.
388  *
389  * @param k The element to remove.
390  * @warning if the set does not contain the element, nothing is done. In
391  * particular, no exception is thrown.
392  */
393  void erase(const Key& k);
394 
395  /**
396  * @brief Erases an element from the set.
397  * @param k The iterator pointing to the element to remove.
398  * @warning if the set does not contain the element, nothing is done. In
399  * particular, no exception is thrown.
400  */
401  void erase(const iterator_safe& k);
402 
403  /**
404  * @brief Removes all the elements, if any, from the set.
405  */
406  void clear();
407 
408  /**
409  * @brief Returns the number of elements in the set.
410  * @return Returns the number of elements in the set.
411  */
412  Size size() const noexcept;
413 
414  /**
415  * @brief Indicates whether a given elements belong to the set.
416  * @return Returns true if a given elements belong to the set.
417  */
418  bool contains(const Key& k) const;
419 
420  /**
421  * @return Returns true if *this is a proper subset of s
422  */
423  template < typename OtherAlloc >
424  bool isProperSubsetOf(const Set< Key, OtherAlloc >& s) const;
425 
426  /**
427  * @return Returns true if *this is a proper superset of s
428  */
429  template < typename OtherAlloc >
430  bool isProperSupersetOf(const Set< Key, OtherAlloc >& s) const;
431 
432  /**
433  * @return Returns true if *this is a subset of s (or equal to s)
434  */
435  template < typename OtherAlloc >
436  bool isSubsetOrEqual(const Set< Key, OtherAlloc >& s) const;
437 
438  /**
439  * @return Returns true if *this is a superset of s (or equal to s)
440  */
441  template < typename OtherAlloc >
442  bool isSupersetOrEqual(const Set< Key, OtherAlloc >& s) const;
443 
444  /**
445  * @brief Indicates whether a given elements belong to the set.
446  * @return Returns true if a given elements belong to the set.
447  */
448  bool exists(const Key& k) const;
449 
450  /**
451  * @brief Indicates whether the set is the empty set.
452  * @return Returns true if the set is empty.
453  */
454  bool empty() const noexcept;
455 
456  /**
457  * @brief Prints the content of the set.
458  * @return Returns the content of the set.
459  */
460  std::string toString() const;
461 
462  /// @}
463  // ============================================================================
464  /// @name Iterators
465  // ============================================================================
466  /// @{
467 
468  /**
469  * @brief The usual safe begin iterator to parse the set.
470  * @return Returns The usual safe begin iterator to parse the set.
471  */
472  iterator_safe beginSafe() const;
473 
474  /**
475  * @brief The usual safe begin iterator to parse the set.
476  * @return Returns the usual safe begin iterator to parse the set.
477  */
478  const_iterator_safe cbeginSafe() const;
479 
480  /**
481  * @brief The usual safe end iterator to parse the set.
482  * @return Returns the usual safe end iterator to parse the set.
483  */
484  const iterator_safe& endSafe() const noexcept;
485 
486  /**
487  * @brief The usual safe end iterator to parse the set.
488  * @return Returns the usual safe end iterator to parse the set.
489  */
490  const const_iterator_safe& cendSafe() const noexcept;
491 
492  /**
493  * @brief The usual unsafe begin iterator to parse the set.
494  * @return Returns the usual unsafe begin iterator to parse the set.
495  */
496  iterator begin() const;
497 
498  /**
499  * @brief The usual unsafe begin iterator to parse the set.
500  * @return Returns the usual unsafe begin iterator to parse the set.
501  */
502  const_iterator cbegin() const;
503 
504  /**
505  * @brief The usual unsafe end iterator to parse the set.
506  * @return Returns the usual unsafe end iterator to parse the set.
507  */
508  const iterator& end() const noexcept;
509 
510  /**
511  * @brief The usual unsafe end iterator to parse the set.
512  * @return Returns the usual unsafe end iterator to parse the set.
513  */
514  const const_iterator& cend() const noexcept;
515 
516  /**
517  * @brief Returns the end iterator for other classes' statics (read the
518  * detailed description of this method).
519  *
520  * To reduce the Sets memory consumption (which are heavily used in aGrUM)
521  * while allowing fast for(iter=begin(); iter!=end();++iter) loops, end
522  * iterators are created just once as a static member of a non-template
523  * Set. While this scheme is efficient and it works quite effectively when
524  * manipulating sets, it has a drawback: other classes with static members
525  * using the Set's end() iterator may fail to work due to the well known
526  * "static initialization order fiasco" (see Marshall Cline's C++ FAQ for
527  * more details about this C++ feature). OK, so what is the problem?
528  * Consider a class, say X, containing a Set that stores all its elements
529  * in a convenient way. To reduce memory consumption, X::end iterator is a
530  * static member that is initialized with a Set::end iterator. If the
531  * compiler decides to initialize X::end before initializing Set::end, then
532  * X::end will be in an incoherent state. Unfortunately, we cannot know for
533  * sure in which order static members will be initialized (the order is a
534  * compiler's decision). Hence, we shall enfore the fact that Set::end is
535  * initialized before X::end. Using method Set::end4Statics will ensure
536  * this fact: it uses the C++ "construct on first use" idiom (see the C++
537  * FAQ) that ensures that the order fiasco is avoided. More precisely,
538  * end4Statics uses a global variable that is the very end iterator used by
539  * all Sets. Now, this induces a small overhead. So, we also provide a
540  * Set::end() method that returns the Set::end iterator without this small
541  * overhead, but assuming that function end4Statics has already been called
542  * once (which is always the case) when a Set has been created.
543  *
544  * So, to summarize: when initializing static members, use end4Statics()
545  * rather than end(). In all the other cases, use simply the usual method
546  * end().
547  *
548  * @return Returns the end iterator for other classes' statics (read the
549  * detailed description of this method).
550  */
551  static const iterator& end4Statics();
552 
553  /**
554  * @brief Returns the end iterator for other classes' statics (read the
555  * detailed description of this method).
556  *
557  * To reduce the Sets memory consumption (which are heavily used in aGrUM)
558  * while allowing fast for(iter=begin(); iter!=end();++iter) loops, end
559  * iterators are created just once as a static member of a non-template
560  * Set. While this scheme is efficient and it works quite effectively when
561  * manipulating sets, it has a drawback: other classes with static members
562  * using the Set's end() iterator may fail to work due to the well known
563  * "static initialization order fiasco" (see Marshall Cline's C++ FAQ for
564  * more details about this C++ feature). OK, so what is the problem?
565  * Consider a class, say X, containing a Set that stores all its elements
566  * in a convenient way. To reduce memory consumption, X::end iterator is a
567  * static member that is initialized with a Set::end iterator. If the
568  * compiler decides to initialize X::end before initializing Set::end, then
569  * X::end will be in an incoherent state. Unfortunately, we cannot know for
570  * sure in which order static members will be initialized (the order is a
571  * compiler's decision). Hence, we shall enfore the fact that Set::end is
572  * initialized before X::end. Using method Set::end4Statics will ensure
573  * this fact: it uses the C++ "construct on first use" idiom (see the C++
574  * FAQ) that ensures that the order fiasco is avoided. More precisely,
575  * end4Statics uses a global variable that is the very end iterator used by
576  * all Sets. Now, this induces a small overhead. So, we also provide a
577  * Set::end() method that returns the Set::end iterator without this small
578  * overhead, but assuming that function end4Statics has already been called
579  * once (which is always the case) when a Set has been created.
580  *
581  * So, to summarize: when initializing static members, use
582  * constEnd4Statics() rather than cend(). In all the other cases, use
583  * simply the usual method cend().
584  *
585  * @return Returns the end iterator for other classes' statics (read the
586  * detailed description of this method).
587  */
588  static const const_iterator& constEnd4Statics();
589 
590  /**
591  * @brief Returns the end iterator for other classes' statics (read the
592  * detailed description of this method).
593  *
594  * To reduce the Sets memory consumption (which are heavily used in aGrUM)
595  * while allowing fast for(iter=begin(); iter!=end();++iter) loops, end
596  * iterators are created just once as a static member of a non-template
597  * Set. While this scheme is efficient and it works quite effectively when
598  * manipulating sets, it has a drawback: other classes with static members
599  * using the Set's end() iterator may fail to work due to the well known
600  * "static initialization order fiasco" (see Marshall Cline's C++ FAQ for
601  * more details about this C++ feature). OK, so what is the problem?
602  * Consider a class, say X, containing a Set that stores all its elements
603  * in a convenient way. To reduce memory consumption, X::end iterator is a
604  * static member that is initialized with a Set::end iterator. If the
605  * compiler decides to initialize X::end before initializing Set::end, then
606  * X::end will be in an incoherent state. Unfortunately, we cannot know for
607  * sure in which order static members will be initialized (the order is a
608  * compiler's decision). Hence, we shall enfore the fact that Set::end is
609  * initialized before X::end. Using method Set::end4Statics will ensure
610  * this fact: it uses the C++ "construct on first use" idiom (see the C++
611  * FAQ) that ensures that the order fiasco is avoided. More precisely,
612  * end4Statics uses a global variable that is the very end iterator used by
613  * all Sets. Now, this induces a small overhead. So, we also provide a
614  * Set::end() method that returns the Set::end iterator without this small
615  * overhead, but assuming that function end4Statics has already been called
616  * once (which is always the case) when a Set has been created.
617  *
618  * So, to summarize: when initializing static members, use
619  * endSafe4Statics() rather than endSafe (). In all the other cases, use
620  * simply the usual method endSafe ().
621  *
622  * @return Returns the end iterator for other classes' statics (read the
623  * detailed description of this method).
624  */
625  static const iterator_safe& endSafe4Statics();
626 
627  /**
628  * @brief Returns the end iterator for other classes' statics (read the
629  * detailed description of this method).
630  *
631  * To reduce the Sets memory consumption (which are heavily used in aGrUM)
632  * while allowing fast for(iter=begin(); iter!=end();++iter) loops, end
633  * iterators are created just once as a static member of a non-template
634  * Set. While this scheme is efficient and it works quite effectively when
635  * manipulating sets, it has a drawback: other classes with static members
636  * using the Set's end() iterator may fail to work due to the well known
637  * "static initialization order fiasco" (see Marshall Cline's C++ FAQ for
638  * more details about this C++ feature). OK, so what is the problem?
639  * Consider a class, say X, containing a Set that stores all its elements
640  * in a convenient way. To reduce memory consumption, X::end iterator is a
641  * static member that is initialized with a Set::end iterator. If the
642  * compiler decides to initialize X::end before initializing Set::end, then
643  * X::end will be in an incoherent state. Unfortunately, we cannot know for
644  * sure in which order static members will be initialized (the order is a
645  * compiler's decision). Hence, we shall enfore the fact that Set::end is
646  * initialized before X::end. Using method Set::end4Statics will ensure
647  * this fact: it uses the C++ "construct on first use" idiom (see the C++
648  * FAQ) that ensures that the order fiasco is avoided. More precisely,
649  * end4Statics uses a global variable that is the very end iterator used by
650  * all Sets. Now, this induces a small overhead. So, we also provide a
651  * Set::end() method that returns the Set::end iterator without this small
652  * overhead, but assuming that function end4Statics has already been called
653  * once (which is always the case) when a Set has been created.
654  *
655  * So, to summarize: when initializing static members, use
656  * constEndSafe4Statics() rather than cendSafe(). In all the other cases,
657  * use simply the usual method cendSafe ().
658  *
659  * @return Returns the end iterator for other classes' statics (read the
660  * detailed description of this method).
661  */
662  static const const_iterator_safe& constEndSafe4Statics();
663 
664  /// @}
665  // ============================================================================
666  /// @name Fine tuning
667  // ============================================================================
668  /// @{
669 
670  /**
671  * @brief Returns the capacity of the underlying hash table containing the
672  * set.
673  *
674  * The method runs in constant time.
675  *
676  * @return Returns the capacity of the underlying hash table containing the
677  * set.
678  */
679  Size capacity() const;
680 
681  /**
682  * @brief Changes the size of the underlying hash table containing the set.
683  *
684  * See gum::HashTable::resize(Size) method resize for more details.
685  *
686  * @param new_capacity The underlying hash table new size.
687  */
688  void resize(Size new_capacity);
689 
690  /**
691  * @brief Enables the user to change dynamically the resizing policy of the
692  * underlying hash table.
693  *
694  * When new_policy is false, the set will not try to change its memory
695  * size, hence resulting in potentially slower accesses.
696  *
697  * @param new_policy If true the set updates dynamically its memory
698  * consumption to guarantee that its elements are fast to retrieve.
699  */
700  void setResizePolicy(const bool new_policy);
701 
702  /**
703  * @brief Returns the current resizing policy of the underlying hash table.
704  * @return Returns the current resizing policy of the underlying hash
705  * table.
706  */
707  bool resizePolicy() const;
708 
709  /// @}
710  // ============================================================================
711  /// @name Mapper
712  // ============================================================================
713  /// @{
714 
715  /**
716  * @brief Creates a hashtable of NewKey from the set.
717  *
718  * @warning The order in the resulting hashtable may not be similar to that
719  * of the original set. Hence iterators on the former may not parse it in
720  * the same order as iterators on the latter.
721  *
722  * @param f A function that maps Key into a NewKey
723  * @param capacity The size of the resulting hashtable. When equal to 0, a
724  * default size is computed that is a good trade-off between space
725  * consumption and efficiency of new elements insertions.
726  */
727  template < typename NewKey,
728  typename NewAlloc = typename Alloc::template rebind< NewKey >::other >
729  HashTable< Key, NewKey, NewAlloc > hashMap(NewKey (*f)(const Key&), Size capacity = 0) const;
730 
731  /**
732  * @brief Creates a hash table of NewKey from the set.
733  *
734  * @warning The order in the resulting hash table may not be similar to
735  * that of the original set. Hence iterators on the former may not parse it
736  * in the same order as iterators on the latter.
737  *
738  * @param val The value taken by all the elements of the resulting
739  * hashtable.
740  * @param size The size of the resulting hash table. When equal to 0, a
741  * default size is computed that is a good trade-off between space
742  * consumption and efficiency of new elements insertions.
743  */
744  template < typename NewKey,
745  typename NewAlloc = typename Alloc::template rebind< NewKey >::other >
746  HashTable< Key, NewKey, NewAlloc > hashMap(const NewKey& val, Size size = 0) const;
747 
748  /**
749  * @brief A method to create a List of NewKey from the set.
750  *
751  * @warning The order of the NewKey elements in the resulting list is
752  * arbitrary.
753  *
754  * @param f A function that maps a Key into a NewKey
755  */
756  template < typename NewKey,
757  typename NewAlloc = typename Alloc::template rebind< NewKey >::other >
758  List< NewKey, NewAlloc > listMap(NewKey (*f)(const Key&)) const;
759 
760  /// @}
761 
762  private:
763  /// Friends to speed up access
764  /// @{
765  friend class SetIterator< Key >;
766  friend class SetIteratorSafe< Key >;
767  template < typename K, typename A >
768  friend class Set;
769  /// @}
770 
771  /// A set of X's is actually a hash table whose keys are the X's.
772  HashTable< Key, bool, Alloc > _inside_;
773 
774  /// Convert a hash table into a set of keys.
775  Set(const HashTable< Key, bool, Alloc >& h);
776  };
777 
778 
779  // ===========================================================================
780  // === SAFE SET ITERATORS ===
781  // ===========================================================================
782 
783  /**
784  * @class SetIteratorSafe
785  * @headerfile set.h <agrum/tools/core/set.h>
786  * @brief Safe iterators for the Set class
787  * @ingroup set_group
788  *
789  * Developers may consider using Set<x>::iterator_safe instead of
790  * SetIteratorSafe<x>.
791  *
792  * @par Usage example:
793  * @code
794  * // creation of a set with 10 elements
795  * Set<int> set;
796  * for (int i = 0; i< 10; ++i)
797  * set<<i;
798  *
799  * // parse the set
800  * for (const auto iter = table.beginSafe (); iter != table.endSafe (); ++iter) {
801  * // display the values
802  * cerr << *iter << endl;
803  * }
804  *
805  * // check whether two iterators point toward the same element
806  * Set<int>::iterator_safe iter1 = table1.beginSafe();
807  * Set<int>::iterator_safe iter2 = table1.endSafe();
808  * if (iter1 != iter)
809  * cerr << "iter1 and iter2 point toward different elements";
810  *
811  * @endcode
812  *
813  * @tparam Key The elements type.
814  */
815  template < typename Key >
816  class SetIteratorSafe {
817  public:
818  /// Types for STL compliance.
819  /// @{
820  using iterator_category = std::forward_iterator_tag;
821  using value_type = Key;
822  using reference = value_type&;
823  using const_reference = const value_type&;
824  using pointer = value_type*;
825  using const_pointer = const value_type*;
826  using difference_type = std::ptrdiff_t;
827  /// @}
828 
829  /**
830  * @brief An enumeration to position the iterator at the beginning or the
831  * end of the set.
832  */
833  enum Position
834  {
835  BEGIN,
836  END
837  };
838 
839  // ============================================================================
840  /// @name Constructors / Destructors
841  // ============================================================================
842  /// @{
843 
844  /**
845  * @brief Default constructor: the iterator points toward nothing.
846  */
847  SetIteratorSafe();
848 
849  /**
850  * @brief Creates an iterator for a given set.
851  *
852  * By default, the iterator points to the beginning of the set, but, using
853  * optional argument pos, you can make it point to end().
854  *
855  * @tparam Alloc The gum::Set allocator.
856  * @param from The gum::Set to iterate over.
857  * @param pos Where to start iterating.
858  */
859  template < typename Alloc >
860  SetIteratorSafe(const Set< Key, Alloc >& from, Position pos = BEGIN);
861 
862  /**
863  * @brief Copy constructor.
864  * @param from The iterator to copy.
865  */
866  SetIteratorSafe(const SetIteratorSafe< Key >& from);
867 
868  /**
869  * @brief Copy constructor.
870  * @param from The iterator to copy.
871  */
872  explicit SetIteratorSafe(const SetIterator< Key >& from);
873 
874  /**
875  * @brief Move constructor.
876  * @param from The iterator to move.
877  */
878  SetIteratorSafe(SetIteratorSafe< Key >&& from);
879 
880  /**
881  * Class destructor.
882  */
883  ~SetIteratorSafe() noexcept;
884 
885  /// @}
886  // ============================================================================
887  /// @name Operators
888  // ============================================================================
889  /// @{
890 
891  /**
892  * @brief Assignment operator.
893  * @param from The iterator to copy.
894  * @return Returns this iterator.
895  */
896  SetIteratorSafe< Key >& operator=(const SetIteratorSafe< Key >& from);
897 
898  /**
899  * @brief Assignment operator.
900  * @param from The iterator to copy.
901  * @return Returns this iterator.
902  */
903  SetIteratorSafe< Key >& operator=(const SetIterator< Key >& from);
904 
905  /**
906  * @brief Assignment operator.
907  * @param from The iterator to move.
908  * @return Returns this iterator.
909  */
910  SetIteratorSafe< Key >& operator=(SetIteratorSafe< Key >&& from) noexcept;
911 
912  /**
913  * @brief Increments the iterator.
914  * @return This iterator.
915  */
916  SetIteratorSafe< Key >& operator++() noexcept;
917 
918  /**
919  * @brief Makes the iterator point to i elements further in the set.
920  * @param i The number of increments.
921  * @return Returns this iterator.
922  */
923  SetIteratorSafe< Key >& operator+=(Size i) noexcept;
924 
925  /**
926  * @brief Returns a new iterator.
927  * @param i The number of increments.
928  * @return Returns a new iterator.
929  */
930  SetIteratorSafe< Key > operator+(Size i) const;
931 
932  /**
933  * @brief Indicates whether two iterators point to different elements or
934  * sets.
935  * @param from The iterator to test for inequality.
936  * @return Returns true if both iterator are not equal.
937  */
938  bool operator!=(const SetIteratorSafe< Key >& from) const noexcept;
939 
940  /**
941  * @brief Indicates whether two iterators point toward the same element of
942  * a same set.
943  * @param from The iterator to test for equality.
944  * @return Returns true if both iterator are equal.
945  */
946  bool operator==(const SetIteratorSafe< Key >& from) const noexcept;
947 
948  /**
949  * @brief Returns the element pointed to by the iterator.
950  *
951  * @throws UndefinedIteratorValue Raised if the iterator does not point
952  * to an element of the set (for instance if the set or the element
953  * previously pointed to by the iterator have been deleted).
954  *
955  * @return Returns the element pointed to by the iterator.
956  */
957  const Key& operator*() const;
958 
959  /**
960  * @brief Returns a pointer to the element pointed to by the iterator.
961  *
962  * @throws UndefinedIteratorValue Raised if the iterator does not point
963  * to an element of the set (for instance if the set or the element
964  * previously pointed to by the iterator have been deleted).
965  *
966  * @return Returns a pointer to the element pointed to by the iterator.
967  */
968  const Key* operator->() const;
969 
970  /// @}
971  // ============================================================================
972  /// @name Accessors / Modifiers
973  // ============================================================================
974  /// @{
975 
976  /**
977  * @brief makes the iterator point toward nothing (in particular, it is not
978  * related anymore to its current set).
979  */
980  void clear() noexcept;
981 
982  /// @}
983 
984  private:
985  /// For efficiency, Set should be able to modify the hash table iterator.
986  template < typename K, typename A >
987  friend class Set;
988 
989  /// The underlying iterator for the set's hash table containing the data.
990  HashTableConstIteratorSafe< Key, bool > _ht_iter_;
991  };
992 
993  // ===========================================================================
994  // === UNSAFE SET ITERATORS ===
995  // ===========================================================================
996 
997  /**
998  * @class SetIterator
999  * @headerfile set.h <agrum/tools/core/set.h>
1000  * @brief Unsafe iterators for the Set class.
1001  * @ingroup set_group
1002  *
1003  * Developers may consider using Set<x>::iterator instead of SetIterator<x>.
1004  *
1005  * @warning Use SetIterator only if you are sure that the iterator will never
1006  * point to a deleted element. Pointing to a deleted element will most
1007  * probably result in a segfault. If you are unsure, prefer using the safe
1008  * iterators Set<>::iterator_safe.
1009  *
1010  * @par Usage example:
1011  * @code
1012  * // creation of a set with 10 elements
1013  * Set<int> set;
1014  * for (int i = 0; i< 10; ++i)
1015  * set<<i;
1016  *
1017  * // parse the set
1018  * for (const auto iter = table.begin (); iter != table.end (); *++iter) {
1019  * // display the values
1020  * cerr << *iter << endl;
1021  * }
1022  *
1023  * // check whether two iterators point toward the same element
1024  * Set<int>::iterator iter1 = table1.begin();
1025  * Set<int>::iterator iter2 = table1.end();
1026  * if (iter1 != iter)
1027  * cerr << "iter1 and iter2 point toward different elements";
1028  *
1029  * @endcode
1030  *
1031  * @tparam Key The elements type.
1032  */
1033  template < typename Key >
1034  class SetIterator {
1035  public:
1036  /// Types for STL compliance.
1037  /// @{
1038  using iterator_category = std::forward_iterator_tag;
1039  using value_type = Key;
1040  using reference = value_type&;
1041  using const_reference = const value_type&;
1042  using pointer = value_type*;
1043  using const_pointer = const value_type*;
1044  using difference_type = std::ptrdiff_t;
1045  /// @}
1046 
1047  /**
1048  * @brief An enumeration to position the iterator at the beginning or the
1049  * end of the set.
1050  */
1051  enum Position
1052  {
1053  BEGIN,
1054  END
1055  };
1056 
1057  // ============================================================================
1058  /// @name Constructors / Destructors
1059  // ============================================================================
1060  /// @{
1061 
1062  /**
1063  * @brief Default constructor: the iterator points toward nothing.
1064  */
1065  SetIterator() noexcept;
1066 
1067  /**
1068  * @brief Creates an iterator for a given set.
1069  *
1070  * By default, the iterator points to the beginning of the set, but, using
1071  * optional argument pos, you can make it point to end().
1072  *
1073  * @tparam Alloc The gum::Set allocator.
1074  * @param from The gum::Set to iterator over.
1075  * @param pos Where to start iterating.
1076  */
1077  template < typename Alloc >
1078  SetIterator(const Set< Key, Alloc >& from, Position pos = BEGIN);
1079 
1080  /**
1081  * @brief Copy constructor.
1082  * @param from The iterator to copy.
1083  */
1084  SetIterator(const SetIterator< Key >& from) noexcept;
1085 
1086  /**
1087  * @brief Move constructor.
1088  * @param from The iterator to move.
1089  */
1090  SetIterator(SetIterator< Key >&& from) noexcept;
1091 
1092  /**
1093  * @brief Class destructor.
1094  */
1095  ~SetIterator() noexcept;
1096 
1097  /// @}
1098  // ============================================================================
1099  /// @name Operators
1100  // ============================================================================
1101  /// @{
1102 
1103  /**
1104  * @brief Assignment operator.
1105  * @param from The iterator to copy.
1106  * @return Returns this iterator.
1107  */
1108  SetIterator< Key >& operator=(const SetIterator< Key >& from) noexcept;
1109 
1110  /**
1111  * @brief Assignment operator.
1112  * @param from The iterator to copy.
1113  * @return Returns this iterator.
1114  */
1115  SetIterator< Key >& operator=(SetIterator< Key >&& from) noexcept;
1116 
1117  /**
1118  * @brief Increments the iterator.
1119  * @return This iterator.
1120  */
1121  SetIterator< Key >& operator++() noexcept;
1122 
1123  /**
1124  * @brief Makes the iterator point to i elements further in the set.
1125  * @param i The number of increments.
1126  * @return Returns this iterator.
1127  */
1128  SetIterator< Key >& operator+=(Size i) noexcept;
1129 
1130  /**
1131  * @brief Returns a new iterator.
1132  * @param i The number of increments.
1133  * @return Returns a new iterator.
1134  */
1135  SetIterator< Key > operator+(Size i) const noexcept;
1136 
1137  /**
1138  * @brief Indicates whether two iterators point to different elements or
1139  * sets.
1140  * @param from The iterator to test for inequality.
1141  * @return Returns true if both iterator are not equal.
1142  */
1143  bool operator!=(const SetIterator< Key >& from) const noexcept;
1144 
1145  /**
1146  * @brief Indicates whether two iterators point toward the same element of
1147  * a same set.
1148  * @param from The iterator to test for equality.
1149  * @return Returns true if both iterator are equal.
1150  */
1151  bool operator==(const SetIterator< Key >& from) const noexcept;
1152 
1153  /**
1154  * @brief Returns the element pointed to by the iterator.
1155  *
1156  * @throws UndefinedIteratorValue Raised if the iterator does not point
1157  * to an element of the set (for instance if the set or the element
1158  * previously pointed to by the iterator have been deleted).
1159  *
1160  * @return Returns the element pointed to by the iterator.
1161  */
1162  const Key& operator*() const;
1163 
1164  /**
1165  * @brief Returns a pointer to the element pointed to by the iterator.
1166  *
1167  * @throws UndefinedIteratorValue Raised if the iterator does not point
1168  * to an element of the set (for instance if the set or the element
1169  * previously pointed to by the iterator have been deleted).
1170  *
1171  * @return Returns a pointer to the element pointed to by the iterator.
1172  */
1173  const Key* operator->() const;
1174 
1175  /// @}
1176  // ============================================================================
1177  /// @name Accessors / Modifiers
1178  // ============================================================================
1179  /// @{
1180 
1181  /**
1182  * @brief makes the iterator point toward nothing (in particular, it is not
1183  * related anymore to its current set).
1184  */
1185  void clear() noexcept;
1186 
1187  /// @}
1188 
1189  private:
1190  /// For efficiency, Set should be able to modify the hash table iterator.
1191  template < typename K, typename A >
1192  friend class Set;
1193  friend class SetIteratorSafe< Key >;
1194 
1195  /// The underlying iterator for the set's hash table containing the data.
1196  HashTableConstIterator< Key, bool > _ht_iter_;
1197  };
1198 
1199 
1200  /// @brief A << operator for HashTableList.
1201  template < typename Key, typename Alloc >
1202  std::ostream& operator<<(std::ostream&, const Set< Key, Alloc >&);
1203 
1204 
1205  /// the hash function for sets of int
1206  template < typename T, typename Alloc >
1207  class HashFunc< Set< T, Alloc > >: public HashFuncBase< Set< T, Alloc > > {
1208  public:
1209  /**
1210  * @brief Returns the value of a key as a Size.
1211  * @param key The value to return as a Size.
1212  * @return Returns the value of a key as a Size.
1213  */
1214  static Size castToSize(const Set< T, Alloc >& key);
1215 
1216  /// computes the hashed value of a key
1217  virtual Size operator()(const Set< T, Alloc >& key) const override final;
1218  };
1219 
1220 } /* namespace gum */
1221 
1222 
1223 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1224 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1225 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1226 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1227 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1228 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1229 extern template class gum::Set< int >;
1230 # endif
1231 # endif
1232 # endif
1233 # endif
1234 # endif
1235 #endif
1236 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1237 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1238 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1239 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1240 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1241 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1242 extern template class gum::Set< long >;
1243 # endif
1244 # endif
1245 # endif
1246 # endif
1247 # endif
1248 #endif
1249 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1250 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1251 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1252 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1253 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1254 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1255 extern template class gum::Set< unsigned int >;
1256 # endif
1257 # endif
1258 # endif
1259 # endif
1260 # endif
1261 #endif
1262 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1263 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1264 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1265 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1266 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1267 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1268 extern template class gum::Set< unsigned long >;
1269 # endif
1270 # endif
1271 # endif
1272 # endif
1273 # endif
1274 #endif
1275 
1276 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1277 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1278 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1279 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1280 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1281 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1282 extern template class gum::Set< double >;
1283 # endif
1284 # endif
1285 # endif
1286 # endif
1287 # endif
1288 #endif
1289 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1290 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1291 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1292 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1293 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1294 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
1295 extern template class gum::Set< std::string >;
1296 # endif
1297 # endif
1298 # endif
1299 # endif
1300 # endif
1301 #endif
1302 
1303 
1304 // always include the implementation of the templates
1305 #include <agrum/tools/core/set_tpl.h>
1306 
1307 #endif // GUM_SET_H