aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
hashTable.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 Class hash tables iterators
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #ifndef GUM_HASHTABLE_H
30 #define GUM_HASHTABLE_H
31 
32 #include <limits>
33 
34 #include <cstddef>
35 #include <initializer_list>
36 #include <iostream>
37 #include <string>
38 #include <utility>
39 #include <vector>
40 
41 #include <agrum/agrum.h>
42 #include <agrum/tools/core/hashFunc.h>
43 
44 namespace gum {
45 
46 #ifndef DOXYGEN_SHOULD_SKIP_THIS
47 
48  // the templates used by this file
49  template < typename Key, typename Val, typename Alloc >
50  class HashTable;
51  template < typename Key, typename Val, typename Alloc >
52  class HashTableList;
53  template < typename Key, typename Val >
54  class HashTableIterator;
55  template < typename Key, typename Val >
56  class HashTableConstIterator;
57  template < typename Key, typename Val >
58  class HashTableIteratorSafe;
59  template < typename Key, typename Val >
60  class HashTableConstIteratorSafe;
61  template < typename T1, typename T2, typename Alloc >
62  class Bijection;
63 
64 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
65 
66  /**
67  * @class HashTableConst
68  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
69  * @brief Parameters specifying the default behavior of the hashtables.
70  * @ingroup hashtable_group
71  */
72  struct HashTableConst {
73  /**
74  * The default number of slots in hashtables. By default, hashtables can
75  * store up to thrice the number of slots elements before their size is
76  * increased To each slot corresponds a chained list of elements with the
77  * same hashed key.
78  */
79  static constexpr Size default_size{Size(4)};
80 
81  /**
82  * The average number of elements admissible by slots. Once this number is
83  * reached, the size of the hashtable is automatically doubled if we are in
84  * automatic resize mode.
85  */
86  static constexpr Size default_mean_val_by_slot{Size(3)};
87 
88  /**
89  * A Boolean indicating whether inserting too many values into the
90  * hashtable makes it resize itself automatically. true = automatic, false
91  * = manual.
92  */
93  static constexpr bool default_resize_policy{true};
94 
95  /**
96  * A Boolean indicating the default behavior when trying to insert more
97  * than once elements with identical keys. true = do not insert the
98  * elements but the first one and throw an exception after the first
99  * insertion; false = insert the elements without complaining.
100  */
101  static constexpr bool default_uniqueness_policy{true};
102  };
103 
104  // Doxygen raises warning with the following comment bloc
105  // @brief Prints the content of a gum::HashTableList in the stream.
106  // @ingroup hashtable_group
107  // @param s The s used to print the gum::HashTableList.
108  // @param list The gum::HashTableList to print.
109  // @return Returns the std::ostream s.
110  // @tparam Key The type of keys in the gum::HashTableList.
111  // @tparam Val The type of values in the gum::HashTableList.
112  // @tparam Alloc The gum::HashTableList allocator.
113 
114  /**
115  * @brief Prints the content of a gum::HashTableList in the stream.
116  * @ingroup hashtable_group
117  */
118  template < typename Key, typename Val, typename Alloc >
119  std::ostream& operator<<(std::ostream& s, const HashTableList< Key, Val, Alloc >& list);
120 
121  // Doxygen raises warning with the following comment bloc
122  // @brief Prints the content of a gum::HashTableList with pointers key in the
123  // stream.
124  // @ingroup hashtable_group
125  // @param s The s used to print the gum::HashTableList.
126  // @param list The gum::HashTableList to print.
127  // @return Returns the std::ostream s.
128  // @tparam Key The type of keys in the gum::HashTableList.
129  // @tparam Val The type of values in the gum::HashTableList.
130  // @tparam Alloc The gum::HashTableList allocator.
131  //
132 
133  /**
134  * @brief Prints the content of a gum::HashTableList with pointers key in
135  * the stream.
136  * @ingroup hashtable_group
137  */
138  template < typename Key, typename Val, typename Alloc >
139  std::ostream& operator<<(std::ostream& s, const HashTableList< Key*, Val, Alloc >& list);
140 
141  // Doxygen raises warning with the following comment bloc
142  // @brief Prints the content of a gum::HashTable in the stream.
143  // @ingroup hashtable_group
144  // @param s The stream used to print the gum::HashTable.
145  // @param table The gum::HashTable to print.
146  // @return Returns the std::ostream s.
147  // @tparam Key The type of keys in the gum::HashTable.
148  // @tparam Val The type of values in the gum::HashTable.
149  // @tparam Alloc The gum::HashTable allocator.
150 
151  /**
152  * @brief Prints the content of a gum::HashTable in the stream.
153  * @ingroup hashtable_group
154  */
155  template < typename Key, typename Val, typename Alloc >
156  std::ostream& operator<<(std::ostream& s, const HashTable< Key, Val, Alloc >& table);
157 
158  // Doxygen raises warning with the following comment bloc
159  // @brief Prints the content of a gum::HashTable with pointers key in the
160  // stream.
161  // @ingroup hashtable_group
162  // @param s The stream used to print the gum::HashTable.
163  // @param table The gum::HashTable to print.
164  // @return Returns the std::ostream s.
165  // @tparam Key The type of keys in the gum::HashTable.
166  // @tparam Val The type of values in the gum::HashTable.
167  // @tparam Alloc The gum::HashTable allocator.
168 
169  /**
170  * @brief Prints the content of a gum::HashTable with pointers key in the
171  * stream.
172  * @ingroup hashtable_group
173  */
174  template < typename Key, typename Val, typename Alloc >
175  std::ostream& operator<<(std::ostream& s, const HashTable< Key*, Val, Alloc >& table);
176 
177  // ===========================================================================
178  // === LISTS SPECIFIC FOR SAVING ELEMENTS IN HASHTABLES ===
179  // ===========================================================================
180 
181  /**
182  * @class HashTableBucket
183  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
184  * @brief A recipient for a pair of key value in a gum::HashTableList.
185  * @ingroup hashtable_group
186  *
187  * In aGrUM, hashtables are vectors of chained lists. Each list corresponds
188  * to the pairs (key,val) the keys of which have the same hashed value. Each
189  * box of the list is called a bucket. Lists are doubly linked so as to
190  * enable efficient begin/end iterators and efficient insert/erase
191  * operations.
192  *
193  * @tparam Key The type for keys in a gum::HashTable.
194  * @tparam Val The type for values in a gum::HashTable.
195  */
196  template < typename Key, typename Val >
197  struct HashTableBucket {
198  /// The pair stored in this bucket.
199  std::pair< const Key, Val > pair;
200 
201  /// A pointer toward the previous bucket in the gum::HashTableList.
202  HashTableBucket< Key, Val >* prev{nullptr};
203 
204  /// A pointer toward the next bucket in the gum::HashTableList.
205  HashTableBucket< Key, Val >* next{nullptr};
206 
207  /**
208  * @brief A dummy type for the emplace constructor.
209  * This type is used to prevent the Bucket emplace (int,...) to compile.
210  */
211  enum class Emplace
212  { EMPLACE };
213 
214  /**
215  * Class constructor.
216  */
217  HashTableBucket() {}
218 
219  /**
220  * Copy constructor.
221  * @param from The gum::HashTableBucket to copy.
222  */
223  HashTableBucket(const HashTableBucket< Key, Val >& from) : pair{from.pair} {}
224 
225  /**
226  * Constructor.
227  * @param k The key part of the pair.
228  * @param v The value part of the pair.
229  */
230  HashTableBucket(const Key& k, const Val& v) : pair{k, v} {}
231 
232  /**
233  * Constructor.
234  * @param k The key part of the pair.
235  * @param v The value part of the pair.
236  */
237  HashTableBucket(Key&& k, Val&& v) : pair{std::move(k), std::move(v)} {}
238 
239  /**
240  * Constructor.
241  * @param p The pair to store.
242  */
243  HashTableBucket(const std::pair< const Key, Val >& p) : pair(p) {}
244 
245  /**
246  * Constructor.
247  * @param p The pair to store.
248  */
249  HashTableBucket(std::pair< const Key, Val >&& p) : pair(std::move(p)) {}
250 
251  /**
252  * The emplace constructor.
253  * @param e The emplace.
254  * @param args A construction list.
255  * @tparam args The types in the construction list.
256  */
257  template < typename... Args >
258  HashTableBucket(Emplace e, Args&&... args) :
259  // emplace (universal) constructor
260  pair(std::forward< Args >(args)...) {}
261 
262  /**
263  * Class destructor.
264  */
265  ~HashTableBucket() {}
266 
267  /**
268  * @brief Returns the pair stored in this bucket.
269  * @return Returns the pair stored in this bucket.
270  */
271  std::pair< const Key, Val >& elt() { return pair; }
272 
273  /**
274  * @brief Returns the key part of the pair.
275  * @return Returns the key part of the pair.
276  */
277  Key& key() { return const_cast< Key& >(pair.first); }
278 
279  /**
280  * @brief Returns the value part of the pair.
281  * @return Returns value key part of the pair.
282  */
283  Val& val() { return pair.second; }
284  };
285 
286  // ===========================================================================
287  // === DOUBLY CHAINED LISTS FOR STORING ELEMENTS IN HASH TABLES ===
288  // ===========================================================================
289 
290  /**
291  * @class HashTableList
292  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
293  * @brief A chained list used by gum::HashTable.
294  * @ingroup hashtable_group
295  *
296  * @tparam Key The type for keys in a gum::HashTable.
297  * @tparam Val The type for values in a gum::HashTable.
298  * @tparam Alloc The gum::HashTable allocator.
299  */
300  template < typename Key, typename Val, typename Alloc >
301  class HashTableList {
302  public:
303  /// types for STL compliance
304  /// @{
305  using key_type = Key;
306  using mapped_type = Val;
307  using value_type = std::pair< const Key, Val >;
308  using reference = value_type&;
309  using const_reference = const value_type&;
310  using pointer = value_type*;
311  using const_pointer = const value_type*;
312  using size_type = Size;
313  using allocator_type = Alloc;
314  using Bucket = HashTableBucket< Key, Val >;
315  /// @}
316 
317  /// The Bucket allocator.
318  using BucketAllocator = typename Alloc::template rebind< Bucket >::other;
319 
320  // ============================================================================
321  /// @name Constructors / Destructors
322  // ============================================================================
323  /// @{
324 
325  /**
326  * @brief Basic constructor that creates an empty list.
327  *
328  * This is what is used basically by gum::HashTable.
329  *
330  * @warning If the allocator is not passed in argument, do not forget to
331  * use method setAllocator after the creation.
332  * @param allocator The gum::HashTableBucket allocator.
333  */
334  HashTableList(BucketAllocator* allocator = nullptr) noexcept;
335 
336  /**
337  * @brief Copy constructor.
338  *
339  * The new list and that which is copied do not share elements: the new
340  * list contains new instances of the keys and values stored in the copied
341  * list. Of course, if these values are pointers, the new values point
342  * toward the same elements.
343  *
344  * @warning Both from and this will share the same allocator.
345  * @param from The gum::HashTableList to copy.
346  */
347  HashTableList(const HashTableList< Key, Val, Alloc >& from);
348 
349  /**
350  * @brief Move constructor.
351  * @param from The gum::HashTableList to move.
352  */
353  HashTableList(HashTableList< Key, Val, Alloc >&& from) noexcept;
354 
355  /**
356  * @brief Class destructor.
357  */
358  ~HashTableList();
359 
360  /// @}
361  // ============================================================================
362  /// @name Operators
363  // ============================================================================
364  /// @{
365 
366  /**
367  * @brief Assignment operator.
368  *
369  * The new list and that which is copied do not share elements: the new
370  * list contains new instances of the keys and values stored in the copied
371  * list. Of course, if these values are pointers, the new values point
372  * toward the same elements.
373  *
374  * If some allocation problem occurs or if copying the Val elements cannot
375  * be performed properly, exceptions may be raised. In this case, the
376  * function guarantees that no memory leak occurs and that the list is kept
377  * in a coherent state (that of an empty list).
378  *
379  * @warning operator= does not change the current allocator of *this
380  * @param from The gum::HashTableList to copy.
381  * @return Returns this gum::HashTableList.
382  */
383  HashTableList< Key, Val, Alloc >& operator=(const HashTableList< Key, Val, Alloc >& from);
384 
385  /**
386  * @brief Generalized assignment operator.
387  *
388  * The new list and that which is copied do not share elements: the new
389  * list contains new instances of the keys and values stored in the copied
390  * list. Of course, if these values are pointers, the new values point
391  * toward the same elements.
392  *
393  * If some allocation problem occurs or if copying the Val elements cannot
394  * be performed properly, exceptions may be raised. In this case, the
395  * function guarantees that no memory leak occurs and that the list is kept
396  * in a coherent state (that of an empty list).
397  *
398  * @warning operator= does not change the current allocator of *this
399  * @param from The gum::HashTableList to copy.
400  * @return Returns this gum::HashTableList.
401  */
402  template < typename OtherAlloc >
403  HashTableList< Key, Val, Alloc >& operator=(const HashTableList< Key, Val, OtherAlloc >& from);
404 
405  /**
406  * @brief Move operator.
407  * @warning operator= does not change the current allocator of *this
408  * @param from The gum::HashTableList to copy.
409  * @return Returns this gum::HashTableList.
410  */
411  HashTableList< Key, Val, Alloc >& operator=(HashTableList< Key, Val, Alloc >&& from) noexcept;
412 
413  /// @}
414  // ============================================================================
415  /// @name Accessors / Modifiers
416  // ============================================================================
417  /// @{
418 
419  /**
420  * @brief Function at returns the ith element in the current chained list.
421  *
422  * The first element has index 0.
423  * @param i The index to look up.
424  * @return Returns the value at index i.
425  * @throw NotFound Raised if the list has fewer than i elements.
426  */
427  value_type& at(Size i);
428 
429  /**
430  * @brief Function at returns the ith element in the current chained list.
431  *
432  * The first element has index 0.
433  * @param i The index to look up.
434  * @return Returns the value at index i.
435  * @throw NotFound Raised if the list has fewer than i elements.
436  */
437  const value_type& at(Size i) const;
438 
439  /**
440  * @brief Returns the value corresponding to a given key.
441  * @param key The key for which a value is returned.
442  * @return Returns the value corresponding to a given key.
443  * @throw NotFound is raised if the element cannot be found
444  */
445  mapped_type& operator[](const key_type& key);
446 
447  /**
448  * @brief Returns the value corresponding to a given key.
449  * @param key The key for which a value is returned.
450  * @return Returns the value corresponding to a given key.
451  * @throw NotFound is raised if the element cannot be found
452  */
453  const mapped_type& operator[](const key_type& key) const;
454 
455  /**
456  * @brief Returns true if a value with the given key exists.
457  *
458  * Checks whether there exists an element with a given key in the list.
459  * @param key The key to test for existence.
460  * @return Returns true if a value with the given key exists.
461  */
462  bool exists(const key_type& key) const;
463 
464  /**
465  * @brief Inserts a new element in the chained list.
466  *
467  * The element is inserted at the beginning of the list.
468  * @param new_elt The element to add in the gum::HashTableList.
469  */
470  void insert(Bucket* new_elt) noexcept;
471 
472  /**
473  * @brief Removes an element from this chained list.
474  * @param ptr The element to remove.
475  */
476  void erase(Bucket* ptr);
477 
478  /**
479  * @brief Removes all the elements of this chained list.
480  */
481  void clear();
482 
483  /**
484  * @brief Returns true if this chained list is empty.
485  * @return Returns true if this chained list is empty.
486  */
487  bool empty() const noexcept;
488 
489  /**
490  * @brief A method to get the bucket corresponding to a given key.
491  *
492  * This enables efficient removals of buckets.
493  * @param key The key of the bucket to return.
494  * @return Returns the buckket matching key.
495  */
496  Bucket* bucket(const Key& key) const;
497 
498  /**
499  * @brief Sets a new allocator.
500  * @param alloc The new allocator.
501  */
502  void setAllocator(BucketAllocator& alloc);
503 
504  /// @}
505 
506  private:
507  /// Friend for faster access.
508  /// @{
509  template < typename K, typename V, typename A >
510  friend class HashTableList;
511  friend class HashTable< Key, Val, Alloc >;
512  friend class HashTableIterator< Key, Val >;
513  friend class HashTableConstIterator< Key, Val >;
514  friend class HashTableIteratorSafe< Key, Val >;
515  friend class HashTableConstIteratorSafe< Key, Val >;
516  friend std::ostream& operator<<<>(std::ostream&, const HashTableList< Key, Val, Alloc >&);
517  friend std::ostream& operator<<<>(std::ostream&, const HashTableList< Key*, Val, Alloc >&);
518  friend std::ostream& operator<<<>(std::ostream&, const HashTable< Key, Val, Alloc >&);
519  friend std::ostream& operator<<<>(std::ostream&, const HashTable< Key*, Val, Alloc >&);
520  /// @}
521 
522  /// A pointer on the first element of the chained list.
523  HashTableBucket< Key, Val >* _deb_list_{nullptr};
524 
525  /// A pointer on the last element of the chained list.
526  HashTableBucket< Key, Val >* _end_list_{nullptr};
527 
528  /// The number of elements in the chained list.
529  Size _nb_elements_{Size(0)};
530 
531  /// The allocator of the containing hashTable.
532  mutable BucketAllocator* _alloc_bucket_;
533 
534  /**
535  * @brief A function used to perform copies of HashTableLists.
536  *
537  * This code is shared by the copy constructor and the copy operator. If it
538  * cannot perform the necessary allocations, no memory leak occurs and the
539  * list is set to the empty list.
540  *
541  * @param from The gum::HashTableList to copy.
542  * @tparam OtherAlloc The other gum::HashTableList allocator.
543  */
544  template < typename OtherAlloc >
545  void _copy_(const HashTableList< Key, Val, OtherAlloc >& from);
546  };
547 
548  // ===========================================================================
549  // === GENERIC HASH TABLES ===
550  // ===========================================================================
551  /**
552  * @class HashTable
553  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
554  * @brief The class for generic Hash Tables.
555  * @ingroup basicstruct_group
556  * @ingroup hashtable_group
557  *
558  * In aGrUM, a hashtable is a vector of chained lists (collision problems are
559  * fixed by chaining). Each slot of the vector contains a list of elements
560  * sharing the same hashed value. To be computationally efficient, the hash
561  * table should not contain too many elements as compared to its number of
562  * slots. Therefore, it is sometimes useful to resize the chained lists
563  * vector. aGrUM's hash tables are designed to automatically double their
564  * size when there is in average more than 3 elements per slot. However, when
565  * memory consumption is a concern, this feature can be turned off either by
566  * passing false as an optional resize_pol argument to the constructor of the
567  * hash table or by using method setResizePolicy when the instance of the
568  * class has already been constructed. Similarly, the default number of
569  * slots of the hash table may be parameterized as an optional argument of
570  * the constructor (size_param). Beware: when inserting elements of a given
571  * class into a hash table, unless the element is an r-value, only a copy of
572  * this element is stored into the table (this is compulsory if the hashtable
573  * is to be generic and can be used to store both complex classes and
574  * built-in types like integers). HashTable have different kinds of
575  * iterators: HashTableIteratorSafe and HashTableConstIteratorSafe (a.k.a.
576  * HashTable<>::iterator_safe and HashTable<>::const_iterator_safe) allow
577  * safe parsing of the hash tables. By safe, we mean that whenever the
578  * element pointed to by such an iterator is removed from the hashtable,
579  * accessing it through the iterator (*iter) does not result in a
580  * segmentation fault but rather in an exception being thrown. This safety is
581  * ensured at a very low cost (actually, our experiments show that our
582  * HashTables and HashTable's safe iterators significantly outperform the
583  * standard library unordered_maps). Of course, if there is no possibility
584  * for an iterator to point to a deleted element, the user can use "unsafe"
585  * iterators HashTableIterator and HashTableConstIterator (a.k.a.
586  * HashTable<>::iterator and HashTable<>::const_iterator). These iterators
587  * are slightly faster than their safe counterparts. However, as in the
588  * standard library, accessing through them a deleted element usually results
589  * in a mess (most probably a segfault).
590  *
591  * @warning HashTables @b guarantee that any element stored within them will
592  * have the @b same @b location in memory until it is removed from the
593  * hashtable (and this holds whatever operation is performed on the hashtable
594  * like new insertions, deletions, resizing, etc.).
595  *
596  * @par Usage example:
597  * @code
598  * // creation of an empty hash table
599  * HashTable<int,string> table1;
600  *
601  * // insert two elements into the hash table
602  * table1.insert (10,"xxx");
603  * table1.insert (20,"yyy");
604  * table1.emplace (30,"zzz");
605  *
606  * // creation of a nonempty hashtable using initializer lists
607  * HashTable<int,bool> table { std::make_pair(3,true), std::make_pair(2,false)
608  * };
609  *
610  * // display the content of the hash table
611  * cerr << table1;
612  *
613  * // get the number of elements stored into the hash table
614  * cerr << "number of elements in table1 = " << table1.size () << endl;
615  *
616  * // create two copies of the hash table
617  * HashTable<int,string> table2, table3 = table1;
618  * table2 = table3;
619  *
620  * // get the element whose key is 10
621  * cerr << table1[10] << " = xxx" << endl;
622  *
623  * // check whether there exists an element with key 20
624  * if (table1.exists (20)) cerr << "element found" << endl;
625  *
626  * // transform the hashtable of string into a hashtable of int assuming f is
627  * // defined as: int f (const string& str) { return str.size (); }
628  * HashTable<int,int> table = table1.map (f);
629  *
630  * // remove two elements from table1 and table2
631  * table1.erase (10); // key = 10
632  * table1.eraseByVal ("yyy"); // val = "yyy"
633  * table2.clear ();
634  *
635  * // check whether the hash table is empty
636  * if (!table1.empty ()) cerr << "table not empty" << endl;
637  *
638  * // check whether hashtables contain the same elements
639  * if ((table1 == table2) && (table1 != table3))
640  * cerr << "check for equality/inequality" << endl;
641  *
642  * // parse the content of a hashtable using an unsafe iterator
643  * for (HashTable<int,string>::const_iterator iter = table1.cbegin();
644  * iter != table1.cend(); ++iter)
645  * cerr << *iter;
646  * HashTable<int,string>::iterator iter = table1.begin();
647  * iter += 2;
648  * cerr << iter.key () << " " << iter.val ();
649  *
650  * // use an iterator to point the element we wish to erase
651  * HashTable<int,string>::iterator_safe iterS = table1.beginSafe ();
652  * table1.erase ( table1.beginSafe () + 4 );
653  * table1.erase ( iterS ); // this is safe because the iterator is safe
654  *
655  * // check for iterator's safety
656  * for (HashTable<int,string>::iterator_safe iter = table1.beginSafe ();
657  * iter != table1.endSafe (); ++iter )
658  * table1.eraseByVal ( *iter );
659  * @endcode
660  *
661  * @tparam Key The type for keys in a gum::HashTable.
662  * @tparam Val The type for values in a gum::HashTable.
663  * @tparam Alloc The gum::HashTable allocator.
664  */
665  template < typename Key, typename Val, typename Alloc = std::allocator< std::pair< Key, Val > > >
666  class HashTable {
667  public:
668  /// Types for STL compliance.
669  /// @{
670  using key_type = Key;
671  using mapped_type = Val;
672  using value_type = std::pair< const Key, Val >;
673  using reference = value_type&;
674  using const_reference = const value_type&;
675  using pointer = value_type*;
676  using const_pointer = const value_type*;
677  using size_type = Size;
678  using difference_type = std::ptrdiff_t;
679  using allocator_type = Alloc;
680  using iterator = HashTableIterator< Key, Val >;
681  using const_iterator = HashTableConstIterator< Key, Val >;
682  using iterator_safe = HashTableIteratorSafe< Key, Val >;
683  using const_iterator_safe = HashTableConstIteratorSafe< Key, Val >;
684  /// @}
685 
686  /// The buckets where data are stored.
687  using Bucket = HashTableBucket< Key, Val >;
688 
689  /// The Bucket allocator.
690  using BucketAllocator = typename Alloc::template rebind< Bucket >::other;
691 
692  // ============================================================================
693  /// @name Constructors / Destructors
694  // ============================================================================
695  /// @{
696 
697  /**
698  * @brief Default constructor.
699  *
700  * The true capacity (vector's size) of the hashtable will be the lowest
701  * number greater than or equal to size_param that is also a power of 2.
702  * The second optional argument is the resizing policy. By default, each
703  * time there is an average of 3 elements by node, the size of the
704  * hashtable is automatically multiplied by 2. But the user may pass false
705  * as argument to resize_pol to disable this feature.
706  *
707  * @param size_param The initial size of the gum::HashTable.
708  * @param resize_pol The policy for resizing the hashtable when new
709  * elements are added (possible values: true = automatic resize and false =
710  * manual resize).
711  * @param key_uniqueness_pol Uniqueness policy : should we prevent inserting
712  * the same key more than once in the table?
713  */
714  explicit HashTable(Size size_param = HashTableConst::default_size,
715  bool resize_pol = HashTableConst::default_resize_policy,
716  bool key_uniqueness_pol = HashTableConst::default_uniqueness_policy);
717 
718  /**
719  * @brief Initializer list constructor.
720  * @param list The initialized list.
721  */
722  explicit HashTable(std::initializer_list< std::pair< Key, Val > > list);
723 
724  /**
725  * @brief Copy constructor.
726  *
727  * This creates a new hashtable the content of which is similar to that of
728  * the table passed in argument. Beware: similar does not mean that both
729  * tables share the same objects, but rather that the objects stored in the
730  * newly created table are copies of those of the table passed in argument.
731  * In particular, the new hash table inherits the parameters (resize
732  * policy, uniqueness policy) of table 'from'.
733  *
734  * @param from The gum::HashTable to copy.
735  */
736  HashTable(const HashTable< Key, Val, Alloc >& from);
737 
738  /**
739  * @brief Generalized copy constructor.
740  *
741  * This creates a new hashtable the content of which is similar to that of
742  * the table passed in argument. Beware: similar does not mean that both
743  * tables share the same objects, but rather that the objects stored in the
744  * newly created table are copies of those of the table passed in argument.
745  * In particular, the new hash table inherits the parameters (resize
746  * policy, uniqueness policy) of table 'table'
747  *
748  * @param from The gum::HashTable to copy.
749  */
750  template < typename OtherAlloc >
751  HashTable(const HashTable< Key, Val, OtherAlloc >& from);
752 
753  /**
754  * @brief Move constructor.
755  * @param from The gum::HashTable to move.
756  */
757  HashTable(HashTable< Key, Val, Alloc >&& from);
758 
759  /**
760  * @brief Class destructor.
761  */
762  ~HashTable();
763 
764  /// @}
765  // ============================================================================
766  /// @name Iterators
767  // ============================================================================
768  /// @{
769 
770  /**
771  * @brief Returns the unsafe iterator pointing to the end of the hashtable.
772  *
773  * Unsafe iterators are slightly faster than safe iterators. However, BE
774  * CAREFUL when using them: they should ONLY be used when you have the
775  * guarantee that they will never point to a deleted element. If unsure,
776  * prefer using the safe iterators (those are only slightly slower).
777  *
778  * @return Returns the unsafe iterator pointing to the end of the hashtable.
779  */
780  const iterator& end() noexcept;
781 
782  /**
783  * @brief Returns the unsafe const_iterator pointing to the end of the
784  * hashtable.
785  *
786  * Unsafe iterators are slightly faster than safe iterators. However, BE
787  * CAREFUL when using them: they should ONLY be used when you have the
788  * guarantee that they will never point to a deleted element. If unsure,
789  * prefer using the safe iterators (those are only slightly slower).
790  *
791  * @return Returns the unsafe const_iterator pointing to the end of the
792  * hashtable.
793  */
794  const const_iterator& end() const noexcept;
795 
796  /**
797  * @brief Returns the unsafe const_iterator pointing to the end of the
798  * hashtable.
799  *
800  * Unsafe iterators are slightly faster than safe iterators. However,
801  * BE CAREFUL when using them: they should ONLY be used when you have the
802  * guarantee that they will never point to a deleted element. If unsure,
803  * prefer using the safe iterators (those are only slightly slower).
804  *
805  * @return Returns the unsafe const_iterator pointing to the end of the
806  * hashtable.
807  */
808  const const_iterator& cend() const noexcept;
809 
810  /**
811  * @brief Returns an unsafe iterator pointing to the beginning of the
812  * hashtable.
813  *
814  * Unsafe iterators are slightly faster than safe iterators. However,
815  * BE CAREFUL when using them: they should ONLY be used when you have the
816  * guarantee that they will never point to a deleted element. If unsure,
817  * prefer using the safe iterators (those are only slightly slower).
818  *
819  * @return Returns an unsafe iterator pointing to the beginning of the
820  * hashtable.
821  */
822  iterator begin();
823 
824  /**
825  * @brief Returns an unsafe const_iterator pointing to the beginning of the
826  * hashtable.
827  *
828  * Unsafe iterators are slightly faster than safe iterators. However,
829  * BE CAREFUL when using them: they should ONLY be used when you have the
830  * guarantee that they will never point to a deleted element. If unsure,
831  * prefer using the safe iterators (those are only slightly slower).
832  *
833  * @return Returns an unsafe const_iterator pointing to the beginning of
834  * the hashtable.
835  */
836  const_iterator begin() const;
837 
838  /**
839  * @brief Returns an unsafe const_iterator pointing to the beginning of the
840  * hashtable.
841  *
842  * Unsafe iterators are slightly faster than safe iterators. However,
843  * BE CAREFUL when using them: they should ONLY be used when you have the
844  * guarantee that they will never point to a deleted element. If unsure,
845  * prefer using the safe iterators (those are only slightly slower).
846  *
847  * @return Returns an unsafe const_iterator pointing to the beginning of the
848  * hashtable.
849  */
850  const_iterator cbegin() const;
851 
852  /**
853  * @brief Returns the safe iterator pointing to the end of the hashtable.
854  *
855  * Safe iterators are slightly slower than unsafe ones but they guarantee
856  * that you will never get a segfault if they try to access to a deleted
857  * element or if they try a ++ operation from a deleted element.
858  *
859  * @return Returns the safe iterator pointing to the end of the hashtable.
860  */
861  const iterator_safe& endSafe() noexcept;
862 
863  /**
864  * @brief Returns the safe const_iterator pointing to the end of the
865  * hashtable.
866  *
867  * Safe iterators are slightly slower than unsafe ones but they guarantee
868  * that you will never get a segfault if they try to access to a deleted
869  * element or if they try a ++ operation from a deleted element.
870  *
871  * @return Returns the safe const_iterator pointing to the end of the
872  * hashtable.
873  */
874  const const_iterator_safe& endSafe() const noexcept;
875 
876  /**
877  * @brief Returns the safe const_iterator pointing to the end of the
878  * hashtable.
879  *
880  * Safe iterators are slightly slower than unsafe ones but they guarantee
881  * that you will never get a segfault if they try to access to a deleted
882  * element or if they try a ++ operation from a deleted element.
883  *
884  * @return Returns the safe const_iterator pointing to the end of the
885  * hashtable.
886  */
887  const const_iterator_safe& cendSafe() const noexcept;
888 
889  /**
890  * @brief Returns the safe iterator pointing to the beginning of the
891  * hashtable.
892  *
893  * Safe iterators are slightly slower than unsafe ones but they guarantee
894  * that you will never get a segfault if they try to access to a deleted
895  * element or if they try a ++ operation from a deleted element.
896  *
897  * @return Returns the safe iterator pointing to the beginning of the
898  * hashtable.
899  */
900  iterator_safe beginSafe();
901 
902  /**
903  * @brief Returns the safe const_iterator pointing to the beginning of the
904  * hashtable.
905  *
906  * Safe iterators are slightly slower than unsafe ones but they guarantee
907  * that you will never get a segfault if they try to access to a deleted
908  * element or if they try a ++ operation from a deleted element.
909  *
910  * @return Returns the safe const_iterator pointing to the beginning of the
911  * hashtable.
912  */
913  const_iterator_safe beginSafe() const;
914 
915  /**
916  * @brief Returns the safe const_iterator pointing to the beginning of the
917  * hashtable.
918  *
919  * Safe iterators are slightly slower than unsafe ones but they guarantee
920  * that you will never get a segfault if they try to access to a deleted
921  * element or if they try a ++ operation from a deleted element.
922  *
923  * @return Returns the safe const_iterator pointing to the beginning of the
924  * hashtable.
925  */
926  const_iterator_safe cbeginSafe() const;
927 
928  /**
929  * @brief Returns the end iterator for other classes' statics (read the
930  * detailed description of this method).
931  *
932  * To reduce memory consumption of hash tables (which are heavily used in
933  * aGrUM) while allowing fast for(iter=begin(); iter!=end();++iter) loops,
934  * end iterators are created just once as a static member of a non-template
935  * hashtable. While this scheme is efficient and it works quite effectively
936  * when manipulating hashtables, it has a drawback: other classes with
937  * static members using the HashTable's end() iterator may fail to work due
938  * to the well known "static initialization order fiasco" (see Marshall
939  * Cline's C++ FAQ for more details about this C++ feature). OK, so what is
940  * the problem? Consider for instance class Set. A Set contains a hashtable
941  * that stores all its elements in a convenient way. To reduce memory
942  * consumption, Set::end iterator is a static member that is initialized
943  * with a HashTable's end iterator. If the compiler decides to initialize
944  * Set::end before initializing HashTable::end, then Set::end will be in an
945  * incoherent state. Unfortunately, we cannot know for sure in which order
946  * static members will be initialized (the order is a compiler's decision).
947  * Hence, we shall enforce the fact that HashTable::end is initialized
948  * before Set::end. Using method HashTable::end4Statics will ensure this
949  * fact: it uses the C++ "construct on first use" idiom (see the C++ FAQ)
950  * that ensures that the order fiasco is avoided. More precisely,
951  * end4Statics initializes a global variable that is the very end iterator
952  * used by all hashtables. Now, this induces a small overhead. So, we also
953  * provide a HashTable::end() method that returns the end iterator without
954  * this small overhead, but assuming that function end4Statics has already
955  * been called once (which is always the case) when a hashtable has been
956  * created.
957  *
958  * So, to summarize: when initializing static members, use end4Statics()
959  * rather than end(). In all the other cases, use simply the usual method
960  * end().
961  *
962  * @return Returns the end iterator for other classes' statics (read the
963  * detailed description of this method).
964  */
965  static const iterator& end4Statics();
966 
967  /**
968  * @brief Returns the end iterator for other classes' statics (read the
969  * detailed description of this method).
970  *
971  * To reduce memory consumption of hash tables (which are heavily used in
972  * aGrUM) while allowing fast for(iter=begin(); iter!=end();++iter) loops,
973  * end iterators are created just once as a static member of a non-template
974  * hashtable. While this scheme is efficient and it works quite effectively
975  * when manipulating hashtables, it has a drawback: other classes with
976  * static members using the HashTable's end() iterator may fail to work due
977  * to the well known "static initialization order fiasco" (see Marshall
978  * Cline's C++ FAQ for more details about this C++ feature). OK, so what is
979  * the problem? Consider for instance class Set. A Set contains a hashtable
980  * that stores all its elements in a convenient way. To reduce memory
981  * consumption, Set::end iterator is a static member that is initialized
982  * with a HashTable's end iterator. If the compiler decides to initialize
983  * Set::end before initializing HashTable::end, then Set::end will be in an
984  * incoherent state. Unfortunately, we cannot know for sure in which order
985  * static members will be initialized (the order is a compiler's decision).
986  * Hence, we shall enforce the fact that HashTable::end is initialized
987  * before Set::end. Using method HashTable::end4Statics will ensure this
988  * fact: it uses the C++ "construct on first use" idiom (see the C++ FAQ)
989  * that ensures that the order fiasco is avoided. More precisely,
990  * end4Statics initializes a global variable that is the very end iterator
991  * used by all hashtables. Now, this induces a small overhead. So, we also
992  * provide a HashTable::end() method that returns the end iterator without
993  * this small overhead, but assuming that function end4Statics has already
994  * been called once (which is always the case) when a hashtable has been
995  * created.
996  *
997  * So, to summarize: when initializing static members, use
998  * constEnd4Statics() rather than cend(). In all the other cases, use
999  * simply the usual method cend().
1000  *
1001  * @return Returns the end iterator for other classes' statics (read the
1002  * detailed description of this method).
1003  */
1004  static const const_iterator& constEnd4Statics();
1005 
1006  /**
1007  * @brief Returns the end iterator for other classes' statics (read the
1008  * detailed description of this method).
1009  *
1010  * To reduce memory consumption of hash tables (which are heavily used in
1011  * aGrUM) while allowing fast for(iter=begin(); iter!=end();++iter) loops,
1012  * end iterators are created just once as a static member of a non-template
1013  * hashtable. While this scheme is efficient and it works quite effectively
1014  * when manipulating hashtables, it has a drawback: other classes with
1015  * static members using the HashTable's end() iterator may fail to work due
1016  * to the well known "static initialization order fiasco" (see Marshall
1017  * Cline's C++ FAQ for more details about this C++ feature). OK, so what is
1018  * the problem? Consider for instance class Set. A Set contains a hashtable
1019  * that stores all its elements in a convenient way. To reduce memory
1020  * consumption, Set::end iterator is a static member that is initialized
1021  * with a HashTable's end iterator. If the compiler decides to initialize
1022  * Set::end before initializing HashTable::end, then Set::end will be in an
1023  * incoherent state. Unfortunately, we cannot know for sure in which order
1024  * static members will be initialized (the order is a compiler's decision).
1025  * Hence, we shall enforce the fact that HashTable::end is initialized
1026  * before Set::end. Using method HashTable::end4Statics will ensure this
1027  * fact: it uses the C++ "construct on first use" idiom (see the C++ FAQ)
1028  * that ensures that the order fiasco is avoided. More precisely,
1029  * end4Statics initializes a global variable that is the very end iterator
1030  * used by all hashtables. Now, this induces a small overhead. So, we also
1031  * provide a HashTable::end() method that returns the end iterator without
1032  * this small overhead, but assuming that function end4Statics has already
1033  * been called once (which is always the case) when a hashtable has been
1034  * created.
1035  *
1036  * So, to summarize: when initializing static members, use
1037  * endSafe4Statics() rather than endSafe(). In all the other cases, use
1038  * simply the usual method endSafe().
1039  *
1040  * @return Returns the end iterator for other classes' statics (read the
1041  * detailed description of this method).
1042  */
1043  static const iterator_safe& endSafe4Statics();
1044 
1045  /**
1046  * @brief Returns the end iterator for other classes' statics (read the
1047  * detailed description of this method).
1048  *
1049  * To reduce memory consumption of hash tables (which are heavily used in
1050  * aGrUM) while allowing fast for(iter=begin(); iter!=end();++iter) loops,
1051  * end iterators are created just once as a static member of a non-template
1052  * hashtable. While this scheme is efficient and it works quite effectively
1053  * when manipulating hashtables, it has a drawback: other classes with
1054  * static members using the HashTable's end() iterator may fail to work due
1055  * to the well known "static initialization order fiasco" (see Marshall
1056  * Cline's C++ FAQ for more details about this C++ feature). OK, so what is
1057  * the problem? Consider for instance class Set. A Set contains a hashtable
1058  * that stores all its elements in a convenient way. To reduce memory
1059  * consumption, Set::end iterator is a static member that is initialized
1060  * with a HashTable's end iterator. If the compiler decides to initialize
1061  * Set::end before initializing HashTable::end, then Set::end will be in an
1062  * incoherent state. Unfortunately, we cannot know for sure in which order
1063  * static members will be initialized (the order is a compiler's decision).
1064  * Hence, we shall enforce the fact that HashTable::end is initialized
1065  * before Set::end. Using method HashTable::end4Statics will ensure this
1066  * fact: it uses the C++ "construct on first use" idiom (see the C++ FAQ)
1067  * that ensures that the order fiasco is avoided. More precisely,
1068  * end4Statics initializes a global variable that is the very end iterator
1069  * used by all hashtables. Now, this induces a small overhead. So, we also
1070  * provide a HashTable::end() method that returns the end iterator without
1071  * this small overhead, but assuming that function end4Statics has already
1072  * been called once (which is always the case) when a hashtable has been
1073  * created.
1074  *
1075  * So, to summarize: when initializing static members, use
1076  * constEndSafe4Statics() rather than cendSafe(). In all the other cases,
1077  * use simply the usual method cendSafe().
1078  *
1079  * @return Returns the end iterator for other classes' statics (read the
1080  * detailed description of this method).
1081  */
1082  static const const_iterator_safe& constEndSafe4Statics();
1083 
1084  /// @}
1085  // ============================================================================
1086  /// @name Operators
1087  // ============================================================================
1088  /// @{
1089 
1090  /**
1091  * @brief Copy operator.
1092  *
1093  * The copy operators ensures that whenever a memory allocation problem
1094  * occurs, no memory leak occurs as well and it also guarantees that in
1095  * this case the hashtable returned is in a coherent state (it is an empty
1096  * hashtable). Note that the copy not only involves copying pairs
1097  * (key,value) but also the copy of the resize and key uniqueness policies.
1098  *
1099  * @param from The gum::HashTable to copy.
1100  * @return Returns this gum::HashTable.
1101  */
1102  HashTable< Key, Val, Alloc >& operator=(const HashTable< Key, Val, Alloc >& from);
1103 
1104  /**
1105  * @brief Generalized copy operator.
1106  *
1107  * The copy operators ensures that whenever a memory allocation problem
1108  * occurs, no memory leak occurs as well and it also guarantees that in
1109  * this case the hashtable returned is in a coherent state (it is an empty
1110  * hashtable). Note that the copy not only involves copying pairs
1111  * (key,value) but also the copy of the resize and key uniqueness policies.
1112  *
1113  * @param from The gum::HashTable to copy.
1114  * @return Returns this gum::HashTable.
1115  */
1116  template < typename OtherAlloc >
1117  HashTable< Key, Val, Alloc >& operator=(const HashTable< Key, Val, OtherAlloc >& from);
1118 
1119  /**
1120  * Move operator.
1121  *
1122  * @param from The gum::HashTable to move.
1123  * @return Returns this gum::HashTable.
1124  */
1125  HashTable< Key, Val, Alloc >& operator=(HashTable< Key, Val, Alloc >&& from);
1126 
1127  /**
1128  * @brief Returns a reference on the value the key of which is passed in
1129  * argument.
1130  *
1131  * In case of multiple identical keys in the hash table, the first value
1132  * encountered is returned. The method runs in constant time.
1133  *
1134  * @param key The key of the value to return.
1135  * @return Returns the value matching the given key.
1136  * @throws NotFound exception is thrown if the element cannot be found.
1137  */
1138  Val& operator[](const Key& key);
1139 
1140  /// returns a reference on the value the key of which is passed in argument
1141  /** In case of multiple identical keys in the hash table, the first value
1142  * encountered is returned. The method runs in constant time.
1143  * @throws NotFound exception is thrown if the element cannot be found. */
1144  const Val& operator[](const Key& key) const;
1145 
1146  /**
1147  * @brief Checks whether two hashtables contain the same elements.
1148  *
1149  * Two hashtables are considered equal if they contain the identical pairs
1150  * (key,val). Two pairs are identical if their keys have the same hashed
1151  * value, these two keys are equal in the sense of ==, and their val's are
1152  * also equal in the sense of ==.
1153  *
1154  * @param from The gum::HashTable to test for equality.
1155  * @return True if this and from are equal.
1156  */
1157  template < typename OtherAlloc >
1158  bool operator==(const HashTable< Key, Val, OtherAlloc >& from) const;
1159 
1160  ///
1161  /**
1162  * @brief Checks whether two hashtables contain different sets of elements.
1163  *
1164  * Two hashtables are considered different if they contain different pairs
1165  * (key,val). Two pairs are different if their keys have different hashed
1166  * values, or if they are different in the sense of !=, or if their val's
1167  * are different in the sense of !=.
1168  *
1169  * @param from The gum::HashTable to test for inequality.
1170  * @return True if this and from are not equal.
1171  */
1172  template < typename OtherAlloc >
1173  bool operator!=(const HashTable< Key, Val, OtherAlloc >& from) const;
1174 
1175  /// @}
1176  // ============================================================================
1177  /// @name Fine tuning
1178  // ============================================================================
1179  /// @{
1180 
1181  /**
1182  * @brief Returns the number of slots in the 'nodes' vector of the
1183  * hashtable.
1184  *
1185  * The method runs in constant time.
1186  *
1187  * @return Returns the number of slots in the 'nodes' vector of the
1188  * hashtable.
1189  */
1190  Size capacity() const noexcept;
1191 
1192  ///
1193  /**
1194  * @brief Changes the number of slots in the 'nodes' vector of the hash
1195  * table.
1196  *
1197  * Usually, method resize enables the user to resize manually the
1198  * hashtable. When in automatic resize mode, the function will actually
1199  * resize the table only if resizing policy is compatible with the new
1200  * size, i.e., the new size is not so small that there would be too many
1201  * elements per slot in the table (this would lead to a significant loss in
1202  * performance). However, the resizing policy may be changed by using
1203  * method setResizePolicy. The method runs in linear time in the size of
1204  * the hashtable. Upon memory allocation problem, the fuction guarantees
1205  * that no data is lost and that the hash table and its iterators are in a
1206  * coherent state. In such a case, a bad_alloc exception is thrown.
1207  *
1208  * @param new_size The new number of slots in the gum::HashTable.
1209  */
1210  void resize(Size new_size);
1211 
1212  /**
1213  * @brief Enables the user to change dynamically the resizing policy.
1214  *
1215  * In most cases, this should be useless. However, when available memory
1216  * becomes rare, avoiding automatic resizing may speed-up new insertions in
1217  * the table.
1218  *
1219  * @warning This function never resizes the hashtable by itself: even if
1220  * you set the new policy to be an automatic resizing and the number of
1221  * elements in the table is sufficiently high that we should resize the
1222  * table, function setResizePolicy won't perform this resizing. The
1223  * resizing will happen only if you insert a new element or if use method
1224  * resize.
1225  *
1226  * @param new_policy The new resizing policy, true implies automatic
1227  * resizing.
1228  */
1229  void setResizePolicy(const bool new_policy) noexcept;
1230 
1231  /**
1232  * @brief Returns the current resizing policy.
1233  * @return Returns the current resizing policy.
1234  */
1235  bool resizePolicy() const noexcept;
1236 
1237  /**
1238  * @brief Enables the user to change dynamically the policy for checking
1239  * whether there can exist several elements in the table with identical
1240  * keys.
1241  *
1242  * By default, we should always check that there does not exist duplicate
1243  * keys. However, this test slows the insertion of elements in the table.
1244  * So, when we know for sure that no duplicate key will be entered into the
1245  * table, we may avoid uniqueness checks.
1246  *
1247  * @warning When setting the key policy to "uniqueness", the function does
1248  * not check whether there are already different elements with identical
1249  * keys in the table. It thus only ensures that elements inserted from now
1250  * on will have unique keys.
1251  */
1252  void setKeyUniquenessPolicy(const bool new_policy) noexcept;
1253 
1254  /**
1255  * @brief Returns the current checking policy.
1256  * @return Returns the current checking policy.
1257  */
1258  bool keyUniquenessPolicy() const noexcept;
1259 
1260  /// @}
1261  // ============================================================================
1262  /// @name Accessors / Modifiers
1263  // ============================================================================
1264  /// @{
1265 
1266  /**
1267  * @brief Returns the number of elements stored into the hashtable.
1268  *
1269  * The method runs in constant time.
1270  *
1271  * @return Returns the number of elements stored into the hashtable.
1272  */
1273  Size size() const noexcept;
1274 
1275  /**
1276  * @brief Checks whether there exists an element with a given key in the
1277  * hashtable.
1278  *
1279  * The method runs in average in constant time if the resizing policy
1280  * is set.
1281  *
1282  * @param key The key to test for existence.
1283  * @return True if key is in this gum::HashTable.
1284  */
1285  bool exists(const Key& key) const;
1286 
1287  /**
1288  * @brief Adds a new element (actually a copy of this element) into the
1289  * hash table.
1290  *
1291  * If there already exists an element with the same key in the table and the
1292  * uniqueness policy prevents multiple identical keys to belong to the same
1293  * hashtable, an exception DuplicateElement is thrown. If the uniqueness
1294  * policy is not set, the method runs in the worst case in constant time,
1295  * else if the automatic resizing policy is set, it runs in constant time in
1296  * average linear in the number of elements by slot. @return As only a copy
1297  * of val is inserted into the hashtable, the method returns a reference on
1298  * a copy of the pair (key,val). @throw DuplicateElement is thrown when
1299  * attempting to insert a pair (key,val) in a hash table containing already
1300  * a pair with the same key and when the hash table's uniqueness policy is
1301  * set.
1302  *
1303  * @param key The key to add.
1304  * @param val The value to add.
1305  * @return The value added by copy to this gum::HashTable.
1306  */
1307  value_type& insert(const Key& key, const Val& val);
1308 
1309  /**
1310  * @brief Moves a new element in the hash table.
1311  *
1312  * If there already exists an element with the same key in the table and
1313  * the uniqueness policy prevents multiple identical keys to belong to the
1314  * same hashtable, an exception DuplicateElement is thrown. If the
1315  * uniqueness policy is not set, the method runs in the worst case in
1316  * constant time, else if the automatic resizing policy is set, it runs in
1317  * constant time in average linear in the number of elements by slot.
1318  * @return a reference to the pair (key,val) in the hashtable. @throw
1319  * DuplicateElement is thrown when attempting to insert a pair (key,val) in
1320  * a hash table containing already a pair with the same key and when the
1321  * hash table's uniqueness policy is set.
1322  *
1323  * @param key The key to move.
1324  * @param val The value to move.
1325  * @return The value moved to this gum::HashTable.
1326  */
1327  value_type& insert(Key&& key, Val&& val);
1328 
1329  /**
1330  * @brief Adds a new element (actually a copy of this element) into the
1331  * hash table.
1332  *
1333  * If there already exists an element with the same key in the table and
1334  * the uniqueness policy prevents multiple identical keys to belong to the
1335  * same hashtable, an exception DuplicateElement is thrown. If the
1336  * uniqueness policy is not set, the method runs in the worst case in
1337  * constant time, else if the automatic resizing policy is set, it runs in
1338  * constant time in average linear in the number of elements by slot.
1339  * @return As only a copy of val is inserted into the hashtable, the method
1340  * returns a reference on a copy of the pair (key,val). @throw
1341  * DuplicateElement is thrown when attempting to insert a pair (key,val) in
1342  * a hash table containing already a pair with the same key and when the
1343  * hash table's uniqueness policy is set.
1344  *
1345  * @param elt The pair of key value to add.
1346  * @return The value added by copy to this gum::HashTable.
1347  */
1348  value_type& insert(const std::pair< Key, Val >& elt);
1349 
1350  /**
1351  * @brief Moves a new element in the hash table.
1352  *
1353  * If there already exists an element with the same key in the table and
1354  * the uniqueness policy prevents multiple identical keys to belong to the
1355  * same hashtable, an exception DuplicateElement is thrown. If the
1356  * uniqueness policy is not set, the method runs in the worst case in
1357  * constant time, else if the automatic resizing policy is set, it runs in
1358  * constant time in average linear in the number of elements by slot.
1359  * @return a reference to the pair (key,val) in the hashtable. @throw
1360  * DuplicateElement is thrown when attempting to insert a pair (key,val) in
1361  * a hash table containing already a pair with the same key and when the
1362  * hash table's uniqueness policy is set.
1363  *
1364  * @param elt The pair of key value to move in this gum::HashTable.
1365  * @return The value moved to this gum::HashTable.
1366  */
1367  value_type& insert(std::pair< Key, Val >&& elt);
1368 
1369  /**
1370  * @brief Emplace a new element into the hashTable.
1371  *
1372  * If there already exists an element with the same key in the list and the
1373  * uniqueness policy prevents multiple identical keys to belong to the same
1374  * hashtable, an exception DuplicateElement is thrown. If the uniqueness
1375  * policy is not set, the method runs in the worst case in constant time,
1376  * else if the automatic resizing policy is set, it runs in constant time
1377  * in average linear in the number of elements by slot. @return a
1378  * reference to the pair (key,val) inserted in the hash table. @throw
1379  * DuplicateElement is thrown when attempting to insert a pair (key,val) in
1380  * a hash table containing already a pair with the same key and when the
1381  * hash table's uniqueness policy is set.
1382  *
1383  * @param args The element to emplace.
1384  */
1385  template < typename... Args >
1386  value_type& emplace(Args&&... args);
1387 
1388  /**
1389  * @brief Returns a reference on the element the key of which is passed in
1390  * argument.
1391  *
1392  * In case of multiple identical keys in the hash table, the first value
1393  * encountered is returned. The method runs in constant time.
1394  * In case of not found key, (key,default_value) is inserted in *this.
1395  *
1396  * @param key The key for wich we want the value.
1397  * @param default_value The default value to return if key does not match
1398  * any value.
1399  * @return Returns a reference on the element the key of which is passed in
1400  * argument.
1401  */
1402  mapped_type& getWithDefault(const Key& key, const Val& default_value);
1403 
1404  /**
1405  * @brief Returns a reference on the element the key of which is passed in
1406  * argument.
1407  *
1408  * In case of multiple identical keys in the hash table, the first value
1409  * encountered is returned. The method runs in constant time. In case of
1410  * not found key, (key,default_value) is inserted in *this.
1411  *
1412  * @param key The key for wich we want the value.
1413  * @param default_value The default value to return if key does not match
1414  * any value.
1415  * @return Returns a reference on the element the key of which is passed in
1416  * argument.
1417  */
1418  mapped_type& getWithDefault(Key&& key, Val&& default_value);
1419 
1420  /**
1421  * @brief Add a new property or modify it if it already existed.
1422  *
1423  * When used as a "dynamic property list", it may be convenient to use this
1424  * function. Function set inserts a new pair (key,val) if the key does not
1425  * already exists, or it changes the value associated with key if a pair
1426  * (key,val) already exists in the hash table.
1427  *
1428  * @param key The key of the value to add or set.
1429  * @param default_value The value to set or add.
1430  */
1431  void set(const Key& key, const Val& default_value);
1432 
1433  /**
1434  * @brief Removes a property (i.e., remove an element).
1435  *
1436  * Reset removes a property (i.e., a pair (key,val)) if it exists. This is
1437  * an alias for erase but it is quite convenient when dealing with "dynamic
1438  * property lists".
1439  *
1440  * @param key The property to remove.
1441  */
1442  void reset(const Key& key);
1443 
1444  /**
1445  * @brief Removes a given element from the hash table.
1446  *
1447  * The element is the first one encountered in the list (from begin() to
1448  * end()) having the specified key. If no such element can be found,
1449  * nothing is done (in particular, it does not throw any exception). The
1450  * function never resizes the nodes vector (even if the resizing policy
1451  * would enable to decrease this size). The method runs in average in time
1452  * linear to the number of iterators pointing to the table if the automatic
1453  * resizing policy is set (else it is in linear time in the number of
1454  * elements of the hash table plus the number of iterators).
1455  *
1456  * @param key The key of the element to remove.
1457  */
1458  void erase(const Key& key);
1459 
1460  /**
1461  * @brief Removes a given element from the hash table.
1462  *
1463  * This method updates all the safe iterators pointing to the deleted
1464  * element, i.e., when trying to dereference those iterators, an exception
1465  * will be raised because they will know that the element they point to no
1466  * longer exists.
1467  *
1468  * @param iter An iterator over the element to remove.
1469  */
1470  void erase(const iterator_safe& iter);
1471 
1472  /**
1473  * @brief Removes a given element from the hash table.
1474  *
1475  * This method updates all the safe iterators pointing to the deleted
1476  * element, i.e., when trying to dereference those iterators, an exception
1477  * will be raised because they will know that the element they point to no
1478  * longer exists.
1479  *
1480  * @param iter An iterator over the element to remove.
1481  */
1482  void erase(const const_iterator_safe& iter);
1483 
1484  /**
1485  * @brief Removes a given element from the hash table.
1486  *
1487  * The element is the first one encountered in the list (from begin() to
1488  * end()) having the specified value. If no such element can be found,
1489  * nothing is done (in particular, it does not throw any exception). The
1490  * function never resizes the nodes vector (even if the resizing policy
1491  * would enable to decrease this size). Comparisons between Val instances
1492  * are performed through == operators. Logically, this method should have
1493  * been named "erase", however, this would have prevented creating hash
1494  * tables where both keys and vals have the same type. Hence we chose to
1495  * add "ByVal" after erase to make a difference between erasing by key and
1496  * erasing by val.
1497  *
1498  * @param val The value to remove.
1499  */
1500  void eraseByVal(const Val& val);
1501 
1502  /**
1503  * @brief Returns a reference on the key given a value.
1504  *
1505  * In case of multiple identical values in the hash table, the first key
1506  * encountered is returned. The method runs in linear time.
1507  *
1508  * @param val The value for which the key is returned.
1509  * @return Returns a reference on the key given a value.
1510  * @throws NotFound Raised if the element cannot be found.
1511  */
1512  const Key& keyByVal(const Val& val) const;
1513 
1514  /**
1515  * @brief Returns a reference on a given key.
1516  *
1517  * Some complex structures use pointers on keys of hashtables. These
1518  * structures thus require that we do not only get a copy of a given key,
1519  * but the key stored in the hashtable itself. This is the very purpose of
1520  * this function.
1521  *
1522  * @param key The key to return.
1523  * @return Returns a reference on a given key.
1524  * @throw NotFound Raised if the element cannot be found.
1525  */
1526  const Key& key(const Key& key) const;
1527 
1528  /**
1529  * @brief Removes all the elements having a certain value from the hash
1530  * table.
1531  *
1532  * If no such element can be found, nothing is done (in particular, it does
1533  * not throw any exception). The function never resizes the nodes vector
1534  * (even if the resizing policy would enable to decrease this size).
1535  * Comparisons between Val instances are performed through == operators.
1536  *
1537  * @param val The value to remove.
1538  *
1539  */
1540  void eraseAllVal(const Val& val);
1541 
1542  /**
1543  * @brief Removes all the elements in the hash table.
1544  *
1545  * The function does not resize the nodes vector (even if the size of this
1546  * one has been increased after the creation of the hash table) and it
1547  * resets the iterators on the hash table to end. The method runs in linear
1548  * time w.r.t. the number of iterators pointing to the hash table.
1549  */
1550  void clear();
1551 
1552  /**
1553  * @brief Indicates whether the hash table is empty.
1554  * @return Returns true if the gum::HashTable is empty.
1555  */
1556  bool empty() const noexcept;
1557 
1558  /**
1559  * @brief Transforms a hashtable of vals into a hashtable of mountains.
1560  *
1561  * @warning Although the resulting hashtable has the same number of
1562  * elements as the original hashtable, by default, the size of the former
1563  * may not be equal to that of the latter. Hence iterators on the original
1564  * hashtable may not parse it in the same order as iterators on the
1565  * resulting hashtable. To guarrantee that both hashtables have the same
1566  * size (and thus have the elements in the same order), set the @e size
1567  * argument to the size of the original hashtable.
1568  *
1569  * @param f A function that maps any Val element into a Mount.
1570  * @param size The size of the resulting hashtable. When equal to 0, a
1571  * default size is computed that is a good trade-off between space
1572  * consumption and efficiency of new elements insertions
1573  * @param resize_pol the resizing policy (automatic or manual resizing)
1574  * @param key_uniqueness_pol uniqueness policy
1575  *
1576  * @return Returns the gum::HashTable of mountains.
1577  */
1578  template < typename Mount,
1579  typename OtherAlloc
1580  = typename Alloc::template rebind< std::pair< Key, Mount > >::other >
1581  HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(Val),
1582  Size size = Size(0),
1583  bool resize_pol = HashTableConst::default_resize_policy,
1584  bool key_uniqueness_pol
1585  = HashTableConst::default_uniqueness_policy) const;
1586 
1587  /**
1588  * @brief Transforms a hashtable of vals into a hashtable of mountains.
1589  *
1590  * @warning Although the resulting hashtable has the same number of
1591  * elements as the original hashtable, by default, the size of the former
1592  * may not be equal to that of the latter. Hence iterators on the original
1593  * hashtable may not parse it in the same order as iterators on the
1594  * resulting hashtable. To guarrantee that both hashtables have the same
1595  * size (and thus have the elements in the same order), set the @e size
1596  * argument to the size of the original hashtable.
1597  *
1598  * @param f A function that maps any Val element into a Mount.
1599  * @param size The size of the resulting hashtable. When equal to 0, a
1600  * default size is computed that is a good trade-off between space
1601  * consumption and efficiency of new elements insertions
1602  * @param resize_pol the resizing policy (automatic or manual resizing)
1603  * @param key_uniqueness_pol uniqueness policy
1604  *
1605  * @return Returns the gum::HashTable of mountains.
1606  */
1607  template < typename Mount,
1608  typename OtherAlloc
1609  = typename Alloc::template rebind< std::pair< Key, Mount > >::other >
1610  HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(Val&),
1611  Size size = Size(0),
1612  bool resize_pol = HashTableConst::default_resize_policy,
1613  bool key_uniqueness_pol
1614  = HashTableConst::default_uniqueness_policy) const;
1615 
1616  /**
1617  * @brief Transforms a hashtable of vals into a hashtable of mountains.
1618  *
1619  * @warning Although the resulting hashtable has the same number of
1620  * elements as the original hashtable, by default, the size of the former
1621  * may not be equal to that of the latter. Hence iterators on the original
1622  * hashtable may not parse it in the same order as iterators on the
1623  * resulting hashtable. To guarrantee that both hashtables have the same
1624  * size (and thus have the elements in the same order), set the @e size
1625  * argument to the size of the original hashtable.
1626  *
1627  * @param f A function that maps any Val element into a Mount.
1628  * @param size The size of the resulting hashtable. When equal to 0, a
1629  * default size is computed that is a good trade-off between space
1630  * consumption and efficiency of new elements insertions
1631  * @param resize_pol the resizing policy (automatic or manual resizing)
1632  * @param key_uniqueness_pol uniqueness policy
1633  *
1634  * @return Returns the gum::HashTable of mountains.
1635  */
1636  template < typename Mount,
1637  typename OtherAlloc
1638  = typename Alloc::template rebind< std::pair< Key, Mount > >::other >
1639  HashTable< Key, Mount, OtherAlloc > map(Mount (*f)(const Val&),
1640  Size size = Size(0),
1641  bool resize_pol = HashTableConst::default_resize_policy,
1642  bool key_uniqueness_pol
1643  = HashTableConst::default_uniqueness_policy) const;
1644 
1645  /**
1646  * @brief Creates a hashtable of mounts with a given value from a hashtable
1647  * of vals.
1648  *
1649  * @warning Although the resulting hashtable has the same number of
1650  * elements as the original hashtable, by default, the size of the former
1651  * may not be equal to that of the latter. Hence iterators on the original
1652  * hashtable may not parse it in the same order as iterators on the
1653  * resulting hashtable. To guarrantee that both hashtables have the same
1654  * size (and thus have the elements in the same order), set the @e size
1655  * argument to the size of the original hashtable.
1656  *
1657  * @param val The value taken by all the elements of the resulting
1658  * hashtable.
1659  * @param size The size of the resulting hashtable. When equal to 0, a
1660  * default size is computed that is a good trade-off between space
1661  * consumption and efficiency of new elements insertions
1662  * @param resize_pol the resizing policy (automatic or manual resizing)
1663  * @param key_uniqueness_pol uniqueness policy
1664  *
1665  * @return Returns the gum::HashTable of mountains.
1666  */
1667  template < typename Mount,
1668  typename OtherAlloc
1669  = typename Alloc::template rebind< std::pair< Key, Mount > >::other >
1670  HashTable< Key, Mount, OtherAlloc > map(const Mount& val,
1671  Size size = Size(0),
1672  bool resize_pol = HashTableConst::default_resize_policy,
1673  bool key_uniqueness_pol
1674  = HashTableConst::default_uniqueness_policy) const;
1675 
1676  /// @}
1677 
1678  private:
1679  /// Friends to optimize the access to data, iterators must be friends
1680  /// @{
1681  template < typename K, typename V, typename A >
1682  friend class HashTable;
1683  friend class HashTableIterator< Key, Val >;
1684  friend class HashTableConstIterator< Key, Val >;
1685  friend class HashTableIteratorSafe< Key, Val >;
1686  friend class HashTableConstIteratorSafe< Key, Val >;
1687 
1688  friend std::ostream& operator<<<>(std::ostream&, const HashTable< Key, Val, Alloc >&);
1689  friend std::ostream& operator<<<>(std::ostream& s, const HashTable< Key*, Val, Alloc >& table);
1690 
1691  /// For bijections to quickly access data.
1692  template < typename T1, typename T2, typename A >
1693  friend class Bijection;
1694  /// @}
1695 
1696  /**
1697  * The hash table is represented as a vector of chained lists. ' __nodes'
1698  * is this very vector.
1699  */
1700  std::vector< HashTableList< Key, Val, Alloc > > _nodes_;
1701 
1702  /// The number of nodes in vector ' __nodes'.
1703  Size _size_;
1704 
1705  /// Number of elements of type Val stored in the hash table.
1706  Size _nb_elements_{Size(0)};
1707 
1708  /// The function used to hash keys (may change when the table is resized).
1709  HashFunc< Key > _hash_func_;
1710 
1711  /// Is resizing performed automatically?
1712  bool _resize_policy_{true};
1713 
1714  /// Shall we check for key uniqueness in the table?
1715  bool _key_uniqueness_policy_{true};
1716 
1717  /**
1718  * @brief Returns where the begin index should be.
1719  *
1720  * Beware: the beginning of a HashTable is the end of its _nodes_ vector,
1721  * i.e., the Bucket at the highest index in _nodes_. This enables a
1722  * slightly faster parsing than if it were the lowest index. @warning
1723  * std::numeric_limits<Size>::max() means that we do not know where the
1724  * beginning of the table really is (this can mean either that there is not
1725  * yet any element in the hash table or that an erase operation has been
1726  * performed and that we lost track of the element that should correspond
1727  * to the begin().
1728  *
1729  * @return Returns where the begin index should be.
1730  */
1731  mutable Size _begin_index_{std::numeric_limits< Size >::max()};
1732 
1733  /// The list of safe iterators pointing to the hash table.
1734  mutable std::vector< HashTableConstIteratorSafe< Key, Val >* > _safe_iterators_;
1735 
1736  /**
1737  * @brief The allocator for the buckets.
1738  *
1739  * @warning the allocator field should compulsorily be the last of field of
1740  * the class. As such, for K and V fixed, all hashTable<K,V,A> are the same
1741  * (up to the allocator) for all allocators A. This feature proves useful
1742  * to avoid passing the allocator as a template parameter to iterators.
1743  */
1744  BucketAllocator _alloc_;
1745 
1746  /// Erases a given bucket.
1747  void _erase_(HashTableBucket< Key, Val >* bucket, Size index);
1748 
1749  /**
1750  * @brief A function used to perform copies of HashTables.
1751  *
1752  * This code is shared by the copy constructor and the copy operator. The
1753  * function ensures that when a memory allocation problem occurs:
1754  * - no memory leak occurs
1755  * - the hashtable returned is empty but in a coherent state
1756  * - an exception is thrown
1757  *
1758  * The function assumes that both this and table have arrays ' __nodes' of
1759  * the same size.
1760  *
1761  * @param table The gum::HashTable to copy.
1762  * @tparam OtherAlloc The other gum::HashTable allocator.
1763  */
1764  template < typename OtherAlloc >
1765  void _copy_(const HashTable< Key, Val, OtherAlloc >& table);
1766 
1767  /**
1768  * @brief Used by all default constructors (general and specialized).
1769  * @param size The size of the gum::HashTable to create.
1770  */
1771  void _create_(Size size);
1772 
1773  /**
1774  * @brief Clear all the safe iterators.
1775  */
1776  void _clearIterators_();
1777 
1778  /**
1779  * @brief Adds a new element (actually a copy of this element) in the hash
1780  * table.
1781  *
1782  * If there already exists an element with the same key in the list and the
1783  * uniqueness policy prevents multiple identical keys to belong to the same
1784  * hashtable, an exception DuplicateElement is thrown. If the uniqueness
1785  * policy is not set, the method runs in the worst case in constant time,
1786  * else if the automatic resizing policy is set, it runs in constant time
1787  * in average linear in the number of elements by slot.
1788  *
1789  * @param bucket The bucket inserted in the hash table.
1790  * @throw DuplicateElement is thrown when attempting to insert a pair
1791  * (key,val) in a hash table containing already a pair with the same key
1792  * and when the hash table's uniqueness policy is set.
1793  */
1794  void _insert_(Bucket* bucket);
1795  };
1796 
1797 
1798  // ===========================================================================
1799  // === SAFE HASH TABLES CONST ITERATORS ===
1800  // ===========================================================================
1801 
1802  /**
1803  * @class HashTableIteratorStaticEnd
1804  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
1805  * @brief A class used to create the static iterator used by HashTables.
1806  * @ingroup hashtable_group
1807  *
1808  * The aim of using this class rather than just creating _HashTableIterEnd_
1809  * as a global variable is to prevent other classes to access and modify
1810  * _HashTableIterEnd_.
1811  */
1812  class HashTableIteratorStaticEnd {
1813  private:
1814  /// The unsafe iterator used by everyone.
1815  static const HashTableIterator< int, int >* _HashTableIterEnd_;
1816 
1817  /// The safe iterator used by everyone.
1818  static const HashTableIteratorSafe< int, int >* _HashTableIterEndSafe_;
1819 
1820  /**
1821  * @brief Creates (if needed) and returns the iterator _HashTableIterEnd_.
1822  * @return Returns the iterator _HashTableIterEnd_.
1823  */
1824  static const HashTableIterator< int, int >* end4Statics();
1825 
1826  /**
1827  * @brief Creates (if needed) and returns the iterator _HashTableIterEnd_.
1828  * @return Returns the iterator _HashTableIterEnd_.
1829  */
1830  static const HashTableConstIterator< int, int >* constEnd4Statics();
1831 
1832  /**
1833  * @brief Creates (if needed) and returns the iterator
1834  * _HashTableIterEndSafe_.
1835  * @return Returns the iterator _HashTableIterEndSafe_.
1836  */
1837  static const HashTableIteratorSafe< int, int >* endSafe4Statics();
1838 
1839  /**
1840  * @brief Creates (if needed) and returns the iterator
1841  * _HashTableIterEndSafe_.
1842  * @return Returns the iterator _HashTableIterEndSafe_.
1843  */
1844  static const HashTableConstIteratorSafe< int, int >* constEndSafe4Statics();
1845 
1846  /// Friends that have access to the iterator.
1847  template < typename Key, typename Val, typename Alloc >
1848  friend class HashTable;
1849  };
1850 
1851 
1852  // ===========================================================================
1853  // === SAFE HASH TABLES CONST ITERATORS ===
1854  // ===========================================================================
1855  /**
1856  * @class HashTableConstIteratorSafe
1857  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
1858  * @brief Safe Const Iterators for hashtables.
1859  * @ingroup hashtable_group
1860  *
1861  * HashTableConstIteratorSafe provides a safe way to parse HashTables. They
1862  * are safe because they are kept informed by the hashtable they belong to of
1863  * the elements deleted by the user. Hence, even if the user removes an
1864  * element pointed to by a HashTableConstIteratorSafe, using the latter to
1865  * access this element will never crash the application. Instead it will
1866  * properly throw a UndefinedIteratorValue exception.
1867  *
1868  * Developers may consider using HashTable<x,y>::const_iterator_safe instead
1869  * of HashTableConstIteratorSafe<x,y>.
1870  *
1871  * @par Usage example:
1872  * @code
1873  * // creation of a hash table with 10 elements
1874  * HashTable<int,string> table;
1875  * for (int i = 0; i< 10; ++i)
1876  * table.insert (i,"xxx" + string (i,'x'));
1877  *
1878  * // parse the hash table
1879  * for (HashTable<int,string>::const_iterator_safe iter = table.cbeginSafe ();
1880  * iter != table.cendSafe (); ++iter) {
1881  * // display the values
1882  * cerr << "at " << iter.key () << " value = " << iter.val () << endl;
1883  * const HashTable<int,string>::value_type& elt = *iter;
1884  * const std::pair<const int, string>& xelt = *iter;
1885  * }
1886  *
1887  * // check whether two iterators point toward the same element
1888  * HashTable<int,string>::const_iterator_safe iter1 = table1.cbeginSafe ();
1889  * HashTable<int,string>::const_iterator_safe iter2 = table1.cendSafe ();
1890  * if (iter1 != iter) {
1891  * cerr << "iter1 and iter2 point toward different elements";
1892  * }
1893  *
1894  * // make iter1 point toward nothing
1895  * iter1.clear ();
1896  * @endcode
1897  */
1898  template < typename Key, typename Val >
1899  class HashTableConstIteratorSafe {
1900  public:
1901  /// Types for STL compliance.
1902  /// @{
1903  using iterator_category = std::forward_iterator_tag;
1904  using key_type = Key;
1905  using mapped_type = Val;
1906  using value_type = std::pair< const Key, Val >;
1907  using reference = value_type&;
1908  using const_reference = const value_type&;
1909  using pointer = value_type*;
1910  using const_pointer = const value_type*;
1911  using difference_type = std::ptrdiff_t;
1912  /// @}
1913 
1914  // ============================================================================
1915  /// @name Constructors / Destructors
1916  // ============================================================================
1917  /// @{
1918 
1919  /**
1920  * @brief Basic constructor: creates an iterator pointing to nothing.
1921  */
1922  HashTableConstIteratorSafe();
1923 
1924  /**
1925  * @brief Constructor for an iterator pointing to the first element of a
1926  * hashtable.
1927  * @tparam Alloc The gum::HashTable allocator.
1928  * @param tab A gum::HashTable to iterate over.
1929  */
1930  template < typename Alloc >
1931  HashTableConstIteratorSafe(const HashTable< Key, Val, Alloc >& tab);
1932 
1933  ///
1934  /**
1935  * @brief Constructor for an iterator pointing to the nth element of a
1936  * hashtable.
1937  *
1938  * The method runs in time linear to ind_elt.
1939  *
1940  * @tparam Alloc The gum::HashTable allocator.
1941  * @param tab the hash table to which the so-called element belongs
1942  * @param ind_elt the position of the element in the hash table (0 means
1943  * the first element).
1944  * @throw UndefinedIteratorValue Raised if the element cannot be found.
1945  */
1946  template < typename Alloc >
1947  HashTableConstIteratorSafe(const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
1948 
1949  /**
1950  * @brief Copy constructor.
1951  * @param from The gum::HashTableConstIteratorSafe to copy.
1952  */
1953  HashTableConstIteratorSafe(const HashTableConstIteratorSafe< Key, Val >& from);
1954 
1955  /**
1956  * @brief Copy constructor.
1957  * @param from The gum::HashTableConstIterator to copy.
1958  */
1959  explicit HashTableConstIteratorSafe(const HashTableConstIterator< Key, Val >& from);
1960 
1961  /**
1962  * @brief Move constructor.
1963  * @param from The gum::HashTableConstIteratorSafe to move.
1964  */
1965  HashTableConstIteratorSafe(HashTableConstIteratorSafe< Key, Val >&& from);
1966 
1967  /**
1968  * @brief Destructor.
1969  */
1970  ~HashTableConstIteratorSafe() noexcept;
1971 
1972  /// @}
1973  // ============================================================================
1974  /// @name Accessors / Modifiers
1975  // ============================================================================
1976  /// @{
1977 
1978  /**
1979  * @brief Returns the key pointed to by the iterator.
1980  * @return Returns the key pointed to by the iterator.
1981  * @throws UndefinedIteratorValue Raised when the iterator does not point
1982  * to a valid hash table element
1983  */
1984  const key_type& key() const;
1985 
1986  ///
1987  /**
1988  * @brief Returns the mapped value pointed to by the iterator.
1989  * @return Returns the mapped value pointed to by the iterator.
1990  * @throws UndefinedIteratorValue Raised when the iterator does not point
1991  * to a valid hash table element.
1992  */
1993  const mapped_type& val() const;
1994 
1995  /**
1996  * @brief Makes the iterator point toward nothing (in particular, it is not
1997  * related anymore to its current hash table).
1998  *
1999  * It is mainly used by the hashtable when the latter is deleted while the
2000  * iterator is still alive.
2001  */
2002  void clear() noexcept;
2003 
2004  /// @}
2005  // ============================================================================
2006  /// @name Operators
2007  // ============================================================================
2008  /// @{
2009 
2010  /**
2011  * @brief Copy operator.
2012  * @param from The gum::HashTableConstIteratorSafe to copy.
2013  * @return Returns this gum::HashTableConstIteratorSafe.
2014  */
2015  HashTableConstIteratorSafe< Key, Val >&
2016  operator=(const HashTableConstIteratorSafe< Key, Val >& from);
2017 
2018  /**
2019  * @brief Copy operator.
2020  * @param from The gum::HashTableConstIterator to copy.
2021  * @return Returns this gum::HashTableConstIteratorSafe.
2022  */
2023  HashTableConstIteratorSafe< Key, Val >&
2024  operator=(const HashTableConstIterator< Key, Val >& from);
2025 
2026  /**
2027  * @brief Move operator.
2028  * @param from The gum::HashTableConstIteratorSafe to move.
2029  * @return Returns this gum::HashTableConstIteratorSafe.
2030  */
2031  HashTableConstIteratorSafe< Key, Val >&
2032  operator=(HashTableConstIteratorSafe< Key, Val >&& from) noexcept;
2033 
2034  /**
2035  * @brief Makes the iterator point to the next element in the hash table.
2036  *
2037  * @code
2038  * for (iter = hash.beginSafe(); iter != hash.endSafe (); ++iter) { }
2039  * @endcode
2040  *
2041  * The above loop is guaranteed to parse the whole hash table as long as no
2042  * element is added to or deleted from the hash table while being in the
2043  * loop. Deleting elements during the loop is guaranteed to never produce a
2044  * segmentation fault.
2045  *
2046  * @return Returns this gum::HashTableConstIteratorSafe pointing to the
2047  * next element in the gum::HashTable it's iterating over.
2048  */
2049  HashTableConstIteratorSafe< Key, Val >& operator++() noexcept;
2050 
2051  /**
2052  * @brief Makes the iterator point to i elements further in the hashtable.
2053  * @param i The number of steps to increment the
2054  * gum::HashTableConstIteratorSafe.
2055  * @return Returns this gum::HashTableConstIteratorSafe.
2056  */
2057  HashTableConstIteratorSafe< Key, Val >& operator+=(Size i) noexcept;
2058 
2059  /**
2060  * @brief Returns a new iterator poiting to i elements further in the
2061  * hashtable.
2062  * @param i The number of steps to increment the
2063  * gum::HashTableConstIteratorSafe.
2064  * @return Returns a new gum::HashTableConstIteratorSafe.
2065  */
2066  HashTableConstIteratorSafe< Key, Val > operator+(Size i) const;
2067 
2068  /**
2069  * @brief Checks whether two iterators are not equal.
2070  * @param from from The iterator to test for inequality.
2071  * @return Returns true if from and this iterator are inequal.
2072  */
2073  bool operator!=(const HashTableConstIteratorSafe< Key, Val >& from) const noexcept;
2074 
2075  /**
2076  * @brief Checks whether two iterators are equal.
2077  * @param from from The iterator to test for equality.
2078  * @return Returns true if from and this iterator are equal.
2079  */
2080  bool operator==(const HashTableConstIteratorSafe< Key, Val >& from) const noexcept;
2081 
2082  /**
2083  * @brief Returns the element pointed to by the iterator.
2084  * @return Returns the element pointed to by the iterator.
2085  * @throws UndefinedIteratorValue Raised when the iterator does not point
2086  * to a valid hash table element.
2087  */
2088  const value_type& operator*() const;
2089 
2090  /// @}
2091 
2092  protected:
2093  /**
2094  * Class HashTable must be a friend because it stores iterator end and this
2095  * can be properly initialized only when the hashtable has been fully
2096  * allocated. Thus, proper initialization can only take place within the
2097  * constructor's code of the hashtable.
2098  */
2099  template < typename K, typename V, typename A >
2100  friend class HashTable;
2101 
2102  /// The hash table the iterator is pointing to.
2103  const HashTable< Key, Val >* _table_{nullptr};
2104 
2105  /**
2106  * @brief the index of the chained list pointed to by the iterator in the
2107  * array _nodes_ of the hash table.
2108  */
2109  Size _index_{Size(0)};
2110 
2111  /// The bucket in the chained list pointed to by the iterator.
2112  HashTableBucket< Key, Val >* _bucket_{nullptr};
2113 
2114  /**
2115  * @brief the bucket we should start from when we decide to do a ++.
2116  *
2117  * Usually it should be equal to nullptr. However, if the user has deleted
2118  * the object pointed to by bucket, this will point to another bucket. When
2119  * it is equal to nullptr, it means that the bucket reached after a ++
2120  * belongs to another slot of the hash table's ' __node' vector.
2121  */
2122  HashTableBucket< Key, Val >* _next_bucket_{nullptr};
2123 
2124  /// Returns the current iterator's bucket.
2125  HashTableBucket< Key, Val >* _getBucket_() const noexcept;
2126 
2127  /**
2128  * @brief Returns the index in the hashtable's node vector pointed to by
2129  * the iterator.
2130  * @return Returns the index in the hashtable's node vector pointed to by
2131  * the iterator.
2132  */
2133  Size _getIndex_() const noexcept;
2134 
2135  /**
2136  * @brief Removes the iterator from its hashtable' safe iterators list.
2137  */
2138  void _removeFromSafeList_() const;
2139 
2140  /**
2141  * @brief Insert the iterator into the hashtable's list of safe iterators.
2142  */
2143  void _insertIntoSafeList_() const;
2144  };
2145 
2146  // ===========================================================================
2147  // === HASH TABLES ITERATORS ===
2148  // ===========================================================================
2149 
2150  /**
2151  * @class HashTableIteratorSafe
2152  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
2153  * @brief Safe Iterators for hashtables.
2154  * @ingroup hashtable_group
2155  *
2156  * HashTableIteratorSafe provides a safe way to parse HashTables. They are
2157  * safe because they are kept informed by the hashtable they belong to of the
2158  * elements deleted by the user. Hence, even if the user removes an element
2159  * pointed to by a HashTableIteratorSafe, using the latter to access this
2160  * element will never crash the application. Instead it will properly throw
2161  * an UndefinedIteratorValue exception.
2162  *
2163  * Developers may consider using HashTable<x,y>::iterator_safe instead of
2164  * HashTableIteratorSafe<x,y>.
2165  *
2166  * @par Usage example:
2167  * @code
2168  * // creation of a hash table with 10 elements
2169  * HashTable<int,string> table;
2170  * for (int i = 0; i< 10; ++i)
2171  * table.insert (i,"xxx" + string (i,'x'));
2172  *
2173  * // parse the hash table
2174  * for (HashTable<int,string>::iterator_safe iter = table.beginSafe ();
2175  * iter != table.endSafe (); ++iter) {
2176  * // display the values
2177  * cerr << "at " << iter.key() << " value = " << iter.val () << endl;
2178  * HashTable<int,string>::value_type& elt = *iter;
2179  * std::pair<const int, string>& xelt = *iter;
2180  * }
2181  *
2182  * // check whether two iterators point toward the same element
2183  * HashTable<int,string>::iterator_safe iter1 = table1.beginSafe ();
2184  * HashTable<int,string>::iterator_safe iter2 = table1.endSafe ();
2185  * if (iter1 != iter) {
2186  * cerr << "iter1 and iter2 point toward different elements";
2187  * }
2188  *
2189  * // make iter1 point toward nothing
2190  * iter1.clear ();
2191  * @endcode
2192  *
2193  * @tparam Key The gum::HashTable key.
2194  * @tparam Val The gum::HashTable Value.
2195  */
2196  template < typename Key, typename Val >
2197  class HashTableIteratorSafe: public HashTableConstIteratorSafe< Key, Val > {
2198  public:
2199  /// Types for STL compliance.
2200  /// @{
2201  using iterator_category = std::forward_iterator_tag;
2202  using key_type = Key;
2203  using mapped_type = Val;
2204  using value_type = std::pair< const Key, Val >;
2205  using reference = value_type&;
2206  using const_reference = const value_type&;
2207  using pointer = value_type*;
2208  using const_pointer = const value_type*;
2209  using difference_type = std::ptrdiff_t;
2210  /// @}
2211 
2212  // ============================================================================
2213  /// @name Constructors / Destructors
2214  // ============================================================================
2215  /// @{
2216 
2217  /**
2218  * @brief Basic constructor: creates an iterator pointing to nothing.
2219  */
2220  HashTableIteratorSafe();
2221 
2222  /**
2223  * @brief Constructor for an iterator pointing to the first element of a
2224  * hashtable.
2225  * @tparam Alloc The gum::HashTable allocator.
2226  */
2227  template < typename Alloc >
2228  HashTableIteratorSafe(const HashTable< Key, Val, Alloc >& tab);
2229 
2230  /**
2231  * @brief Constructor for an iterator pointing to the nth element of a
2232  * hashtable.
2233  *
2234  * The method runs in time linear to ind_elt.
2235  *
2236  * @param tab the hash table to which the so-called element belongs
2237  * @param ind_elt the position of the element in the hash table (0 means
2238  * the first element).
2239  * @tparam Alloc The gum::HashTable allocator.
2240  * @throw UndefinedIteratorValue Raised if the element cannot be found
2241  */
2242  template < typename Alloc >
2243  HashTableIteratorSafe(const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2244 
2245  /**
2246  * @brief Copy constructor.
2247  * @param from the gum::HashTableIteratorSafe to copy.
2248  * @return This gum::HashTableIteratorSafe.
2249  */
2250  HashTableIteratorSafe(const HashTableIteratorSafe< Key, Val >& from);
2251 
2252  /**
2253  * @brief Copy constructor.
2254  * @param from the gum::HashTableIterator to copy.
2255  * @return This gum::HashTableIteratorSafe.
2256  */
2257  explicit HashTableIteratorSafe(const HashTableIterator< Key, Val >& from);
2258 
2259  /**
2260  * @brief Move constructor.
2261  * @param from The gum::HashTableIteratorSafe to move.
2262  * @return Returns this gum::HashTableIteratorSafe.
2263  */
2264  HashTableIteratorSafe(HashTableIteratorSafe< Key, Val >&& from) noexcept;
2265 
2266  /**
2267  * @brief Class destructor.
2268  */
2269  ~HashTableIteratorSafe() noexcept;
2270 
2271  /// @}
2272  // ============================================================================
2273  /// @name Accessors / Modifiers
2274  // ============================================================================
2275  /// @{
2276 
2277  /// Usefull Alias
2278  /// @{
2279  using HashTableConstIteratorSafe< Key, Val >::key;
2280  using HashTableConstIteratorSafe< Key, Val >::val;
2281  using HashTableConstIteratorSafe< Key, Val >::clear;
2282  /// @}
2283 
2284  /**
2285  * @brief Returns the mapped value pointed to by the iterator.
2286  * @return Returns the mapped value pointed to by the iterator.
2287  * @throws UndefinedIteratorValue Raised when the iterator does not point
2288  * to a valid hash table element.
2289  */
2290  mapped_type& val();
2291 
2292  /// @}
2293  // ============================================================================
2294  /// @name Operators
2295  // ============================================================================
2296  /// @{
2297 
2298  /**
2299  * @brief Copy operator.
2300  * @param from The gum::HashTableIteratorSafe to copy.
2301  * @return Returns this gum::HashTableIterator.
2302  */
2303  HashTableIteratorSafe< Key, Val >& operator=(const HashTableIteratorSafe< Key, Val >& from);
2304 
2305  /**
2306  * @brief Copy operator.
2307  * @param from The gum::HashTableIterator to copy.
2308  * @return Returns this gum::HashTableIterator.
2309  */
2310  HashTableIteratorSafe< Key, Val >& operator=(const HashTableIterator< Key, Val >& from);
2311 
2312  /**
2313  * @brief Move operator.
2314  * @param from The gum::HashTableIteratorSafe to move.
2315  * @return Returns this gum::HashTableIterator.
2316  */
2317  HashTableIteratorSafe< Key, Val >& operator=(HashTableIteratorSafe< Key, Val >&& from) noexcept;
2318 
2319  /**
2320  * @brief Makes the iterator point to the next element in the hash table.
2321  *
2322  * @code
2323  * for (iter = hash.beginSafe (); iter != hash.endSafe (); ++iter) { }
2324  * @endcode
2325  *
2326  * The above loop is guaranteed to parse the whole hash table as long as no
2327  * element is added to or deleted from the hash table while being in the
2328  * loop. Deleting elements during the loop is guaranteed to never produce a
2329  * segmentation fault.
2330  *
2331  * @return This gum::HashTableIteratorSafe.
2332  */
2333  HashTableIteratorSafe< Key, Val >& operator++() noexcept;
2334 
2335  /**
2336  * @brief Makes the iterator point to i elements further in the hashtable.
2337  * @param i The number of increments.
2338  * @return Return this gum::HashTableIteratorSafe.
2339  */
2340  HashTableIteratorSafe< Key, Val >& operator+=(Size i) noexcept;
2341 
2342  /**
2343  * @brief Returns a new iterator pointing to i elements further in the
2344  * hashtable.
2345  * @param i The number of increments.
2346  * @return Returns this gum::HashTableIteratorSafe.
2347  */
2348  HashTableIteratorSafe< Key, Val > operator+(Size i) const;
2349 
2350  /**
2351  * @brief Checks whether two iterators are pointing toward different
2352  * elements.
2353  * @param from The gum::HashTableIteratorSafe to test for inequality.
2354  * @return Returns true if this and from are not equal.
2355  */
2356  bool operator!=(const HashTableIteratorSafe< Key, Val >& from) const noexcept;
2357 
2358  /**
2359  * @brief Checks whether two iterators are pointing toward equal
2360  * elements.
2361  * @param from The gum::HashTableIteratorSafe to test for equality.
2362  * @return Returns true if this and from are equal.
2363  */
2364  bool operator==(const HashTableIteratorSafe< Key, Val >& from) const noexcept;
2365 
2366  /**
2367  * @brief Returns the value pointed to by the iterator.
2368  * @return Returns the value pointed to by the iterator.
2369  * @throws UndefinedIteratorValue Raised when the iterator does not point
2370  * to a valid hash table element
2371  */
2372  value_type& operator*();
2373 
2374  /**
2375  * @brief Returns the value pointed to by the iterator.
2376  * @return Returns the value pointed to by the iterator.
2377  *
2378  * @throws UndefinedIteratorValue Raised when the iterator
2379  * does not point to a valid hash table element.
2380  */
2381  const value_type& operator*() const;
2382 
2383  /// @}
2384  };
2385 
2386  // ===========================================================================
2387  // === UNSAFE HASH TABLES CONST ITERATORS ===
2388  // ===========================================================================
2389 
2390  /**
2391  * @class HashTableConstIterator
2392  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
2393  * @brief Unsafe Const Iterators for hashtables
2394  * @ingroup hashtable_group
2395  *
2396  * HashTableConstIterator provides a fast but unsafe way to parse HashTables.
2397  * They should @b only be used when parsing hashtables in which no element is
2398  * removed from the hashtable. Removing an element where the iterator points
2399  * to will mess the iterator as it will most certainly point to an
2400  * unallocated memory. So, this kind of iterator should only be used when
2401  * parsing "(key) constant" hash tables, e.g., when we wish to display the
2402  * content of a hash table or when we wish to update the mapped values of
2403  * some elements of the hash table without ever modifying their keys.
2404  *
2405  * Developers may consider using HashTable<x,y>::const_iterator instead of
2406  * HashTableConstIterator<x,y>.
2407  *
2408  * @par Usage example:
2409  * @code
2410  * // creation of a hash table with 10 elements
2411  * HashTable<int,string> table;
2412  * for (int i = 0; i< 10; ++i)
2413  * table.insert (i,"xxx" + string (i,'x'));
2414  *
2415  * // parse the hash table
2416  * for (HashTable<int,string>::const_iterator iter = table.cbegin ();
2417  * iter != table.cend (); ++iter) {
2418  * // display the values
2419  * cerr << "at " << iter.key() << " value = " << iter.val () << endl;
2420  * const HashTable<int,string>::value_type& elt = *iter;
2421  * const std::pair<const int, string>& xelt = *iter;
2422  * }
2423  *
2424  * // check whether two iterators point toward the same element
2425  * HashTable<int,string>::const_iterator iter1 = table1.cbegin();
2426  * HashTable<int,string>::const_iterator iter2 = table1.cend();
2427  * if (iter1 != iter) {
2428  * cerr << "iter1 and iter2 point toward different elements";
2429  * }
2430  *
2431  * // make iter1 point toward nothing
2432  * iter1.clear ();
2433  * @endcode
2434  *
2435  * @tparam Key The gum::HashTable key.
2436  * @tparam Val The gum::HashTable Value.
2437  */
2438  template < typename Key, typename Val >
2439  class HashTableConstIterator {
2440  public:
2441  /// Types for STL compliance.
2442  /// @{
2443  using iterator_category = std::forward_iterator_tag;
2444  using key_type = Key;
2445  using mapped_type = Val;
2446  using value_type = std::pair< const Key, Val >;
2447  using reference = value_type&;
2448  using const_reference = const value_type&;
2449  using pointer = value_type*;
2450  using const_pointer = const value_type*;
2451  using difference_type = std::ptrdiff_t;
2452  /// @}
2453 
2454  // ============================================================================
2455  /// @name Constructors / Destructors
2456  // ============================================================================
2457  /// @{
2458 
2459  /**
2460  * @brief Basic constructor: creates an iterator pointing to nothing.
2461  */
2462  HashTableConstIterator() noexcept;
2463 
2464  /**
2465  * @brief Constructor for an iterator pointing to the first element of a
2466  * hashtable.
2467  * @param tab The gum::HashTable to iterate over.
2468  * @tparam Alloc The gum::HashTable allocator.
2469  */
2470  template < typename Alloc >
2471  HashTableConstIterator(const HashTable< Key, Val, Alloc >& tab) noexcept;
2472 
2473  /**
2474  * @brief Constructor for an iterator pointing to the nth element of a
2475  * hashtable.
2476  *
2477  * The method runs in time linear to ind_elt.
2478  *
2479  * @param tab The hash table to which the so-called element belongs.
2480  * @param ind_elt The position of the element in the hash table (0 means
2481  * the first element).
2482  * @throw UndefinedIteratorValue Raised if the element cannot be found.
2483  */
2484  template < typename Alloc >
2485  HashTableConstIterator(const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2486 
2487  /**
2488  * @brief Copy constructor.
2489  * @param from The gum::HashTableConstIterator to copy.
2490  */
2491  HashTableConstIterator(const HashTableConstIterator< Key, Val >& from) noexcept;
2492 
2493  /**
2494  * @brief Move constructor.
2495  * @param from The gum::HashTableConstIterator to move.
2496  */
2497  HashTableConstIterator(HashTableConstIterator< Key, Val >&& from) noexcept;
2498 
2499  /**
2500  * @brief Class destructor.
2501  */
2502  ~HashTableConstIterator() noexcept;
2503 
2504  /// @}
2505  // ============================================================================
2506  /// @name Accessors / Modifiers
2507  // ============================================================================
2508  /// @{
2509 
2510  /**
2511  * @brief Returns the key corresponding to the element pointed to by the
2512  * iterator.
2513  *
2514  * @warning Using this method on an iterator that points to an element that
2515  * has been deleted will most certainly result in a segfault. If unsure,
2516  * use a safe iterator instead of an unsafe one.
2517  *
2518  * @return Returns the key corresponding to the element pointed to by the
2519  * iterator.
2520  */
2521  const key_type& key() const;
2522 
2523  /**
2524  * @brief Returns the mapped value pointed to by the iterator.
2525  *
2526  * @warning Using this method on an iterator that points to an element that
2527  * has been deleted will most certainly result in a segfault. If unsure, use
2528  * a safe iterator instead of an unsafe one.
2529  *
2530  * @return Returns the mapped value pointed to by the iterator.
2531  */
2532  const mapped_type& val() const;
2533 
2534  /**
2535  * @brief Makes the iterator point toward nothing (in particular, it is not
2536  * related anymore to its current hash table).
2537  */
2538  void clear() noexcept;
2539 
2540  /// @}
2541  // ============================================================================
2542  /// @name Operators
2543  // ============================================================================
2544  /// @{
2545 
2546  /**
2547  * @brief Copy operator.
2548  * @param from The gum::HashTableConstIterator to copy.
2549  * @return Returns this gum::HashTableConstIterator.
2550  */
2551  HashTableConstIterator< Key, Val >&
2552  operator=(const HashTableConstIterator< Key, Val >& from) noexcept;
2553 
2554  /**
2555  * @brief Move operator.
2556  * @param from The gum::HashTableConstIterator to move.
2557  * @return Returns this gum::HashTableConstIterator.
2558  */
2559  HashTableConstIterator< Key, Val >&
2560  operator=(HashTableConstIterator< Key, Val >&& from) noexcept;
2561 
2562  ///
2563  /**
2564  * @brief Makes the iterator point to the next element in the hash table.
2565  *
2566  * @code
2567  * for (iter = cbegin (); iter != cend(); ++iter ) { }
2568  * @endcode
2569  *
2570  * The above loop is guaranteed to parse the whole hash table as long as no
2571  * element is added to or deleted from the hash table while being in the
2572  * loop.
2573  *
2574  * @warning performing a ++ on an iterator that points to an element that
2575  * has been deleted will most certainly result in a segfault.
2576  *
2577  * @return Returns this gum::HashTableConstIterator.
2578  */
2579  HashTableConstIterator< Key, Val >& operator++() noexcept;
2580 
2581  /**
2582  * @brief Makes the iterator point to i elements further in the hashtable.
2583  * @param i The number of increments.
2584  * @return Returns this gum::HashTableConstIterator.
2585  */
2586  HashTableConstIterator< Key, Val >& operator+=(Size i) noexcept;
2587 
2588  /**
2589  * @brief Returns a new iterator pointing to i elements further in the
2590  * hashtable.
2591  * @param i The number of increments.
2592  * @return Returns a new iterator pointing to i elements further in the
2593  * hashtable.
2594  */
2595  HashTableConstIterator< Key, Val > operator+(Size i) const noexcept;
2596 
2597  /**
2598  * @brief Checks whether two iterators are pointing toward different
2599  * elements.
2600  * @param from The gum::HashTableConstIterator to test for inequality.
2601  * @return Returns true if this and from are not equal.
2602  */
2603  bool operator!=(const HashTableConstIterator< Key, Val >& from) const noexcept;
2604 
2605  /**
2606  * @brief Checks whether two iterators are pointing toward equal
2607  * elements.
2608  * @param from The gum::HashTableConstIterator to test for equality.
2609  * @return Returns true if this and from are equal.
2610  */
2611  bool operator==(const HashTableConstIterator< Key, Val >& from) const noexcept;
2612 
2613 
2614  /**
2615  * @brief Returns the value pointed to by the iterator.
2616  *
2617  * @warning using this method on an iterator that points to an element that
2618  * has been deleted will most certainly result in a segfault. If unsure,
2619  * use a safe iterator instead of an unsafe one.
2620  *
2621  * @return Returns the value pointed to by the iterator.
2622  */
2623  const value_type& operator*() const;
2624 
2625  /// @}
2626 
2627  protected:
2628  /**
2629  * Class HashTable must be a friend because it stores iterator end and this
2630  * one can be properly initialized only when the hashtable has been fully
2631  * allocated. Thus, proper initialization can only take place within the
2632  * constructor's code of the hashtable.
2633  *
2634  * @tparam K The gum::HashTable keys type.
2635  * @tparam V The gum::HashTable values type.
2636  * @tparam A The gum::HashTable allocator.
2637  */
2638  template < typename K, typename V, typename A >
2639  friend class HashTable;
2640 
2641  /// For the safe copy constructor and operator.
2642  friend class HashTableConstIteratorSafe< Key, Val >;
2643 
2644  /// The hash table the iterator is pointing to.
2645  const HashTable< Key, Val >* _table_{nullptr};
2646 
2647  /**
2648  * @brief The index of the chained list pointed by the iterator in the
2649  * array of nodes of the hash table.
2650  */
2651  Size _index_{Size(0)};
2652 
2653  /// The bucket in the chained list pointed to by the iterator.
2654  typename HashTable< Key, Val >::Bucket* _bucket_{nullptr};
2655 
2656  /**
2657  * @brief Returns the current iterator's bucket.
2658  * @return Returns the current iterator's bucket.
2659  */
2660  typename HashTable< Key, Val >::Bucket* _getBucket_() const noexcept;
2661 
2662  /**
2663  * @brief Returns the index in the hashtable's node vector pointed to by
2664  * the iterator.
2665  * @return Returns the index in the hashtable's node vector pointed to by
2666  * the iterator.
2667  */
2668  Size _getIndex_() const noexcept;
2669  };
2670 
2671  // ===========================================================================
2672  // === UNSAFE HASH TABLES ITERATORS ===
2673  // ===========================================================================
2674 
2675  /**
2676  * @class HashTableIterator
2677  * @headerfile hashTable.h <agrum/tools/core/hashTable.h>
2678  * @brief Unsafe Iterators for hashtables
2679  * @ingroup hashtable_group
2680  *
2681  * HashTableIterator provides a fast but unsafe way to parse HashTables.
2682  * They should @b only be used when parsing hashtables in which no element is
2683  * removed from the hashtable. Removing an element where the iterator points
2684  * to will mess the iterator as it will most certainly point to an
2685  * unallocated memory. So, this kind of iterator should only be used when
2686  * parsing "(key) constant" hash tables, e.g., when we wish to display the
2687  * content of a hash table or when we wish to update the mapped values of
2688  * some elements of the hash table without ever modifying their keys.
2689  *
2690  * Developers may consider using HashTable<x,y>::iterator instead of
2691  * HashTableIterator<x,y>.
2692  * @par Usage example:
2693  * @code
2694  * // creation of a hash table with 10 elements
2695  * HashTable<int,string> table;
2696  * for (int i = 0; i< 10; ++i)
2697  * table.insert (i,"xxx" + string (i,'x'));
2698  *
2699  * // parse the hash table
2700  * for (HashTable<int,string>::iterator iter = table.begin ();
2701  * iter != table.end (); ++iter) {
2702  * // display the values
2703  * cerr << "at " << iter.key() << " value = " << iter.val () << endl;
2704  * HashTable<int,string>::value_type& elt = *iter;
2705  * std::pair<const int, string>& xelt = *iter;
2706  * }
2707  *
2708  * // check whether two iterators point toward the same element
2709  * HashTable<int,string>::iterator iter1 = table1.begin();
2710  * HashTable<int,string>::iterator iter2 = table1.end();
2711  * if (iter1 != iter) {
2712  * cerr << "iter1 and iter2 point toward different elements";
2713  * }
2714  *
2715  * // make iter1 point toward nothing
2716  * iter1.clear ();
2717  * @endcode
2718  *
2719  * @tparam Key The gum::HashTable key.
2720  * @tparam Val The gum::HashTable Value.
2721  */
2722  template < typename Key, typename Val >
2723  class HashTableIterator: public HashTableConstIterator< Key, Val > {
2724  public:
2725  /// types for STL compliance
2726  /// @{
2727  using iterator_category = std::forward_iterator_tag;
2728  using key_type = Key;
2729  using mapped_type = Val;
2730  using value_type = std::pair< const Key, Val >;
2731  using reference = value_type&;
2732  using const_reference = const value_type&;
2733  using pointer = value_type*;
2734  using const_pointer = const value_type*;
2735  using difference_type = std::ptrdiff_t;
2736  /// @}
2737 
2738  // ############################################################################
2739  /// @name Constructors / Destructors
2740  // ############################################################################
2741  /// @{
2742 
2743  /**
2744  * @brief Basic constructor: creates an iterator pointing to nothing.
2745  */
2746  HashTableIterator() noexcept;
2747 
2748  /**
2749  * @brief Constructor for an iterator pointing to the first element of a
2750  * hashtable.
2751  * @tparam Alloc The gum::HashTable allocator.
2752  * @param tab The gum::HashTable to iterate over.
2753  */
2754  template < typename Alloc >
2755  HashTableIterator(const HashTable< Key, Val, Alloc >& tab) noexcept;
2756 
2757  ///
2758  /**
2759  * @brief Constructor for an iterator pointing to the nth element of a
2760  * hashtable.
2761  *
2762  * The method runs in time linear to ind_elt.
2763  *
2764  * @tparam Alloc The gum::HashTable allocator.
2765  * @param tab The hash table to which the so-called element belongs.
2766  * @param ind_elt The position of the element in the hash table (0 means
2767  * the first element).
2768  * @throw UndefinedIteratorValue Raised if the element cannot be found.
2769  */
2770  template < typename Alloc >
2771  HashTableIterator(const HashTable< Key, Val, Alloc >& tab, Size ind_elt);
2772 
2773  /**
2774  * @brief Copy constructor.
2775  * @param from The gum::HashTableIterator to copy.
2776  */
2777  HashTableIterator(const HashTableIterator< Key, Val >& from) noexcept;
2778 
2779  /**
2780  * @brief Move constructor.
2781  * @param from The gum::HashTableIterator to move.
2782  */
2783  HashTableIterator(HashTableIterator< Key, Val >&& from) noexcept;
2784 
2785  /**
2786  * @brief Class destructor.
2787  */
2788  ~HashTableIterator() noexcept;
2789 
2790  /// @}
2791  // ============================================================================
2792  /// @name Accessors / Modifiers
2793  // ============================================================================
2794  /// @{
2795 
2796  /// Usefull alias.
2797  /// @{
2798  using HashTableConstIterator< Key, Val >::key;
2799  using HashTableConstIterator< Key, Val >::val;
2800  using HashTableConstIterator< Key, Val >::clear;
2801  /// @}
2802 
2803  /**
2804  * @brief Returns the mapped value pointed to by the iterator.
2805  *
2806  * @warning using this method on an iterator that points to an element that
2807  * has been deleted will most certainly result in a segfault. If unsure,
2808  * use a safe iterator instead of an unsafe one.
2809  *
2810  * @return Returns the mapped value pointed to by the iterator.
2811  */
2812  mapped_type& val();
2813 
2814  /// @}
2815  // ============================================================================
2816  /// @name Operators
2817  // ============================================================================
2818  /// @{
2819 
2820  /**
2821  * @brief Copy operator.
2822  * @param from The gum::HashTableIterator to copy.
2823  * @return Returns this gum::HashTableIterator.
2824  */
2825  HashTableIterator< Key, Val >& operator=(const HashTableIterator< Key, Val >& from) noexcept;
2826 
2827  /**
2828  * @brief Move operator.
2829  * @param from The gum::HashTableIterator to move.
2830  * @return Returns this gum::HashTableIterator.
2831  */
2832  HashTableIterator< Key, Val >& operator=(HashTableIterator< Key, Val >&& from) noexcept;
2833 
2834  /**
2835  * @brief Makes the iterator point to the next element in the hash table.
2836  *
2837  * @code
2838  * for (iter = begin(); iter != end(); ++iter) { }
2839  * @endcode
2840  *
2841  * The above loop is guaranteed to parse the whole hash table as long as no
2842  * element is added to or deleted from the hash table while being in the
2843  * loop.
2844  *
2845  * @warning performing a ++ on an iterator that points to an element that
2846  * has been deleted will most certainly result in a segfault.
2847  *
2848  * @return Returns this gum::HashTableIterator.
2849  */
2850  HashTableIterator< Key, Val >& operator++() noexcept;
2851 
2852  /**
2853  * @brief Makes the iterator point to i elements further in the hashtable.
2854  * @param i The number of increments.
2855  * @return Returns this gum::HashTableIterator.
2856  */
2857  HashTableIterator< Key, Val >& operator+=(Size i) noexcept;
2858 
2859  /**
2860  * @brief Returns a new iterator.
2861  * @param i The number of increments.
2862  * @return Returns this gum::HashTableIterator.
2863  */
2864  HashTableIterator< Key, Val > operator+(Size i) const noexcept;
2865 
2866  /**
2867  * @brief Checks whether two iterators are pointing toward different
2868  * elements.
2869  * @param from The gum::HashTableIterator to test for inequality.
2870  * @return Returns true if this and from are not equal.
2871  */
2872  bool operator!=(const HashTableIterator< Key, Val >& from) const noexcept;
2873 
2874  /**
2875  * @brief Checks whether two iterators are pointing toward equal
2876  * elements.
2877  * @param from The gum::HashTableIterator to test for equality.
2878  * @return Returns true if this and from are equal.
2879  */
2880  bool operator==(const HashTableIterator< Key, Val >& from) const noexcept;
2881 
2882  /**
2883  * @brief Returns the value pointed to by the iterator.
2884  *
2885  * @warning using this method on an iterator that points to an element that
2886  * has been deleted will most certainly result in a segfault. If unsure,
2887  * use a safe iterator instead of an unsafe one.
2888  *
2889  * @return Returns the value pointed to by the iterator.
2890  */
2891  value_type& operator*();
2892 
2893  /**
2894  * @brief Returns the value pointed to by the iterator.
2895  *
2896  * @warning using this method on an iterator that points to an element that
2897  * has been deleted will most certainly result in a segfault. If unsure,
2898  * use a safe iterator instead of an unsafe one.
2899  *
2900  * @return Returns the value pointed to by the iterator.
2901  */
2902  const value_type& operator*() const;
2903 
2904  /// @}
2905  };
2906 
2907 } // namespace gum
2908 
2909 
2910 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2911 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2912 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2913 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2914 extern template class gum::HashTable< int, int >;
2915 # endif
2916 # endif
2917 # endif
2918 #endif
2919 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2920 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2921 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2922 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2923 extern template class gum::HashTable< int, std::string >;
2924 # endif
2925 # endif
2926 # endif
2927 #endif
2928 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2929 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2930 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2931 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2932 extern template class gum::HashTable< std::string, std::string >;
2933 # endif
2934 # endif
2935 # endif
2936 #endif
2937 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2938 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2939 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2940 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
2941 extern template class gum::HashTable< std::string, int >;
2942 # endif
2943 # endif
2944 # endif
2945 #endif
2946 
2947 
2948 // always include the implementation of the templates
2949 #include <agrum/tools/core/hashTable_tpl.h>
2950 
2951 #endif // GUM_HASHTABLE_H