Flow 2.0.0
Flow project: Full implementation reference.
linked_hash_set.hpp
Go to the documentation of this file.
1/* Flow
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19#pragma once
20
23#include <cstddef>
24
25namespace flow::util
26{
27
28/**
29 * An object of this class is a map that combines the lookup speed of an `unordered_set<>` and ordering and
30 * iterator stability capabilities of a `list<>`.
31 *
32 * This is just like Linked_hash_map, except it only stores keys -- no mapped values. All comments, except for
33 * self-explanatory differences, from Linked_hash_map apply here. Thus I will only speak of differences below to
34 * avoid duplication of this header. Incidentally the most visible API difference (aside from having no `Mapped`s
35 * to speak of, only `Key`s) is that Linked_hash_set lacks `(*this)[]` operator; so one always uses insert() to
36 * insert.
37 *
38 * Move semantics for keys are supported (let `x` be a `*this`):
39 * - `x.insert(std::move(a_key))`;
40 * - `x.insert(Key{...})`.
41 *
42 * The iterators are, really, `list<Key>` const-iterators; and as such are not invalidated except
43 * due to direct erasure of a given pointee.
44 *
45 * @internal
46 * ### Impl notes ###
47 * It's very much like Linked_hash_map; just the `list` #m_value_list stores only `Key`s as opposed to
48 * `pair<const Key, Mapped>`s. See Linked_hash_map.
49 * @endinternal
50 *
51 * @tparam Key_t
52 * Key type. Same as for Linked_hash_map.
53 * @tparam Hash_t
54 * Hasher type. Same as for Linked_hash_map.
55 * @tparam Pred_t
56 * Equality functor type. Same as for Linked_hash_map.
57 */
58template<typename Key_t, typename Hash_t, typename Pred_t>
60{
61public:
62 // Types.
63
64 /// Convenience alias for template arg.
65 using Key = Key_t;
66
67 /// Convenience alias for template arg.
68 using Hash = Hash_t;
69
70 /// Convenience alias for template arg.
71 using Pred = Pred_t;
72
73 /// Short-hand for values, which in this case are simply the keys.
74 using Value = Key;
75
76private:
77 // Types. These are here in the middle of public block due to inability to forward-declare aliases.
78
79 /// Short-hand for doubly linked list of `Key`s.
80 using Value_list = std::list<Value>;
81
82public:
83
84 // Types (continued).
85
86 /// Expresses sizes/lengths of relevant things.
87 using size_type = std::size_t;
88 /// Type for difference of `size_type`s.
89 using difference_type = std::ptrdiff_t;
90
91 /// Type for iterator pointing into an immutable structure of this type.
92 using Const_iterator = typename Value_list::const_iterator;
93
94 /**
95 * Type for iterator pointing into a mutable structure of this type but actually that is not possible;
96 * so alias to #Const_iterator. Note these are standard semantics (see `std::set`, etc.).
97 */
99
100 /// Type for reverse iterator pointing into an immutable structure of this type.
101 using Const_reverse_iterator = typename Value_list::const_reverse_iterator;
102
103 /**
104 * Type for reverse iterator pointing into a mutable structure of this type but actually that is not possible;
105 * so alias to #Const_reverse_iterator. Note these are standard semantics (see `std::set`, etc.).
106 */
108
109 /// For container compliance (hence the irregular capitalization): #Key type.
110 using key_type = Key;
111 /// For container compliance (hence the irregular capitalization): #Value type.
113 /// For container compliance (hence the irregular capitalization): #Hash type.
114 using hasher = Hash;
115 /// For container compliance (hence the irregular capitalization): #Pred type.
117 /// For container compliance (hence the irregular capitalization): pointer to #Key type.
118 using pointer = Value*;
119 /// For container compliance (hence the irregular capitalization): pointer to `const Key` type.
120 using const_pointer = const Value*;
121 /// For container compliance (hence the irregular capitalization): reference to #Key type.
122 using reference = Value&;
123 /// For container compliance (hence the irregular capitalization): reference to `const Key` type.
124 using const_reference = const Value&;
125 /// For container compliance (hence the irregular capitalization): `Iterator` type.
127 /// For container compliance (hence the irregular capitalization): `Const_iterator` type.
129
130 // Constructors/destructor.
131
132 /**
133 * Constructs empty structure with some basic parameters.
134 *
135 * @param n_buckets
136 * Number of buckets for the unordered (hash) table. Special value -1 (default) will cause us to use
137 * whatever `unordered_set<>` would use by default.
138 * @param hasher_obj
139 * Instance of the hash function type (`hasher_obj(k) -> size_t` should be hash of `Key k`).
140 * @param pred
141 * Instance of the equality function type (`pred(k1, k2)` should return `true` if and
142 * only if the `Key`s are equal by value).
143 */
145 const Hash& hasher_obj = Hash{},
146 const Pred& pred = Pred{});
147
148 /**
149 * Constructs structure with some basic parameters, and values initialized from initializer list.
150 * The values are inserted as if `insert(v)` was called for each element `v` in `values`
151 * **in reverse order**. Since the canonical ordering places the *newest* (last inserted/`touch()`ed)
152 * element at the *front* of the ordering, that means that forward iteration through the set (right after this
153 * constructor runs) will yield values in the *same* order as in initializer list `values`.
154 *
155 * @param values
156 * Values with which to fill the structure after initializing it.
157 * Typically you'd provide a series of keys like this:
158 * `{ key1, key2, ... }`. They will appear in iterated sequence in the same order as
159 * they appear in this list.
160 * @param n_buckets
161 * See other constructor.
162 * @param hasher_obj
163 * See other constructor.
164 * @param pred
165 * See other constructor.
166 */
167 explicit Linked_hash_set(std::initializer_list<Value> values,
168 size_type n_buckets = size_type(-1),
169 const Hash& hasher_obj = Hash{},
170 const Pred& pred = Pred{});
171
172 /**
173 * Constructs object that is a copy of the given source. Equivalent to default-ction followed by `operator=(src)`.
174 *
175 * @param src
176 * Source object.
177 */
179
180 /**
181 * Constructs object by making it equal to the given source, while the given source becomes as-if default-cted.
182 * Equivalent to default-ction followed by `operator=(std::move(src))`.
183 *
184 * This is a constant-time operation.
185 *
186 * @param src
187 * Source object which is emptied.
188 */
190
191 // Methods.
192
193 /**
194 * Overwrites this object with a copy of the given source. We become equal to `src` but independent of it to a
195 * common-sense extent. In addition, the hasher instance and equality predicate are copied from `src`. Finally, a
196 * reasonable attempt is made to also make the internal structure of the hash map to be similar to that of `src.
197 *
198 * @param src
199 * Source object. No-op if `this == &src`.
200 * @return `*this`.
201 */
203
204 /**
205 * Overwrites this object making it identical to the given source, while the given source becomes as-if default-cted.
206 *
207 * This is a constant-time operation, plus whatever is the cost of `this->clear()` (linear in pre-op `.size()`).
208 *
209 * @param src
210 * Source object which is emptied; except no-op if `this == &src`.
211 * @return `*this`.
212 */
214
215 /**
216 * Swaps the contents of this structure and `other`. This is a constant-time operation, as internal
217 * representations are swapped instead of any copy-assignment.
218 *
219 * @see The `swap()` free function.
220 * It is generally best (equivalent but covers more generic cases) to use the ADL-enabled `swap(a, b)`
221 * pattern instead of this member function. That is: `using std::swap; ...; swap(a, b);`.
222 * (Details are outside our scope here; but in short ADL will cause the right thing to happen.)
223 *
224 * @param other
225 * The other structure.
226 */
227 void swap(Linked_hash_set& other);
228
229 /**
230 * Attempts to insert (copying it) the given keyinto the map; if key
231 * already in `*this` makes no change. See also the overload which can avoid a copy and destructively move
232 * the key instead.
233 *
234 * Return value indicates various info of interest about what occurred or did not occur.
235 * If inserted, the new element is considered "newest," as if by touch(). If not inserted, the existing element
236 * location is not affected (use touch() upon consulting the return value, if this is desirable).
237 *
238 * @param key
239 * The key to attempt to insert. A copy of this value is placed in `*this`.
240 * @return A pair whose second element is true if and only if the insertion occurred; and whose first element
241 * is an iterator pointing to either the newly inserted element or already present one with a key equal to
242 * `key`.
243 */
244 std::pair<Iterator, bool> insert(const Key& key);
245
246 /**
247 * Identical to the other overload, except that (if key not already present in `*this`) the key
248 * is moved, not copied, into `*this`.
249 *
250 * @param key
251 * The key to attempt to insert (it is moved-from, if insertion occurs).
252 * @return See other overload.
253 */
254 std::pair<Iterator, bool> insert(Key&& key);
255
256 /**
257 * Attempts to find value at the given key in the map. Key presence is determined identically to how it would be
258 * done in an `unordered_set<Key_t, Hash_t, Pred_t>`, with the particular #Hash and #Pred instances given to ctor
259 * (typically their default-cted instances, typically occupying no memory).
260 *
261 * The returned iterator (if valid) *cannot* be used to mutate the key inside the map.
262 *
263 * @param key
264 * Key whose equal to find.
265 * @return If found, iterator to the key/mapped-value pair with the equivalent key; else `this->end()`.
266 */
267 Const_iterator find(const Key& key) const;
268
269 /**
270 * Returns the number of times a key equal to the given one is present (as-if via find()) in the map: either 1 or 0.
271 *
272 * @param key
273 * Key whose equal to find.
274 * @return 0 or 1.
275 */
276 size_type count(const Key& key) const;
277
278 /**
279 * Given a valid iterator into the structure, makes the pointed-to element "newest" by moving it from wherever it
280 * is to be first in the iteration order. Behavior undefined if iterator invalid.
281 *
282 * The iterator continues to be valid.
283 *
284 * @param it
285 * Iterator to an element of the structure.
286 */
287 void touch(const Const_iterator& it);
288
289 /**
290 * Given a key into the structure, makes the corresponding element "newest" by moving it from wherever it
291 * is to be first in the iteration order; or does nothing if no such key. `find(key)` equivalent is performed
292 * first. Return value indicates whether it was found.
293 *
294 * @param key
295 * Key whose equal to find.
296 * @return `true` if the key was found (even if it was already "newest"); `false` if not found.
297 */
298 bool touch(const Key& key);
299
300 /**
301 * Erases the element pointed to by the given valid iterator. Behavior undefined if it is not valid. `it` becomes
302 * invalid.
303 *
304 * @param it
305 * Iterator of element to erase.
306 * @return Iterator one position past (i.e., "older") than `it`, before `*it` was removed.
307 */
309
310 /**
311 * Erases all elements in the range [`it_newest`, `it_past_oldest`). Behavior undefined if a given iterator is
312 * invalid, or if the range is invalid. Corner case: an empty range is allowed; then this no-ops. Unless no-op,
313 * `it_newest` becomes invalid.
314 *
315 * @param it_newest
316 * Iterator of first ("newest") element to erase.
317 * @param it_past_oldest
318 * Iterator of one past last ("oldest") element to erase.
319 * @return `it_past_oldest` copy.
320 */
321 Const_iterator erase(const Const_iterator& it_newest, const Const_iterator& it_past_oldest);
322
323 /**
324 * Erases the element with the given key, if it exists. `find(key)` equivalent is performed
325 * first. Return value indicates whether it existed.
326 *
327 * @param key
328 * Key such that its equal's (if found) element will be erased.
329 * @return Number of elements erased (0 or 1).
330 */
331 size_type erase(const Key& key);
332
333 /// Makes it so that `size() == 0`.
334 void clear();
335
336 /**
337 * Synonym of newest().
338 * @return See newest().
339 */
341
342 /**
343 * Returns first, a/k/a "newest," element's iterator (to immutable element, due to nature of this type).
344 * @return Ditto.
345 */
347
348 /**
349 * Synonym of past_oldest(). Exists as standard container method.
350 * @return See past_oldest().
351 */
352 Iterator end() const;
353
354 /**
355 * Returns one past last, a/k/a "oldest," element's iterator (to immutable element, due to nature of this type).
356 * @return Ditto.
357 */
359
360 /**
361 * Synonym of const_newest(). Exists as standard container method (hence the odd formatting).
362 * @return See const_newest().
363 */
365
366 /**
367 * Returns first, a/k/a "newest," element's iterator (to immutable element).
368 * @return Ditto.
369 */
371
372 /**
373 * Synonym of const_past_oldest(). Exists as standard container method (hence the odd formatting).
374 * @return See const_past_oldest().
375 */
377
378 /**
379 * Returns one past last, a/k/a "oldest," element's iterator (to immutable element).
380 * @return Ditto.
381 */
383
384 /**
385 * Synonym of oldest().
386 * @return See oldest().
387 */
389
390 /**
391 * Returns first, a/k/a "oldest," element's reverse iterator (to immutable element, due to nature of this type).
392 * @return Ditto.
393 */
395
396 /**
397 * Synonym of past_newest(). Exists as standard container method.
398 * @return See past_newest().
399 */
401
402 /**
403 * Returns one past last, a/k/a "newest," element's reverse iterator (to immutable element, due
404 * to nature of this type).
405 * @return Ditto.
406 */
408
409 /**
410 * Synonym of const_oldest().
411 * @return See const_oldest().
412 */
414
415 /**
416 * Returns first, a/k/a "oldest," element's reverse iterator (to immutable element).
417 * @return Ditto.
418 */
420
421 /**
422 * Synonym of const_past_newest(). Exists as standard container method.
423 * @return See const_past_newest().
424 */
426
427 /**
428 * Returns one past last, a/k/a "newest," element's reverse iterator (to immutable element).
429 * @return Ditto.
430 */
432
433 /**
434 * Returns true if and only if container is empty. Same performance as of `unordered_set<>`.
435 * @return Ditto.
436 */
437 bool empty() const;
438
439 /**
440 * Returns number of elements stored. Same performance as of `unordered_set<>.`
441 * @return Ditto.
442 */
444
445 /**
446 * Returns max number of elements that can be stored. Same performance as of `unordered_set<>` + `list<>`.
447 * @return Ditto.
448 */
450
451private:
452
453 // Data.
454
455 /// Analogous to Linked_hash_map::m_value_list; but simpler in that it just stores `Key`s, not pairs of (stuff).
457
458 /**
459 * Analogous to Linked_hash_map::m_value_iter_set; just configured to generate a simpler `.iter()` off each element
460 * by supplying `false` instead of `true` for the last template arg.
461 */
463}; // class Linked_hash_set
464
465// Free functions: in *_fwd.hpp.
466
467// Template implementations.
468
469template<typename Key_t, typename Hash_t, typename Pred_t>
471 const Hash& hasher_obj,
472 const Pred& pred) :
473 Linked_hash_set({}, n_buckets, hasher_obj, pred)
474{
475 // That's all.
476}
477
478template<typename Key_t, typename Hash_t, typename Pred_t>
480 size_type n_buckets,
481 const Hash& hasher_obj,
482 const Pred& pred) :
483 // Their initializer_list is meant for a set of keys, but it is perfect for our list of keys.
484 m_value_list(values),
485 /* @todo Using detail:: like this is technically uncool, but so far all alternatives look worse.
486 * We blame the somewhat annoying ctor API for unordered_*. */
487 m_value_iter_set((n_buckets == size_type(-1))
488 ? boost::unordered::detail::default_bucket_count
489 : n_buckets,
490 hasher_obj, pred)
491{
492 // Now link each key in the quick-lookup table to its stored location in the ordering.
493 const auto value_list_end_it = m_value_list.cend();
494 for (auto value_list_it = m_value_list.cbegin(); value_list_it != value_list_end_it; ++value_list_it)
495 {
496 // Note that value_list_it contains both the iterator (lookup result) and the lookup key (iterator pointee).
497 m_value_iter_set.insert(value_list_it);
498 }
499}
500
501template<typename Key_t, typename Hash_t, typename Pred_t>
503 // An empty m_value_iter_set is constructed here but immediately replaced within the {body}.
504{
505 operator=(src);
506}
507
508template<typename Key_t, typename Hash_t, typename Pred_t>
510 // An empty m_value_iter_set is constructed here but immediately replaced within the {body}.
511{
512 operator=(std::move(src));
513}
514
515template<typename Key_t, typename Hash_t, typename Pred_t>
518{
519 /* See Linked_hash_map equivalent method, to which this is analogous. Keeping comments here light.
520 * Though we don't have to do the reinterpret_cast<> thing; can just assign the list to src's counterpart;
521 * in our case Value is just Key -- no const-ness involved. */
522
523 using Value_iter_set = decltype(m_value_iter_set);
524
525 if (&src == this)
526 {
527 return *this;
528 }
529 // else
530
531 m_value_list = src.m_value_list;
532
533 const auto& src_value_iter_set = src.m_value_iter_set;
534 m_value_iter_set = Value_iter_set{src_value_iter_set.bucket_count(),
535 src_value_iter_set.hash_function(),
536 src_value_iter_set.key_eq()};
537
538 const auto value_list_end_it = m_value_list.cend();
539 for (auto value_list_it = m_value_list.cbegin(); value_list_it != value_list_end_it; ++value_list_it)
540 {
541 m_value_iter_set.insert(value_list_it);
542 }
543
544 return *this;
545} // Linked_hash_set::operator=()
546
547template<typename Key_t, typename Hash_t, typename Pred_t>
550{
551 if (&src != this)
552 {
553 clear();
554 swap(src);
555 }
556 return *this;
557}
558
559template<typename Key_t, typename Hash_t, typename Pred_t>
561{
562 using std::swap;
563
564 swap(m_value_iter_set, other.m_value_iter_set); // unordered_set<> exchange; constant-time for sure at least.
565 swap(m_value_list, other.m_value_list); // list<> exchange (probably ~= head+tail pointer pairs exchanged).
566 // Per cppreference.com `list<>::iterator`s (inside the `_maps`s) remain valid after list<>s swapped.
567}
568
569template<typename Key_t, typename Hash_t, typename Pred_t>
570std::pair<typename Linked_hash_set<Key_t, Hash_t, Pred_t>::Iterator, bool>
572{
573 using std::pair;
574
575 const auto set_it = m_value_iter_set.find(key);
576 if (set_it != m_value_iter_set.end())
577 {
578 return pair<Iterator, bool>{set_it->iter(), false}; // *set_it is Linked_hash_key.
579 }
580 // else
581
582 /* Insert it at the front: as advertised, new element is "touched," meaning it is made "newest," so goes at start.
583 * Note that "it" = a copy of key; this invokes Key copy ctor, as emplace_front() forwards to it. */
584 m_value_list.emplace_front(key);
585
586 /* Iterator to the new element is therefore iterator to start of list of `Key`s.
587 * And make sure we can look it up in the future quickly (such as what is done above).
588 * Linked_hash_key_set m_value_iter_set achieves these aims black-boxily. */
589 const auto list_it = m_value_list.cbegin();
590 m_value_iter_set.insert(list_it);
591 return pair<Iterator, bool>{list_it, true};
592}
593
594template<typename Key_t, typename Hash_t, typename Pred_t>
595std::pair<typename Linked_hash_set<Key_t, Hash_t, Pred_t>::Iterator, bool>
597{
598 using std::pair;
599
600 // Same as other insert() but construct value in-place inside the list<> as-if: Key k2{move(k)}.
601
602 const auto set_it = m_value_iter_set.find(key);
603 if (set_it != m_value_iter_set.end())
604 {
605 return pair<Iterator, bool>{set_it->iter(), false}; // *set_it is Linked_hash_key.
606 }
607 // else
608
609 m_value_list.emplace_front(std::move(key)); // <-- The difference.
610
611 const auto list_it = m_value_list.cbegin();
612 m_value_iter_set.insert(list_it);
613 return pair<Iterator, bool>{list_it, true};
614}
615
616template<typename Key_t, typename Hash_t, typename Pred_t>
619{
620 const auto set_it = m_value_iter_set.find(key);
621 return (set_it == m_value_iter_set.cend()) ? m_value_list.cend() : set_it->iter();
622}
623
624template<typename Key_t, typename Hash_t, typename Pred_t>
627{
628 return m_value_iter_set.count(key);
629}
630
631template<typename Key_t, typename Hash_t, typename Pred_t>
633{
634 m_value_list.splice(m_value_list.begin(), m_value_list, it);
635}
636
637template<typename Key_t, typename Hash_t, typename Pred_t>
639{
640 const auto it = find(key);
641 if (it == end())
642 {
643 return false;
644 }
645 // else
646
647 touch(it);
648 return true;
649}
650
651template<typename Key_t, typename Hash_t, typename Pred_t>
654{
655 m_value_iter_set.erase(*it);
656 return m_value_list.erase(it);
657}
658
659template<typename Key_t, typename Hash_t, typename Pred_t>
662{
663 for (auto it = it_newest; it != it_past_oldest; ++it)
664 {
665 m_value_iter_set.erase(*it);
666 }
667
668 return m_value_list.erase(it_newest, it_past_oldest);
669}
670
671template<typename Key_t, typename Hash_t, typename Pred_t>
674{
675 const auto set_it = m_value_iter_set.find(key);
676 if (set_it == m_value_iter_set.end())
677 {
678 return 0;
679 }
680 // else
681
682 const auto list_it = set_it->iter();
683 m_value_iter_set.erase(set_it);
684 m_value_list.erase(list_it);
685
686 return 1;
687}
688
689template<typename Key_t, typename Hash_t, typename Pred_t>
691{
692 m_value_iter_set.clear();
693 m_value_list.clear();
694}
695
696template<typename Key_t, typename Hash_t, typename Pred_t>
699{
700 return m_value_list.cbegin();
701}
702
703template<typename Key_t, typename Hash_t, typename Pred_t>
706{
707 return newest(); // For us Iterator = Const_iterator.
708}
709
710template<typename Key_t, typename Hash_t, typename Pred_t>
713{
714 return newest();
715}
716
717template<typename Key_t, typename Hash_t, typename Pred_t>
720{
721 return begin(); // For us Iterator = Const_iterator.
722}
723
724template<typename Key_t, typename Hash_t, typename Pred_t>
727{
728 return m_value_list.cend();
729}
730
731template<typename Key_t, typename Hash_t, typename Pred_t>
734{
735 return past_oldest(); // For us Iterator = Const_iterator.
736}
737
738template<typename Key_t, typename Hash_t, typename Pred_t>
741{
742 return past_oldest();
743}
744
745template<typename Key_t, typename Hash_t, typename Pred_t>
748{
749 return end(); // For us Iterator = Const_iterator.
750}
751
752template<typename Key_t, typename Hash_t, typename Pred_t>
755{
756 return m_value_list.crbegin();
757}
758
759template<typename Key_t, typename Hash_t, typename Pred_t>
762{
763 return oldest(); // For us Iterator = Const_iterator.
764}
765
766template<typename Key_t, typename Hash_t, typename Pred_t>
769{
770 return oldest();
771}
772
773template<typename Key_t, typename Hash_t, typename Pred_t>
776{
777 return rbegin(); // For us Reverse_iterator = Const_reverse_iterator.
778}
779
780template<typename Key_t, typename Hash_t, typename Pred_t>
783{
784 return m_value_list.crend(); // For us Reverse_iterator = Const_reverse_iterator.
785}
786
787template<typename Key_t, typename Hash_t, typename Pred_t>
790{
791 return past_newest(); // For us Reverse_iterator = Const_reverse_iterator.
792}
793
794template<typename Key_t, typename Hash_t, typename Pred_t>
797{
798 return past_newest();
799}
800
801template<typename Key_t, typename Hash_t, typename Pred_t>
804{
805 return m_value_list.rend(); // For us Reverse_iterator = Const_reverse_iterator.
806}
807
808template<typename Key_t, typename Hash_t, typename Pred_t>
811{
812 return m_value_iter_set.size(); // I'm skeptical/terrified of list::size()'s time complexity.
813}
814
815template<typename Key_t, typename Hash_t, typename Pred_t>
817{
818 return m_value_list.empty();
819}
820
821template<typename Key_t, typename Hash_t, typename Pred_t>
824{
825 return std::min(m_value_iter_set.max_size(), m_value_list.max_size());
826}
827
828template<typename Key_t, typename Hash_t, typename Pred_t>
830{
831 val1.swap(val2);
832}
833
834} // namespace flow::util
An object of this class is a map that combines the lookup speed of an unordered_set<> and ordering an...
Hash hasher
For container compliance (hence the irregular capitalization): Hash type.
Value * pointer
For container compliance (hence the irregular capitalization): pointer to Key type.
Linked_hash_set(const Linked_hash_set &src)
Constructs object that is a copy of the given source.
Const_iterator cbegin() const
Synonym of const_newest().
Const_reverse_iterator const_oldest() const
Returns first, a/k/a "oldest," element's reverse iterator (to immutable element).
Pred_t Pred
Convenience alias for template arg.
void swap(Linked_hash_set &other)
Swaps the contents of this structure and other.
Linked_hash_set & operator=(Linked_hash_set &&src)
Overwrites this object making it identical to the given source, while the given source becomes as-if ...
Const_reverse_iterator Reverse_iterator
Type for reverse iterator pointing into a mutable structure of this type but actually that is not pos...
void clear()
Makes it so that size() == 0.
bool empty() const
Returns true if and only if container is empty.
Value value_type
For container compliance (hence the irregular capitalization): Value type.
Reverse_iterator rend() const
Synonym of past_newest().
std::pair< Iterator, bool > insert(const Key &key)
Attempts to insert (copying it) the given keyinto the map; if key already in *this makes no change.
std::size_t size_type
Expresses sizes/lengths of relevant things.
Const_iterator erase(const Const_iterator &it)
Erases the element pointed to by the given valid iterator.
Linked_hash_set & operator=(const Linked_hash_set &src)
Overwrites this object with a copy of the given source.
Linked_hash_set(Linked_hash_set &&src)
Constructs object by making it equal to the given source, while the given source becomes as-if defaul...
Const_reverse_iterator const_past_newest() const
Returns one past last, a/k/a "newest," element's reverse iterator (to immutable element).
size_type size() const
Returns number of elements stored.
std::pair< Iterator, bool > insert(Key &&key)
Identical to the other overload, except that (if key not already present in *this) the key is moved,...
Reverse_iterator rbegin() const
Synonym of oldest().
Const_iterator const_past_oldest() const
Returns one past last, a/k/a "oldest," element's iterator (to immutable element).
Const_iterator cend() const
Synonym of const_past_oldest().
Pred key_equal
For container compliance (hence the irregular capitalization): Pred type.
Key Value
Short-hand for values, which in this case are simply the keys.
const Value * const_pointer
For container compliance (hence the irregular capitalization): pointer to const Key type.
void touch(const Const_iterator &it)
Given a valid iterator into the structure, makes the pointed-to element "newest" by moving it from wh...
typename Value_list::const_reverse_iterator Const_reverse_iterator
Type for reverse iterator pointing into an immutable structure of this type.
Const_iterator const_newest() const
Returns first, a/k/a "newest," element's iterator (to immutable element).
Const_iterator const_iterator
For container compliance (hence the irregular capitalization): Const_iterator type.
Iterator begin() const
Synonym of newest().
Reverse_iterator oldest() const
Returns first, a/k/a "oldest," element's reverse iterator (to immutable element, due to nature of thi...
size_type erase(const Key &key)
Erases the element with the given key, if it exists.
Const_iterator erase(const Const_iterator &it_newest, const Const_iterator &it_past_oldest)
Erases all elements in the range [it_newest, it_past_oldest).
Key key_type
For container compliance (hence the irregular capitalization): Key type.
Iterator past_oldest() const
Returns one past last, a/k/a "oldest," element's iterator (to immutable element, due to nature of thi...
Const_iterator Iterator
Type for iterator pointing into a mutable structure of this type but actually that is not possible; s...
Linked_hash_set(size_type n_buckets=size_type(-1), const Hash &hasher_obj=Hash{}, const Pred &pred=Pred{})
Constructs empty structure with some basic parameters.
size_type count(const Key &key) const
Returns the number of times a key equal to the given one is present (as-if via find()) in the map: ei...
Key_t Key
Convenience alias for template arg.
size_type max_size() const
Returns max number of elements that can be stored.
const Value & const_reference
For container compliance (hence the irregular capitalization): reference to const Key type.
typename Value_list::const_iterator Const_iterator
Type for iterator pointing into an immutable structure of this type.
Hash_t Hash
Convenience alias for template arg.
Iterator iterator
For container compliance (hence the irregular capitalization): Iterator type.
Const_iterator find(const Key &key) const
Attempts to find value at the given key in the map.
Iterator newest() const
Returns first, a/k/a "newest," element's iterator (to immutable element, due to nature of this type).
std::list< Value > Value_list
Short-hand for doubly linked list of Keys.
Value_list m_value_list
Analogous to Linked_hash_map::m_value_list; but simpler in that it just stores Keys,...
std::ptrdiff_t difference_type
Type for difference of size_types.
Linked_hash_set(std::initializer_list< Value > values, size_type n_buckets=size_type(-1), const Hash &hasher_obj=Hash{}, const Pred &pred=Pred{})
Constructs structure with some basic parameters, and values initialized from initializer list.
Const_reverse_iterator crend() const
Synonym of const_past_newest().
Iterator end() const
Synonym of past_oldest().
bool touch(const Key &key)
Given a key into the structure, makes the corresponding element "newest" by moving it from wherever i...
Reverse_iterator past_newest() const
Returns one past last, a/k/a "newest," element's reverse iterator (to immutable element,...
Linked_hash_key_set< Key, Iterator, Hash, Pred, false > m_value_iter_set
Analogous to Linked_hash_map::m_value_iter_set; just configured to generate a simpler ....
Value & reference
For container compliance (hence the irregular capitalization): reference to Key type.
Const_reverse_iterator crbegin() const
Synonym of const_oldest().
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
Definition: basic_blob.hpp:31
void swap(Basic_blob< Allocator, SHARING > &blob1, Basic_blob< Allocator, SHARING > &blob2, log::Logger *logger_ptr) noexcept
Equivalent to blob1.swap(blob2).
void swap(Linked_hash_set< Key_t, Hash_t, Pred_t > &val1, Linked_hash_set< Key_t, Hash_t, Pred_t > &val2)
Equivalent to val1.swap(val2).