BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_unorderedmap.h
Go to the documentation of this file.
1/// @file bslstl_unorderedmap.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_unorderedmap.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_UNORDEREDMAP
9#define INCLUDED_BSLSTL_UNORDEREDMAP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_unorderedmap bslstl_unorderedmap
15/// @brief Provide an STL-compliant `unordered_map` container.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_unorderedmap
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_unorderedmap-purpose"> Purpose</a>
25/// * <a href="#bslstl_unorderedmap-classes"> Classes </a>
26/// * <a href="#bslstl_unorderedmap-canonical-header"> Canonical Header </a>
27/// * <a href="#bslstl_unorderedmap-description"> Description </a>
28/// * <a href="#bslstl_unorderedmap-requirements-on-value_type"> Requirements on value_type </a>
29/// * <a href="#bslstl_unorderedmap-glossary"> Glossary </a>
30/// * <a href="#bslstl_unorderedmap-requirements-on-hash-and-equal"> Requirements on HASH and EQUAL </a>
31/// * <a href="#bslstl_unorderedmap-memory-allocation"> Memory Allocation </a>
32/// * <a href="#bslstl_unorderedmap-bslma-style-allocators"> bslma-Style Allocators </a>
33/// * <a href="#bslstl_unorderedmap-operations"> Operations </a>
34/// * <a href="#bslstl_unorderedmap-iterator-pointer-and-reference-invalidation"> Iterator, Pointer, and Reference Invalidation </a>
35/// * <a href="#bslstl_unorderedmap-unordered-map-configuration"> Unordered Map Configuration </a>
36/// * <a href="#bslstl_unorderedmap-practical-requirements-on-hash"> Practical Requirements on HASH </a>
37/// * <a href="#bslstl_unorderedmap-usage"> Usage </a>
38/// * <a href="#bslstl_unorderedmap-example-1-gathering-document-statistics"> Example 1: Gathering Document Statistics </a>
39/// * <a href="#bslstl_unorderedmap-example-2-examining-and-setting-unordered-map-configuration"> Example 2: Examining and Setting Unordered Map Configuration </a>
40/// * <a href="#bslstl_unorderedmap-example-3-inverse-concordance"> Example 3: Inverse Concordance </a>
41///
42/// # Purpose {#bslstl_unorderedmap-purpose}
43/// Provide an STL-compliant `unordered_map` container.
44///
45/// # Classes {#bslstl_unorderedmap-classes}
46///
47/// - bsl::unordered_map : STL-compliant `unordered_map` container
48///
49/// # Canonical Header {#bslstl_unorderedmap-canonical-header}
50/// bsl_unordered_map.h
51///
52/// @see package bos+stdhdrs in the bos package group
53///
54/// # Description {#bslstl_unorderedmap-description}
55/// This component defines a single class template,
56/// `bsl::unordered_map`, implementing the standard container holding a
57/// collection of unique keys, each mapped to an associated value with no
58/// guarantees on ordering.
59///
60/// An instantiation of `unordered_map` is an allocator-aware, value-semantic
61/// type whose salient attributes are its size (number of keys) and the set of
62/// `KEY-VALUE` pairs the `unordered_map` contains, without regard to their
63/// order. If `unordered_map` is instantiated with a key type or mapped type
64/// that is not itself value-semantic, then it will not retain all of its
65/// value-semantic qualities. In particular, if the key or mapped type cannot
66/// be tested for equality, then an `unordered_map` containing that type cannot
67/// be tested for equality. It is even possible to instantiate `unordered_map`
68/// with types that do not have an accessible copy-constructor, in which case
69/// the `unordered_map` will not be copyable. Note if a hasher and/or
70/// equality-comparison functor are supplied at container construction, they are
71/// copied to the container, and those copies, rather than the object(s)
72/// supplied, are used for hashing and equality comparison of keys.
73///
74/// When comparing unordered map containers for equality, the keys are compared
75/// using `operator==`, rather than the `EQUALS` parameter function type.
76///
77/// An `unordered_map` meets the requirements of an unordered associative
78/// container with forward iterators in the C++11 standard [23.2.5]. The
79/// `unordered_map` implemented here adheres to the C++11 standard when compiled
80/// with a C++11 compiler, and makes the best approximation when compiled with a
81/// C++03 compiler. In particular, for C++03 we emulate move semantics, but
82/// limit forwarding (in `emplace`) to `const` lvalues, and make no effort to
83/// emulate `noexcept` or initializer-lists. The `unordered_map` implemented
84/// here adheres to the C++ standard, except that it may rehash when setting the
85/// @ref max_load_factor in order to preserve the property that the factor is
86/// always respected (which is a potentially throwing operation).
87///
88/// ## Requirements on value_type {#bslstl_unorderedmap-requirements-on-value_type}
89///
90///
91/// An `unordered_map` is a fully Value-Semantic Type (see @ref bsldoc_glossary )
92/// only if the supplied `KEY` and `VALUE` template parameters are themselves
93/// fully value-semantic. The alias `value_type` is defined as
94/// `pair<const KEY, VALUE>`. It is possible to instantiate an `unordered_map`
95/// with `KEY` and `VALUE` parameter arguments that do not provide a full set of
96/// value-semantic operations, but then some methods of the container may not be
97/// instantiable. The following terminology, adopted from the C++11 standard,
98/// is used in the function documentation of `map` to describe a function's
99/// requirements for the `KEY` and `VALUE` template parameters. These terms are
100/// also defined in section [17.6.3.1] of the C++11 standard.
101///
102/// ## Glossary {#bslstl_unorderedmap-glossary}
103///
104///
105/// @code
106/// Legend
107/// ------
108/// 'X' - denotes an allocator-aware container type (e.g., 'map')
109/// 'T' - 'value_type' associated with 'X'
110/// 'A' - type of the allocator used by 'X'
111/// 'm' - lvalue of type 'A' (allocator)
112/// 'p', - address ('T *') of uninitialized storage for a 'T' within an 'X'
113/// 'rv' - rvalue of type (non-'const') 'T'
114/// 'v' - rvalue or lvalue of type (possibly 'const') 'T'
115/// 'args' - 0 or more arguments
116/// @endcode
117/// The following terms are used to more precisely specify the requirements on
118/// template parameter types in function-level documentation.
119///
120/// *default-insertable*: `T` has a default constructor. More precisely, `T`
121/// is `default-insertable` into `X` means that the following expression is
122/// well-formed:
123/// `allocator_traits<A>::construct(m, p)`
124///
125/// *move-insertable*: `T` provides a constructor that takes an rvalue of type
126/// (non-`const`) `T`. More precisely, `T` is `move-insertable` into `X`
127/// means that the following expression is well-formed:
128/// `allocator_traits<A>::construct(m, p, rv)`
129/// Note that since the `first` field of `T` is `const`, `T` is not
130/// *move-insertable* unless `key_type` is *copy-insertable*.
131///
132/// *copy-insertable*: `T` provides a constructor that takes an lvalue or
133/// rvalue of type (possibly `const`) `T`. More precisely, `T` is
134/// `copy-insertable` into `X` means that the following expression is
135/// well-formed:
136/// `allocator_traits<A>::construct(m, p, v)`
137///
138/// *move-assignable*: `T` provides an assignment operator that takes an rvalue
139/// of type (non-`const`) `T`. Note that since the `first` element of
140/// `value_type` is `const`, `value_type` is not `move-assignable`.
141/// Note that since the `first` field of `T` is `const`, `T` is not
142/// *move-assignable* unless `key_type` is *copy-assignable*.
143///
144/// *copy-assignable*: `T` provides an assignment operator that takes an lvalue
145/// or rvalue of type (possibly `const`) `T`.
146///
147/// *emplace-constructible*: `T` is `emplace-constructible` into `X` from
148/// `args` means that the following expression is well-formed:
149/// `allocator_traits<A>::construct(m, p, args)`
150///
151/// *erasable*: `T` provides a destructor. More precisely, `T` is `erasable`
152/// from `X` means that the following expression is well-formed:
153/// `allocator_traits<A>::destroy(m, p)`
154///
155/// *equality-comparable*: The type provides an equality-comparison operator
156/// that defines an equivalence relationship and is both reflexive and
157/// transitive.
158///
159/// ## Requirements on HASH and EQUAL {#bslstl_unorderedmap-requirements-on-hash-and-equal}
160///
161///
162/// The (template parameter) types `HASH` and `EQUAL` must be copy-constructible
163/// function-objects. Note that this requirement is somewhat stronger than the
164/// requirement currently in the standard; see the discussion for Issue 2215
165/// (http://cplusplus.github.com/LWG/lwg-active.html#2215);
166///
167/// Naturally, if either `HASH` or `EQUAL` is to be the default for its type, it
168/// must be default-constructible as well.
169///
170/// `HASH` shall support a function call operator compatible with the following
171/// statements:
172/// @code
173/// HASH hash;
174/// KEY key;
175/// std::size_t result = hash(key);
176/// @endcode
177/// where the definition of the called function meets the requirements of a
178/// hash function as specified in {@ref bslstl_hash |Standard Hash Function}.
179///
180/// `EQUAL` shall support the a function call operator compatible with the
181/// following statements:
182/// @code
183/// EQUAL equal;
184/// KEY key1, key2;
185/// bool result = equal(key1, key2);
186/// @endcode
187/// where the definition of the called function defines an equivalence
188/// relationship on keys that is both reflexive and transitive.
189///
190/// The `HASH` and `EQUAL` function-objects are further constrained, such that
191/// for any two objects whose keys compare equivalent by the comparator, shall
192/// also produce the same return value from the hasher.
193///
194/// ## Memory Allocation {#bslstl_unorderedmap-memory-allocation}
195///
196///
197/// The type supplied as the `ALLOCATOR` template parameter determines how
198/// memory will be allocated. The `unordered_map` template supports allocators
199/// meeting the requirements of the C++11 standard [allocator.requirements],
200/// and, in addition, it supports scoped-allocators derived from the
201/// `bslma::Allocator` memory allocation protocol. Clients intending to use
202/// `bslma` style allocators should use the template's default `ALLOCATOR` type.
203/// The default type for the `ALLOCATOR` template parameter, `bsl::allocator`,
204/// provides a C++11 standard-compatible adapter for a `bslma::Allocator`
205/// object.
206///
207/// ### bslma-Style Allocators {#bslstl_unorderedmap-bslma-style-allocators}
208///
209///
210/// If the (template parameter) type `ALLOCATOR` of an `unordered_map`
211/// instantiation is `bsl::allocator`, then objects of that unordered map type
212/// will conform to the standard behavior of a `bslma`-allocator-enabled type.
213/// Such an unordered map accepts an optional `bslma::Allocator` argument at
214/// construction. If the address of a `bslma::Allocator` object is explicitly
215/// supplied at construction, it is used to supply memory for the
216/// `unordered_map` throughout its lifetime; otherwise, the `unordered_map` will
217/// use the default allocator installed at the time of the `unordered_map`s
218/// construction (see @ref bslma_default ). In addition to directly allocating
219/// memory from the indicated `bslma::Allocator`, an `unordered_map` supplies
220/// that allocator's address to the constructors of contained objects of the
221/// (template parameter) types `KEY` and `VALUE` if, respectively, those types
222/// define the `bslma::UsesBslmaAllocator` trait to `true`.
223///
224/// ## Operations {#bslstl_unorderedmap-operations}
225///
226///
227/// This section describes the run-time complexity of operations on instances
228/// of `unordered_map`:
229/// @code
230/// Legend
231/// ------
232/// 'K' - template parameter type 'KEY' of the unordered map
233/// 'M' - template parameter type 'VALUE' of the unordered map
234/// 'a', 'b' - two distinct objects of type 'unordered_map<K, V>'
235/// 'n', 'm' - number of elements in 'a' and 'b', respectively
236/// 'w' - number of buckets of 'a'
237/// 'hf' - hash functor hashing objects of type 'K'
238/// 'eq' - equality functor comparing objects of type 'K'
239/// 'A' - STL-style memory allocator
240/// 'i1', 'i2' - two iterators defining a sequence of 'value_type'
241/// objects
242/// 'rg' - range of objects convertable to `value_type' objects
243/// 'k' - object of type 'K'
244/// 'vt' - object of type 'bsl::pair<const K, M>'
245/// 'Args&&...' - variable number of arguments
246/// 't&&' - movable reference to variable 't'
247/// 'ai1', 'ai2' - two iterators belonging to 'a'
248/// 'idx' - bucket index
249/// '{*}' - C++11 std::initializer_list
250/// 'distance(i1, i2)' - number of elements in the range '[i1 .. i2)'
251/// 'distance(ai1,ai2)' - number of elements in the range '[ai1 .. ai2)'
252/// 'distance({*})' - number of elements in the initializer list
253/// 'z' - floating point value representing a load factor
254///
255/// +----------------------------------------------------+--------------------+
256/// | Operation | Complexity |
257/// +====================================================+====================+
258/// | unordered_map<K, M> a; (default construction) | O[1] |
259/// | unordered_map<K, M> a(A); | |
260/// +----------------------------------------------------+--------------------+
261/// | unordered_map<K, M> a(b); (copy construction) | Average: O[m] |
262/// | unordered_map<K, M> a(b, A); | Worst: O[m^2] |
263/// +----------------------------------------------------+--------------------+
264/// | unordered_map<K, M> a(b&&); (move construction) | O[1]
265/// +----------------------------------------------------+--------------------+
266/// | unordered_map<K, M> a(b&&, A); (move construction) | Best: O[1]
267/// | | Worst: O[m^2] |
268/// +----------------------------------------------------+--------------------+
269/// | unordered_map<K, M> a(w); | O[n] |
270/// | unordered_map<K, M> a(w, A); | |
271/// | unordered_map<K, M> a(w, hf); | |
272/// | unordered_map<K, M> a(w, hf, A); | |
273/// | unordered_map<K, M> a(w, hf, eq); | |
274/// | unordered_map<K, M> a(w, hf, eq, A); | |
275/// +----------------------------------------------------+--------------------+
276/// | unordered_map<K, M> a(i1, i2); | Average: O[N] |
277/// | unordered_map<K, M> a(i1, i2, A); | Worst: O[N^2] |
278/// | unordered_map<K, M> a(i1, i2, w); | where N = |
279/// | unordered_map<K, M> a(i1, i2, w, A); | distance(i1, i2)] |
280/// | unordered_map<K, M> a(i1, i2, w, hf); | |
281/// | unordered_map<K, M> a(i1, i2, w, hf, A); | |
282/// | unordered_map<K, M> a(i1, i2, w, hf, eq); | |
283/// | unordered_map<K, M> a(i1, i2, w, hf, eq, A); | |
284/// +----------------------------------------------------+--------------------+
285/// | unordered_map<K, M> a(from_range, rg); | Average: O[N] |
286/// | unordered_map<K, M> a(from_range, rg, A); | Worst: O[N^2] |
287/// | unordered_map<K, M> a(from_range, rg, w); | where N = range:: |
288/// | unordered_map<K, M> a(from_range, rg, w, A); | distance(rg)] |
289/// | unordered_map<K, M> a(from_range, rg, w, hf); | |
290/// | unordered_map<K, M> a(from_range, rg, w, hf, A); | |
291/// | unordered_map<K, M> a(from_range, rg, w, hf, eq); | |
292/// | unordered_map<K, M> a(from_range, rg, w, hf, eq, A)| |
293/// +----------------------------------------------------+--------------------+
294/// | unordered_map<K, M> a({*}); | Average: O[N] |
295/// | unordered_map<K, M> a({*}, A); | Worst: O[N^2] |
296/// | unordered_map<K, M> a({*}, w); | where N = |
297/// | unordered_map<K, M> a({*}, w, A); | 'distance{*}'|
298/// | unordered_map<K, M> a({*}, w, hf); | |
299/// | unordered_map<K, M> a({*}, w, hf, A); | |
300/// | unordered_map<K, M> a({*}, w, hf, eq); | |
301/// | unordered_map<K, M> a({*}, w, hf, eq, A); | |
302/// +----------------------------------------------------+--------------------+
303/// | a.~unordered_map<K, M>(); (destruction) | O[n] |
304/// +----------------------------------------------------+--------------------+
305/// | a = b; (assignment) | Average: O[n+m] |
306/// | | Worst: O[n+m^2] |
307/// +----------------------------------------------------+--------------------+
308/// | a = {*}; (assignment) | Average: O[n+N] |
309/// | | Worst: O[n+N^2] |
310/// | | where N = |
311/// | | distance({*})|
312/// +----------------------------------------------------+--------------------+
313/// | a.begin(), a.end(), a.cbegin(), a.cend() | O[1] |
314/// +----------------------------------------------------+--------------------+
315/// | a.begin(idx), a.end(idx), a.cbegin(idx), | O[1] |
316/// | a.cend(idx) | |
317/// +----------------------------------------------------+--------------------+
318/// | a == b, a != b | Best: O[n] |
319/// | | Worst: O[n^2] |
320/// +----------------------------------------------------+--------------------+
321/// | a.swap(b), swap(a, b) | O[1] |
322/// +----------------------------------------------------+--------------------+
323/// | a.key_eq() | O[1] |
324/// +----------------------------------------------------+--------------------+
325/// | a.hash_function() | O[1] |
326/// +----------------------------------------------------+--------------------+
327/// | a.size() | O[1] |
328/// +----------------------------------------------------+--------------------+
329/// | a.max_size() | O[1] |
330/// +----------------------------------------------------+--------------------+
331/// | a.empty() | O[1] |
332/// +----------------------------------------------------+--------------------+
333/// | a.get_allocator() | O[1] |
334/// +----------------------------------------------------+--------------------+
335/// | a[k] | Average: O[1] |
336/// | | Worst: O[n] |
337/// +----------------------------------------------------+--------------------+
338/// | a.at(k) | Average: O[1] |
339/// | | Worst: O[n] |
340/// +----------------------------------------------------+--------------------+
341/// | a.insert(vt), a.insert(ai1, vt) | Average: O[1] |
342/// | a.emplace(Args&&...) | Worst: O[n] |
343/// | a.emplace_hint(ai1, Args&&...) | |
344/// +----------------------------------------------------+--------------------+
345/// | a.insert(vt&&), a.insert(ai1, vt&&) | Average: O[1] |
346/// | | Worst: O[n] |
347/// +----------------------------------------------------+--------------------+
348/// | a.insert(i1, i2) | Average: O[ |
349/// | | distance(i1, i2)]|
350/// | | Worst: O[n * |
351/// | | distance(i1, i2)]|
352/// +----------------------------------------------------+--------------------+
353/// | a.insert({*}) | Average: O[ |
354/// | | distance({*})]|
355/// | | Worst: O[ |
356/// | | (n+distance{*})^2]|
357/// +----------------------------------------------------+--------------------+
358/// | a.insert_range(rg) | Average: O[ |
359/// | | ranges:: |
360/// | | distance(rg)]|
361/// | | Worst: O[n * |
362/// | | ranges:: |
363/// | | distance(rg)]|
364/// +----------------------------------------------------+--------------------+
365/// | a.erase(ai1) | Average: O[1] |
366/// | | Worst: O[n] |
367/// +----------------------------------------------------+--------------------+
368/// | a.erase(k) | Average: |
369/// | | O[a.count(k)]|
370/// | | Worst: |
371/// | | O[n] |
372/// +----------------------------------------------------+--------------------+
373/// | a.erase(ai1, ai2) | Average: O[ |
374/// | | distance(ai1, ai2)]|
375/// | | Worst: O[n] |
376/// +----------------------------------------------------+--------------------+
377/// | a.clear() | O[n] |
378/// +----------------------------------------------------+--------------------+
379/// | a.contains(k) | Average: O[1] |
380/// | | Worst: O[n] |
381/// +----------------------------------------------------+--------------------+
382/// | a.find(k) | Average: O[1] |
383/// | | Worst: O[n] |
384/// +----------------------------------------------------+--------------------+
385/// | a.count(k) | Average: O[1] |
386/// | | Worst: O[n] |
387/// +----------------------------------------------------+--------------------+
388/// | a.equal_range(k) | Average: O[1] |
389/// | | Worst: O[n] |
390/// +----------------------------------------------------+--------------------+
391/// | a.bucket_count() | O[1] |
392/// +----------------------------------------------------+--------------------+
393/// | a.max_bucket_count() | O[1] |
394/// +----------------------------------------------------+--------------------+
395/// | a.bucket(k) | O[1] |
396/// +----------------------------------------------------+--------------------+
397/// | a.bucket_size(idx) | O[a.bucket_size( |
398/// | | idx)]|
399/// +----------------------------------------------------+--------------------+
400/// | a.load_factor() | O[1] |
401/// +----------------------------------------------------+--------------------+
402/// | a.max_load_factor() | O[1] |
403/// | a.max_load_factor(z) | O[1] |
404/// +----------------------------------------------------+--------------------+
405/// | a.rehash(k) | Average: O[n] |
406/// | | Worst: O[n^2] |
407/// +----------------------------------------------------+--------------------+
408/// | a.reserve(k) | Average: O[n] |
409/// | | Worst: O[n^2] |
410/// +----------------------------------------------------+--------------------+
411/// @endcode
412///
413/// ## Iterator, Pointer, and Reference Invalidation {#bslstl_unorderedmap-iterator-pointer-and-reference-invalidation}
414///
415///
416/// No method of `unordered_map` invalidates a pointer or reference to an
417/// element in the unordered map, unless it also erases that element, such as
418/// any `erase` overload, `clear`, or the destructor (that erases all elements).
419/// Pointers and references are stable through a rehash.
420///
421/// Iterators to elements in the container are invalidated by any rehash, so
422/// iterators may be invalidated by an `insert` or `emplace` call if it triggers
423/// a rehash (but not otherwise). Iterators to specific elements are also
424/// invalidated when that element is erased. Note that although the `end`
425/// iterator is not an iterator referring to any element in the container, it
426/// may be invalidated by any non-`const` method.
427///
428/// ## Unordered Map Configuration {#bslstl_unorderedmap-unordered-map-configuration}
429///
430///
431/// The unordered map has interfaces that can provide insight into and control
432/// of its inner workings. The unordered map is implemented using a hash table
433/// (see @ref bslstl_hashtable ), a dynamically sized array of "buckets". If two
434/// elements hash to the same bucket (termed a "collision"), then that bucket
435/// will house multiple elements. As elements are added to the unordered map,
436/// the number of buckets is increased (and the existing elements redistributed)
437/// to keep the average number of elements per bucket (the "loading factor")
438/// below the specified maximum (the "maximum load factor", 1 by default).
439/// {Example 2: Examining and Setting Unordered Map Configuration} illustrates
440/// the use of these interfaces.
441///
442/// ## Practical Requirements on HASH {#bslstl_unorderedmap-practical-requirements-on-hash}
443///
444///
445/// An important factor in the performance an unordered map (and any of the
446/// other unordered containers) is the choice of hash function. In general, one
447/// wants the hash function to return uniformly distributed values that can be
448/// assigned to buckets (see {Unordered Map Configuration}) with few collisions.
449///
450/// The `bsl` package provides general purpose, default hash functions for
451/// `bsl::string`, `bslstl::StringRef`, and the arithmetic types (e.g., `int`);
452/// however, custom defined hash functions may do better, especially if one has
453/// information about the distribution of keys; there is considerable literature
454/// on designing hash functions.
455///
456/// When a user-defined class is used as a key, hasher must be provided (and
457/// equality functor, if equality is not otherwise defined). Two examples,
458/// {Example 3} and {@ref bslstl_unorderedset |Example 1}, address this issue by
459/// adapting the existing default hash functions for primitive types, an
460/// approach that may not always prove adequate.
461///
462/// ## Usage {#bslstl_unorderedmap-usage}
463///
464///
465/// In this section we show intended use of this component.
466///
467/// ### Example 1: Gathering Document Statistics {#bslstl_unorderedmap-example-1-gathering-document-statistics}
468///
469///
470/// Unordered maps are useful in situations when there is no meaningful way to
471/// order the key values, when the order of the keys is irrelevant to the
472/// problem domain (see {Example 3}), and (even if there is a meaningful
473/// ordering) the value of ordering the results is outweighed by the higher
474/// performance provided by unordered maps (compared to ordered maps).
475///
476/// Suppose one wished to gather statistics on the words appearing in a large
477/// set of documents on disk or in a data base. Gathering those statistics is
478/// intrusive (as one is competing for access to the documents with the regular
479/// users) and must be done as quickly as possible. Moreover, the set of unique
480/// words appearing in those documents may be high. The English language has in
481/// excess of a million words (albeit many appear infrequently), and, if the
482/// documents contain serial numbers, or Social Security numbers, or chemical
483/// formulas, etc., then the `O[log(n)]` insertion time of ordered maps may well
484/// be inadequate. The unordered map, having an `O[1]` typical insertion cost,
485/// is a viable alternative. In many problem domains, sorting, if needed, can
486/// be done after the data is gathered.
487///
488/// This example illustrates the use of `bsl::unordered_map` to gather one
489/// simple statistic (counts of unique words) on a single document. To avoid
490/// irrelevant details of acquiring the data, several modestly sized documents
491/// are stored in static arrays:
492/// @code
493/// static char document0[] =
494/// " IN CONGRESS, July 4, 1776.\n"
495/// "\n"
496/// " The unanimous Declaration of the thirteen united States of America,\n"
497/// "\n"
498/// " When in the Course of human events, it becomes necessary for one\n"
499/// " people to dissolve the political bands which have connected them with\n"
500/// " another, and to assume among the powers of the earth, the separate\n"
501/// " and equal station to which the Laws of Nature and of Nature's God\n"
502/// " entitle them, a decent respect to the opinions of mankind requires\n"
503/// " that they should declare the causes which impel them to the\n"
504/// " separation. We hold these truths to be self-evident, that all men\n"
505/// " are created equal, that they are endowed by their Creator with\n"
506/// " certain unalienable Rights, that among these are Life, Liberty and\n"
507/// " the pursuit of Happiness.--That to secure these rights, Governments\n"
508/// " are instituted among Men, deriving their just powers from the consent\n"
509/// " of the governed, --That whenever any Form of Government becomes\n"
510/// ...
511/// " States may of right do. And for the support of this Declaration,\n"
512/// " with a firm reliance on the protection of divine Providence, we\n"
513/// " mutually pledge to each other our Lives, our Fortunes and our sacred\n"
514/// " Honor.\n";
515///
516/// static char document1[] =
517/// "/The Universal Declaration of Human Rights\n"
518/// "/-----------------------------------------\n"
519/// "/Preamble\n"
520/// "/ - - - -\n"
521/// " Whereas recognition of the inherent dignity and of the equal and\n"
522/// " inalienable rights of all members of the human family is the\n"
523/// " foundation of freedom, justice and peace in the world,\n"
524/// ...
525/// "/Article 30\n"
526/// "/ - - - - -\n"
527/// " Nothing in this Declaration may be interpreted as implying for any\n"
528/// " State, group or person any right to engage in any activity or to\n"
529/// " perform any act aimed at the destruction of any of the rights and\n"
530/// " freedoms set forth herein.\n";
531///
532/// static char document2[] =
533/// "/CHARTER OF FUNDAMENTAL RIGHTS OF THE EUROPEAN UNION\n"
534/// "/---------------------------------------------------\n"
535/// " PREAMBLE\n"
536/// "\n"
537/// " The peoples of Europe, in creating an ever closer union among them,\n"
538/// " are resolved to share a peaceful future based on common values.\n"
539/// ...
540/// "/Article 54\n"
541/// "/- - - -\n"
542/// " Prohibition of abuse of rights\n"
543/// "\n"
544/// " Nothing in this Charter shall be interpreted as implying any right to\n"
545/// " engage in any activity or to perform any act aimed at the destruction\n"
546/// " of any of the rights and freedoms recognized in this Charter or at\n"
547/// " their limitation to a greater extent than is provided for herein.\n";
548///
549/// static char * const documents[] = { document0,
550/// document1,
551/// document2
552/// };
553/// const int numDocuments = sizeof documents / sizeof *documents;
554/// @endcode
555/// First, we define an alias to make our code more comprehensible.
556/// @code
557/// typedef bsl::unordered_map<bsl::string, int> WordTally;
558/// @endcode
559/// Next, we create an (empty) unordered map to hold our word tallies. The
560/// output from the `printf` statements will be discussed in {Example 2}.
561/// @code
562/// WordTally wordTally;
563///
564/// printf("size %4d initial\n", wordTally.size());
565/// printf("bucket_count %4d initial\n", wordTally.bucket_count());
566/// printf("load_factor %f initial\n", wordTally.load_factor());
567/// printf("max_load_factor %f initial\n", wordTally.max_load_factor());
568/// @endcode
569/// Then, we define the set of characters that define word boundaries:
570/// @code
571/// const char *delimiters = " \n\t,:;.()[]?!/";
572/// @endcode
573/// Next, we extract the words from our documents. Note that `strtok` modifies
574/// the document arrays (which were not made `const`).
575///
576/// For each iteration of the inner loop, that method looks for a map entry
577/// matching the given key value. On the first occurrence of a word, the map
578/// has no such entry, so one is created with a default value of the mapped
579/// value (0, just what we want in this case) and inserted into the map where it
580/// is found on any subsequent occurrences of the word. The `operator[]` method
581/// returns a reference providing modifiable access to the mapped value. Here,
582/// we apply the `++` operator to that reference to maintain a tally for the
583/// word.
584/// @code
585/// for (int idx = 0; idx < numDocuments; ++idx) {
586/// for (char *cur = strtok(documents[idx], delimiters);
587/// cur;
588/// cur = strtok(NULL, delimiters)) {
589/// ++wordTally[bsl::string(cur)];
590/// }
591/// }
592/// @endcode
593/// Now that the data has been (quickly) gathered, we can indulge in analysis
594/// that is more time consuming. For example, we can define a comparison
595/// function, copy the data to another container (e.g., `bsl::vector`), sort the
596/// entries, and determine the 20 most commonly used words in the given
597/// documents:
598/// @code
599/// /// Assignable equivalent to `WordTally::value_type`. Note that
600/// /// `bsl::vector` requires assignable types.
601/// typedef bsl::pair<bsl::string, int> WordTallyEntry;
602///
603/// struct WordTallyEntryCompare {
604/// static bool lessValue(const WordTallyEntry& a,
605/// const WordTallyEntry& b) {
606/// return a.second < b.second;
607/// }
608/// static bool moreValue(const WordTallyEntry& a,
609/// const WordTallyEntry& b) {
610/// return !lessValue(a, b);
611/// }
612/// };
613///
614/// bsl::vector<WordTallyEntry> array(wordTally.cbegin(), wordTally.cend());
615///
616/// assert(20 <= array.size());
617///
618/// std::partial_sort(array.begin(),
619/// array.begin() + 20,
620/// array.end(),
621/// WordTallyEntryCompare::moreValue);
622/// @endcode
623/// Notice that @ref partial_sort suffices here since we seek only the 20 most used
624/// words, not a complete distribution of word counts.
625///
626/// Finally, we print the sorted portion of `array`:
627/// @code
628/// for (bsl::vector<WordTallyEntry>::const_iterator cur = array.begin(),
629/// end = cur + 20;
630/// end != cur; ++cur) {
631/// printf("%-10s %4d\n", cur->first.c_str(), cur->second);
632/// }
633/// @endcode
634/// and standard output shows:
635/// @code
636/// the 463
637/// - 398
638/// of 361
639/// and 349
640/// to 306
641/// in 141
642/// or 106
643/// right 93
644/// be 90
645/// Article 86
646/// has 79
647/// a 76
648/// shall 69
649/// for 69
650/// by 62
651/// with 50
652/// Everyone 49
653/// rights 44
654/// their 44
655/// is 43
656/// @endcode
657/// Notice that "-" (used as an header underscore in our markup) appears in the
658/// word count. That could be eliminated by adding `-` to the set of
659/// delimiters; however, that would partition hyphenated words into separate
660/// words. In practice, one defines a "stop list" of common words (e.g., "the",
661/// "of", "and", "is") that one does not wish to tally. We could easily add "-"
662/// to the stop list.
663///
664/// ### Example 2: Examining and Setting Unordered Map Configuration {#bslstl_unorderedmap-example-2-examining-and-setting-unordered-map-configuration}
665///
666///
667/// Suppose we wish to examine (and possibly influence) the performance of an
668/// unordered map. The unordered map provides several interfaces that allow us
669/// to do so. Several of these were used in {Example 1} (code repeated below):
670/// @code
671/// WordTally wordTally;
672///
673/// printf("size %4d initial\n", wordTally.size());
674/// printf("bucket_count %4d initial\n", wordTally.bucket_count());
675/// printf("load_factor %f initial\n", wordTally.load_factor());
676/// printf("max_load_factor %f initial\n", wordTally.max_load_factor());
677/// @endcode
678/// First, we examine the metrics of this newly created (empty) unordered map:
679/// @code
680/// size 0 initial
681/// bucket_count 1 initial
682/// load_factor 0.000000 initial
683/// max_load_factor 1.000000 initial
684/// @endcode
685/// Notice that even when there are no elements (`size` is 0) there is one
686/// bucket. Since there are no elements, the average number of elements per
687/// bucket (the @ref load_factor above) must be 0.
688///
689/// Next, after `wordTally` has been loaded, we examine its metrics:
690/// @code
691/// printf("size %4d\n", wordTally.size());
692/// printf("bucket_count %4d\n", wordTally.bucket_count());
693/// printf("load_factor %f\n", wordTally.load_factor());
694/// printf("max_load_factor %f\n", wordTally.max_load_factor());
695/// @endcode
696/// and find at standard output:
697/// @code
698/// size 1504
699/// bucket_count 2099
700/// load_factor 0.716532
701/// max_load_factor 1.000000
702/// @endcode
703/// Notice how the number of buckets has increased. (Sampling this metric as
704/// the map was loaded would show that the increase was done in several stages.)
705///
706/// Then, we see that the load factor is indeed below the specified maximum;
707/// however we obtain further details of how the buckets are used.
708///
709/// Using the @ref bucket_count method, the unordered map's interface for the
710/// number of elements in each bucket, we can easily determine the bucket with
711/// the greatest number of elements (i.e., the greatest number of collisions):
712/// @code
713/// bsl::vector<int> bucketSizes;
714/// bucketSizes.reserve(wordTally.bucket_count());
715///
716/// for (size_t idx = 0; idx < wordTally.bucket_count(); ++idx) {
717/// bucketSizes.push_back(static_cast<int>(wordTally.bucket_size(idx)));
718/// }
719///
720/// assert(0 < bucketSizes.size());
721/// int maxBucketSize = *std::max_element(bucketSizes.begin(),
722/// bucketSizes.end());
723/// printf("maxBucketSize %4d\n", maxBucketSize);
724/// @endcode
725/// and find on standard output:
726/// @code
727/// maxBucketSize 5
728/// @endcode
729/// We can also count the number of empty buckets, and the number of buckets at
730/// `maxBucketSize`.
731/// @code
732/// int numEmptyBuckets = static_cast<int>(std::count(bucketSizes.begin(),
733/// bucketSizes.end(),
734/// 0));
735/// printf("numEmptyBuckets %4d\n", numEmptyBuckets);
736///
737/// int numMaxBuckets = static_cast<int>(std::count(bucketSizes.begin(),
738/// bucketSizes.end(),
739/// maxBucketSize));
740/// printf("numMaxBuckets %4d\n", numMaxBuckets);
741/// @endcode
742/// which shows on standard output:
743/// @code
744/// numEmptyBuckets 1031
745/// numMaxBuckets 3
746/// @endcode
747/// Suppose we are not satisfied with this distribution. (Perhaps the load
748/// factor is too high.) We can create a second, differently configured table.
749///
750/// Next, create a new table `wordTally2` with twice the bucket count shown by
751/// the first table (`wordTally`), and examine its initial metrics.
752/// @code
753/// WordTally wordTally2(wordTally.bucket_count() * 2);
754///
755/// printf("size2 %4d initial\n", wordTally2.size());
756/// printf("bucket_count2 %4d initial\n", wordTally2.bucket_count());
757/// printf("load_factor2 %f initial\n", wordTally2.load_factor());
758/// printf("max_load_factor2 %f initial\n", wordTally2.max_load_factor());
759/// @endcode
760/// Standard output shows:
761/// @code
762/// size2 0 initial
763/// bucket_count2 4201 initial
764/// load_factor2 0.000000 initial
765/// max_load_factor2 1.000000 initial
766/// @endcode
767/// Notice that although we requested 4198 buckets (2 * 2099), we created a
768/// table with 4201 buckets. (4201 is the smallest prime number greater than
769/// 4198).
770///
771/// Then, we load our new table and examine its metrics. For simplicity, we
772/// load data from the first table rather than re-tokenize our documents.
773/// @code
774/// wordTally2 = wordTally;
775///
776/// printf("size2 %4d\n", wordTally2.size());
777/// printf("bucket_count2 %4d\n", wordTally2.bucket_count());
778/// printf("load_factor2 %f\n", wordTally2.load_factor());
779/// printf("max_load_factor2 %f\n", wordTally2.max_load_factor());
780///
781/// bsl::vector<int> bucketSizes2;
782/// bucketSizes2.reserve(wordTally2.bucket_count());
783///
784/// for (size_t idx = 0; idx < wordTally2.bucket_count(); ++idx) {
785/// bucketSizes2.push_back(static_cast<int>(wordTally2.bucket_size(idx)));
786/// }
787///
788/// assert(0 < bucketSizes2.size());
789/// int maxBucketSize2 = *std::max_element(bucketSizes2.begin(),
790/// bucketSizes2.end());
791/// printf("maxBucketSize2 %4d\n", maxBucketSize2);
792///
793/// int numEmptyBuckets2 = static_cast<int>(std::count(bucketSizes2.begin(),
794/// bucketSizes2.end(),
795/// 0));
796/// printf("numEmptyBuckets2 %4d\n", numEmptyBuckets2);
797///
798/// int numMaxBuckets2 = static_cast<int>(std::count(bucketSizes2.begin(),
799/// bucketSizes2.end(),
800/// maxBucketSize2));
801/// printf("numMaxBuckets2 %4d\n", numMaxBuckets2);
802/// @endcode
803/// Finally, we see on standard output:
804/// @code
805/// size2 1504
806/// bucket_count2 4201
807/// load_factor2 0.358010
808/// max_load_factor2 1.000000
809/// maxBucketSize2 4
810/// numEmptyBuckets2 2971
811/// numMaxBuckets2 5
812/// @endcode
813/// Notice that the loading factor has been (roughly) cut in half; we have
814/// achieved our goal. Also notice that the bucket count is unchanged since
815/// construction; thus, there were no rehashes during the loading this unordered
816/// map. Finally, notice that the number of empty (unused) buckets is
817/// significantly higher, and there's been a modest decrease in the largest
818/// bucket size, but more instances of them.
819///
820/// Thus, the unordered map provides facilities by which we can make trade-offs
821/// in performance characteristics of the containers we create.
822///
823/// ### Example 3: Inverse Concordance {#bslstl_unorderedmap-example-3-inverse-concordance}
824///
825///
826/// If one has a concordance for a set of documents (an index of the position of
827/// every unique word in those documents), then words of interest can be
828/// efficiently located. Suppose after locating a word of interest one also
829/// needs the surrounding words (for context). Searching in the original
830/// document requires re-tokenization (time consuming). Alternatively, one can
831/// use the concordance to create an inverse concordance to provide a fast
832/// lookup of the words at given locations in a document and then examine words
833/// near the word of interest.
834///
835/// First, we define the types required (and convenient aliases) to create an
836/// unordered map from a word location to the corresponding word. The "key"
837/// value will be `WordLocation`, a pair of `int` values: the first being the
838/// document code number (arbitrarily assigned), and second the word offset in
839/// that document (the first word of the document is at offset 0). The "mapped"
840/// value of each entry is a `bsl::string` containing the word at that location.
841/// @code
842/// /// Document code number (`first`) and word offset (`second`) in that
843/// /// document specify a word location. The first word in the document
844/// /// is at word offset 0.
845/// typedef bsl::pair<int, int> WordLocation;
846/// @endcode
847/// Notice that the `WordLocation`, the type of the key value, has no natural
848/// ordering. The assignment of document codes is arbitrary so there is no
849/// reason to consider the words on one document to sort below those in any
850/// another.
851///
852/// Then, since there is no default hash function for the `WordLocation` type,
853/// we define one. The document code and the word offset are individually
854/// hashed using the default hasher for the `int` type and those results bitwise
855/// exclusive OR-ed a combined result. This trivial combination formula
856/// suffices for this problem, but is *not* a general solution for combining
857/// hashes; see {Practical Requirements on `HASH`}.
858/// @code
859/// class WordLocationHash
860/// {
861/// private:
862/// WordLocationHash& operator=(const WordLocationHash& rhs);
863///
864/// public:
865/// // CREATORS
866///
867/// /// Create a `WordLocationHash` object.
868/// //! WordLocationHash() = default;
869///
870/// /// Create a `WordLocationHash` object. Note that as
871/// /// `WordLocationHash` is an empty (stateless) type, this operation
872/// /// has no observable effect.
873/// //! WordLocationHash(const WordLocationHash& original) = default;
874///
875/// /// Destroy this object.
876/// //! ~WordLocationHash() = default;
877///
878/// // ACCESSORS
879///
880/// /// Return a hash value computed using the specified `x`.
881/// std::size_t operator()(WordLocation x) const
882/// {
883/// bsl::hash<int> hasher;
884/// return hasher(x.first) ^ hasher(x.second);
885/// }
886/// };
887/// @endcode
888/// Notice that many of the required methods of the hash type are compiler
889/// generated. (The declaration of those methods are commented out and suffixed
890/// by an `= default` comment.)
891///
892/// In addition to a hash functor, the unordered map requires an equality
893/// comparison functor. In this example, the unordered map uses `operator==`
894/// method of `std::pair` by default. If the mapped type has no such method, a
895/// equality-comparison functor must be provided explicitly.
896///
897/// Next, we define the type of the unordered map and associated convenience
898/// aliases:
899/// @code
900/// typedef bsl::unordered_map<WordLocation, bsl::string, WordLocationHash>
901/// InverseConcordance;
902///
903/// typedef InverseConcordance::const_iterator InverseConcordanceConstItr;
904/// @endcode
905/// Next, we obtain a concordance for the document set (see
906/// {@ref bslstl_unorderedmultimap |Example 1}). Here, the concordance is provided
907/// as a statically initialized array:
908/// @code
909/// const static struct {
910/// const char *d_word;
911/// int d_documentCode;
912/// int d_wordOffset;
913/// } concordance[] = {
914/// { "extent", 2, 3597 }, { "to", 2, 1225 },
915/// ...
916/// { "to", 2, 1252 }, { "Every", 2, 1049 }
917/// };
918/// const int numConcordance = sizeof concordance/sizeof *concordance;
919/// @endcode
920/// Then, we create `inverseConcordance`, an unordered map, and initialize it
921/// with values obtained from `concordance`.
922/// @code
923/// InverseConcordance inverseConcordance;
924///
925/// for (int idx = 0; idx < numConcordance; ++idx) {
926/// bsl::string word = concordance[idx].d_word;
927/// int documentCode = concordance[idx].d_documentCode;
928/// int wordOffset = concordance[idx].d_wordOffset;
929///
930/// WordLocation location(documentCode, wordOffset);
931/// InverseConcordance::value_type value(location, word);
932/// bool status =
933/// inverseConcordance.insert(value).second;
934/// assert(status);
935/// }
936/// @endcode
937/// Notice that we expect every `insert` to be successful, as the concordance
938/// should not show more than one word at any location.
939///
940/// Next, suppose we knew the location of the word "unalienable" in the document
941/// set (see {@ref bslstl_unorderedmultimap |Example 1}) and want to know its
942/// context?
943/// @code
944/// "unalienable", 0, 109
945/// @endcode
946/// We use the `find` method of `inverseConcordance` to determine the words
947/// within offset `delta` of "unalienable". Note that we must check the
948/// validity of the returned iterator, in case we probe beyond the boundaries of
949/// the document.
950/// @code
951/// const int docCode = 0;
952/// const int origin = 109;
953/// const int delta = 16;
954///
955/// for (int offset = origin - delta; offset < origin + delta; ++offset) {
956/// WordLocation location(docCode, offset);
957/// InverseConcordanceConstItr itr = inverseConcordance.find(location);
958///
959/// if (inverseConcordance.end() != itr) {
960/// printf("%d %4d: %s\n",
961/// itr->first.first,
962/// itr->first.second,
963/// itr->second.c_str());
964/// assert(origin != offset
965/// || bsl::string("unalienable") == itr->second);
966/// }
967/// }
968/// @endcode
969/// Notice that the assertion confirms that "unalienable" is found in our
970/// inverse location at the location we obtained from the concordance.
971///
972/// Finally, we find on standard output:
973/// @code
974/// 0 93: evident
975/// 0 94: that
976/// 0 95: all
977/// 0 96: men
978/// 0 97: are
979/// 0 98: created
980/// 0 99: equal
981/// 0 100: that
982/// 0 101: they
983/// 0 102: are
984/// 0 103: endowed
985/// 0 104: by
986/// 0 105: their
987/// 0 106: Creator
988/// 0 107: with
989/// 0 108: certain
990/// 0 109: unalienable
991/// 0 110: Rights
992/// 0 111: that
993/// 0 112: among
994/// 0 113: these
995/// 0 114: are
996/// 0 115: Life
997/// 0 116: Liberty
998/// 0 117: and
999/// 0 118: the
1000/// 0 119: pursuit
1001/// 0 120: of
1002/// 0 121: Happiness
1003/// 0 122: That
1004/// 0 123: to
1005/// 0 124: secure
1006/// @endcode
1007/// @}
1008/** @} */
1009/** @} */
1010
1011/** @addtogroup bsl
1012 * @{
1013 */
1014/** @addtogroup bslstl
1015 * @{
1016 */
1017/** @addtogroup bslstl_unorderedmap
1018 * @{
1019 */
1020
1021#include <bslscm_version.h>
1022
1023#include <bslstl_algorithm.h>
1024#include <bslstl_equalto.h>
1025#include <bslstl_hash.h>
1026#include <bslstl_hashtable.h>
1029#include <bslstl_iteratorutil.h>
1030#include <bslstl_pair.h>
1031#include <bslstl_ranges.h>
1032#include <bslstl_stdexceptutil.h>
1034
1037
1038#include <bslma_allocatortraits.h>
1039#include <bslma_allocatortraits.h>
1040#include <bslma_destructorguard.h>
1041#include <bslma_isstdallocator.h>
1042#include <bslma_bslallocator.h>
1044
1046#include <bslmf_assert.h>
1048#include <bslmf_enableif.h>
1050#include <bslmf_isconvertible.h>
1051#include <bslmf_movableref.h>
1053#include <bslmf_typeidentity.h>
1054#include <bslmf_util.h> // 'forward(V)'
1055
1056#include <bsls_assert.h>
1057#include <bsls_compilerfeatures.h>
1058#include <bsls_keyword.h>
1059#include <bsls_libraryfeatures.h>
1060#include <bsls_objectbuffer.h>
1061#include <bsls_performancehint.h>
1062#include <bsls_platform.h>
1063#include <bsls_util.h> // 'forward<T>(V)'
1064
1065#include <cstddef> // NULL
1066
1067#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1068# include <initializer_list>
1069#endif
1070
1071#ifdef BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER
1072#include <type_traits> // 'std::is_constructible'
1073 #ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1074 #error Rvalue references curiously absent despite native 'type_traits'.
1075 #endif
1076#endif
1077
1078#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1079 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1080# define BSLSTL_UNORDEREDMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T) \
1081 requires ::BloombergLP::bslmf::ContainerCompatibleRange<R, T>
1082#else
1083# define BSLSTL_UNORDEREDMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
1084#endif
1085
1086#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1087// clang-format off
1088// Include version that can be compiled with C++03
1089// Generated on Mon Jan 13 08:31:39 2025
1090// Command line: sim_cpp11_features.pl bslstl_unorderedmap.h
1091
1092# define COMPILING_BSLSTL_UNORDEREDMAP_H
1094# undef COMPILING_BSLSTL_UNORDEREDMAP_H
1095
1096// clang-format on
1097#else
1098
1099namespace bsl {
1100
1101 // ===================
1102 // class unordered_map
1103 // ===================
1104
1105/// This class template implements a value-semantic container type holding
1106/// an unordered set of `KEY-VALUE` pairs having unique keys that provide a
1107/// mapping from keys (of template parameter type `KEY`) to their associated
1108/// mapped values (of template parameter type `VALUE`).
1109///
1110/// This class:
1111/// * supports a complete set of *value-semantic* operations
1112/// * is *exception-neutral* (agnostic except for the `at` method)
1113/// * is *alias-safe*
1114/// * is `const` *thread-safe*
1115/// For terminology see @ref bsldoc_glossary .
1116///
1117/// See @ref bslstl_unorderedmap
1118template <class KEY,
1119 class VALUE,
1120 class HASH = bsl::hash<KEY>,
1121 class EQUAL = bsl::equal_to<KEY>,
1122 class ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE> > >
1124
1125 private:
1126 // PRIVATE TYPES
1127
1128 /// This `typedef` is an alias for the allocator traits type associated
1129 /// with this container.
1131
1132 /// This `typedef` is an alias for the type of key-value pair objects
1133 /// maintained by this unordered map.
1134 typedef bsl::pair<const KEY, VALUE> ValueType;
1135
1136 /// This `typedef` is an alias for the policy used internally by this
1137 /// unordered map to extract the `KEY` value from the key-value pair
1138 /// objects maintained by this unordered map.
1139 typedef BloombergLP::bslstl::UnorderedMapKeyConfiguration<const KEY,
1140 ValueType>
1141 ListConfiguration;
1142
1143 /// This typedef is an alias for the template instantiation of the
1144 /// underlying `bslstl::HashTable` used to implement this container.
1145 typedef BloombergLP::bslstl::HashTable<ListConfiguration,
1146 HASH,
1147 EQUAL,
1148 ALLOCATOR> HashTable;
1149
1150 /// This typedef is an alias for the type of links maintained by the
1151 /// linked list of elements held by the underlying `bslstl::HashTable`.
1152 typedef BloombergLP::bslalg::BidirectionalLink HashTableLink;
1153
1154 /// This typedef is an alias for the type of nodes that hold the values
1155 /// in this unordered map.
1156 typedef typename HashTable::NodeType HashTableNode;
1157
1158 /// This typedef is a convenient alias for the utility associated with
1159 /// movable references.
1160 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
1161
1162 // FRIENDS
1163 template <class KEY2,
1164 class VALUE2,
1165 class HASH2,
1166 class EQUAL2,
1167 class ALLOCATOR2>
1168 friend bool operator==(
1171
1172 // PRIVATE MANIPULATORS
1173
1174 /// Insert the values between the specified `first` and `last` into an
1175 /// initially empty set.
1176 template <class INPUT_ITERATOR, class SENTINEL>
1177 void constructFromRange(INPUT_ITERATOR first, SENTINEL last);
1178
1179#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1180 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1181
1182 /// Insert the values between the specified `first` and `last` into an
1183 /// initially empty set. The specified `numElements` is used to improve performance.
1184 ///
1185 /// \pre The behavior is undefined if the iterators support
1186 /// the calculation of distance and `numElements` is not the distance
1187 /// from `first` to `last`.
1188 template <class INPUT_ITERATOR, class SENTINEL>
1189 void constructFromRange(INPUT_ITERATOR first,
1190 SENTINEL last,
1191 size_t numElements);
1192#endif
1193
1194 /// Insert the values between the specified `first` and `last` into this
1195 /// set.
1196 template <class INPUT_ITERATOR, class SENTINEL>
1197 void insertFromRange(INPUT_ITERATOR first, SENTINEL last);
1198
1199#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1200 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1201
1202 /// Insert the values between the specified `first` and `last` into this
1203 /// set. The specified `numElements` is used to improve performance.
1204 ///
1205 /// \pre The behavior is undefined if the iterators support the calculation of
1206 /// distance and `numElements` is not the distance from `first` to `last`.
1207 template <class INPUT_ITERATOR, class SENTINEL>
1208 void insertFromRange(INPUT_ITERATOR first,
1209 SENTINEL last,
1210 size_t numElements);
1211#endif
1212
1213 public:
1214 // TRAITS
1215
1216 // PUBLIC TYPES
1217 typedef KEY key_type;
1218 typedef VALUE mapped_type;
1220 typedef HASH hasher;
1221 typedef EQUAL key_equal;
1222 typedef ALLOCATOR allocator_type;
1223
1226
1231
1232 typedef BloombergLP::bslstl::HashTableIterator<
1234 typedef BloombergLP::bslstl::HashTableIterator<
1236 typedef BloombergLP::bslstl::HashTableBucketIterator<
1238 typedef BloombergLP::bslstl::HashTableBucketIterator<
1240
1241 private:
1242 // DATA
1243 HashTable d_impl; // underlying hash table used by this unordered map
1244
1245 public:
1246 // CREATORS
1247
1248 /// Create an empty unordered map having a @ref max_load_factor of 1.0.
1249 /// Optionally specify an `initialNumBuckets` indicating the minimum
1250 /// initial size of the array of buckets of this unordered map. If
1251 /// `initialNumBuckets` is not supplied, one empty bucket shall be used
1252 /// and no memory allocated. Optionally specify a `hashFunction` used
1253 /// to generate the hash values associated with the `KEY-VALUE` pairs
1254 /// contained in this unordered map. If `hashFunction` is not supplied,
1255 /// a default-constructed object of the (template parameter) type `HASH`
1256 /// is used. Optionally specify a key-equality functor `keyEqual` used
1257 /// to determine whether two keys are equivalent. If `keyEqual` is not
1258 /// supplied, a default-constructed object of the (template parameter)
1259 /// type `EQUAL` is used. Optionally specify the `basicAllocator` used
1260 /// to supply memory. If `basicAllocator` is not supplied, a
1261 /// default-constructed object of the (template parameter) type
1262 /// `ALLOCATOR` is used. If the `ALLOCATOR` type is `bsl::allocator`
1263 /// (the default), then `basicAllocator` shall be convertible to
1264 /// `bslma::Allocator *`. If the `ALLOCATOR` type is `bsl::allocator`
1265 /// and `basicAllocator` is not supplied, the currently installed default allocator is used to supply memory.
1266 ///
1267 /// \note Note that more than
1268 /// `initialNumBuckets` buckets may be created in order to preserve the
1269 /// bucket allocation strategy of the hash-table (but never fewer).
1270 explicit
1271 unordered_map(size_type initialNumBuckets,
1272 const HASH& hashFunction = HASH(),
1273 const EQUAL& keyEqual = EQUAL(),
1274 const ALLOCATOR& basicAllocator = ALLOCATOR());
1275 unordered_map(size_type initialNumBuckets,
1276 const HASH& hashFunction,
1277 const ALLOCATOR& basicAllocator);
1278 unordered_map(size_type initialNumBuckets,
1279 const ALLOCATOR& basicAllocator);
1280 explicit
1281 unordered_map(const ALLOCATOR& basicAllocator);
1283
1284 /// Create an empty unordered map, having a @ref max_load_factor of 1.0,
1285 /// and then create a `value_type` object for each iterator in the range
1286 /// starting at the specified `first` iterator and ending immediately
1287 /// before the specified `last` iterator, by converting from the object
1288 /// referred to by each iterator. Insert into this unordered map each
1289 /// such object, ignoring those having a key that appears earlier in the
1290 /// sequence. Optionally specify a minimum `initialNumBuckets`
1291 /// indicating the minimum initial size of the array of buckets of this
1292 /// unordered map. If `initialNumBuckets` is 0 or not supplied, and
1293 /// `first` and `last` denote an empty range, a single empty bucket
1294 /// shall be supplied. The actual number of buckets the unordered_map
1295 /// is created with shall always be enough to accommodate the number of
1296 /// elements of the range without exceeding the @ref max_load_factor .
1297 /// Optionally specify a `hashFunction` used to generate hash values
1298 /// associated with the `KEY-VALUE` pairs contained in this unordered
1299 /// map. If `hashFunction` is not supplied, a default-constructed
1300 /// object of the (template parameter) type `HASH` is used. Optionally
1301 /// specify a key-equality functor `keyEqual` used to verify that two
1302 /// keys are equivalent. If `keyEqual` is not supplied, a
1303 /// default-constructed object of the (template parameter) type `EQUAL`
1304 /// is used. Optionally specify a `basicAllocator` used to supply
1305 /// memory. If `basicAllocator` is not supplied, a default-constructed
1306 /// object of the (template parameter) type `ALLOCATOR` is used. If
1307 /// `ALLOCATOR` type is `bsl::allocator` (the default), then
1308 /// `basicAllocator` shall be convertible to `bslma::Allocator *`. If
1309 /// the `ALLOCATOR` type is `bsl::allocator` and `basicAllocator` is not
1310 /// supplied, the currently installed default allocator is used to
1311 /// supply memory. The (template parameter) type `INPUT_ITERATOR` shall
1312 /// meet the requirements of an input iterator defined in the C++11
1313 /// standard [24.2.3] providing access to values of a type convertible to `value_type`.
1314 ///
1315 /// \pre The behavior is undefined unless `first` and
1316 /// `last` refer to a sequence of valid values where `first` is at a position at or before `last`.
1317 ///
1318 /// \note Note that more than
1319 /// `initialNumBuckets` buckets may be created in order to preserve the
1320 /// bucket allocation strategy of the hash-table (but never fewer).
1321 template <class INPUT_ITERATOR>
1322 unordered_map(INPUT_ITERATOR first,
1323 INPUT_ITERATOR last,
1324 size_type initialNumBuckets = 0,
1325 const HASH& hashFunction = HASH(),
1326 const EQUAL& keyEqual = EQUAL(),
1327 const ALLOCATOR& basicAllocator = ALLOCATOR());
1328 template <class INPUT_ITERATOR>
1329 unordered_map(INPUT_ITERATOR first,
1330 INPUT_ITERATOR last,
1331 size_type initialNumBuckets,
1332 const HASH& hashFunction,
1333 const ALLOCATOR& basicAllocator);
1334 template <class INPUT_ITERATOR>
1335 unordered_map(INPUT_ITERATOR first,
1336 INPUT_ITERATOR last,
1337 size_type initialNumBuckets,
1338 const ALLOCATOR& basicAllocator);
1339 template <class INPUT_ITERATOR>
1340 unordered_map(INPUT_ITERATOR first,
1341 INPUT_ITERATOR last,
1342 const ALLOCATOR& basicAllocator);
1343
1344#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1345# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1346 template <
1347 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
1348 class = bsl::enable_if_t<
1349 std::is_invocable_v<EQUAL, const KEY &, const KEY &>>,
1350 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
1351 >
1352# endif
1354 std::initializer_list<value_type> values,
1355 size_type initialNumBuckets = 0,
1356 const HASH& hashFunction = HASH(),
1357 const EQUAL& keyEqual = EQUAL(),
1358 const ALLOCATOR& basicAllocator = ALLOCATOR());
1359# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1360 template <
1361 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
1362 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
1363 >
1364# endif
1365 unordered_map(std::initializer_list<value_type> values,
1366 size_type initialNumBuckets,
1367 const HASH& hashFunction,
1368 const ALLOCATOR& basicAllocator);
1369# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1370 template <
1371 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
1372 >
1373# endif
1374 unordered_map(std::initializer_list<value_type> values,
1375 size_type initialNumBuckets,
1376 const ALLOCATOR& basicAllocator);
1377# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1378 /// Create an empty unordered map, having a @ref max_load_factor of 1.0,
1379 /// and then create a `value_type` object for each in the range
1380 /// specified by `values` argument, ignoring elements having a key that
1381 /// appears earlier in the sequence. Optionally specify a minimum
1382 /// `initialNumBuckets` indicating the minimum initial size of the array
1383 /// of buckets of this unordered map. If `initialNumBuckets` is not
1384 /// supplied and `values` is an empty list, a single empty bucket shall
1385 /// be created. The actual number of buckets the unordered_map is
1386 /// created with shall always be enough to accommodate the number of
1387 /// elements in `values` without exceeding the @ref max_load_factor .
1388 /// Optionally specify a `hashFunction` used to generate hash values
1389 /// associated with the `KEY-VALUE` pairs contained in this unordered
1390 /// map. If `hashFunction` is not supplied, a default-constructed
1391 /// object of the (template parameter) type `HASH` is used. Optionally
1392 /// specify a key-equality functor `keyEqual` used to verify that two
1393 /// keys are equivalent. If `keyEqual` is not supplied, a
1394 /// default-constructed object of the (template parameter) type `EQUAL`
1395 /// is used. Optionally specify a `basicAllocator` used to supply
1396 /// memory. If `basicAllocator` is not supplied, a default-constructed
1397 /// object of the (template parameter) type `ALLOCATOR` is used. If the
1398 /// `ALLOCATOR` type is `bsl::allocator` (the default), then
1399 /// `basicAllocator` shall be convertible to `bslma::Allocator *`. If
1400 /// the `ALLOCATOR` type is `bsl::allocator` and `basicAllocator` is not
1401 /// supplied, the currently installed default allocator is used to supply memory.
1402 ///
1403 /// \note Note that more than `initialNumBuckets` buckets may
1404 /// be created in order to preserve the bucket allocation strategy of
1405 /// the hash-table (but never fewer).
1406 template <
1407 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
1408 >
1409# endif
1410 unordered_map(std::initializer_list<value_type> values,
1411 const ALLOCATOR& basicAllocator);
1412#endif
1413
1414 /// Create an unordered set, and insert each `value_type` object in the
1415 /// specified `range`, ignoring those keys having a key equivalent to
1416 /// that which appears earlier in the `range`. Optionally specify an
1417 /// `initialNumBuckets` indicating the initial size of the array of
1418 /// buckets of this container. If `initialNumBuckets` is not supplied,
1419 /// an implementation-defined value is used. Optionally specify a
1420 /// `hashFunction` used to generate the hash values for each key value
1421 /// contained in this set. If `hashFunction` is not supplied, a
1422 /// default-constructed object of the (template parameter) type `HASH`
1423 /// is used. Optionally specify a key-equality functor `keyEqual` used
1424 /// to determine whether two keys have the same value. If `keyEqual` is
1425 /// not supplied, a default-constructed object of the (template
1426 /// parameter) type `EQUAL` is used. Optionally specify a
1427 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1428 /// supplied, a default-constructed object of the (template parameter)
1429 /// type `ALLOCATOR` is used. If the type `ALLOCATOR` is
1430 /// `bsl::allocator` (the default), then `basicAllocator`, if supplied,
1431 /// shall be convertible to `bslma::Allocator *`. If the type
1432 /// `ALLOCATOR` is `bsl::allocator` and `basicAllocator` is not
1433 /// supplied, the currently installed default allocator is used. This
1434 /// operation has `O[N]` complexity, where `N` is the number of elements in `range`.
1435 ///
1436 /// \note Note that `RANGE` must meet the requirements of an
1437 /// input range and the values from `range` must have a type matching or
1438 /// convertible to `value_type`.
1439 template <class RANGE>
1442 bsl::from_range_t ,
1443 BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range,
1444 size_type initialNumBuckets = 0,
1445 const HASH& hashFunction = HASH(),
1446 const EQUAL& keyEqual = EQUAL(),
1447 const ALLOCATOR& basicAllocator = ALLOCATOR())
1448 : d_impl(hashFunction,
1449 keyEqual,
1450 initialNumBuckets,
1451 1.0f,
1452 basicAllocator)
1453 {
1454 // Defined inline to avoid `clang` and Windows errors.
1455#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1456 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1457 if constexpr (ranges::sized_range<RANGE>) {
1458 constructFromRange(bsl::ranges::begin(range),
1459 bsl::ranges::end (range),
1460 bsl::ranges::size (range));
1461 } else // ...
1462#endif
1463 {
1464 constructFromRange(bsl::ranges::begin(range),
1465 bsl::ranges::end (range));
1466 }
1467 }
1468
1469 template <class RANGE>
1473 size_type initialNumBuckets,
1474 const HASH& hashFunction,
1475 const ALLOCATOR& basicAllocator)
1476 : d_impl(hashFunction, EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
1477 {
1478 // Defined inline to avoid `clang` error.
1479
1481 range,
1482 initialNumBuckets,
1483 hashFunction,
1484 EQUAL(),
1485 basicAllocator);
1486 this->swap(other);
1487 }
1488
1489 template <class RANGE>
1493 size_type initialNumBuckets,
1494 const ALLOCATOR& basicAllocator)
1495 : d_impl(HASH(), EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
1496 {
1497 // Defined inline to avoid `clang` error.
1498
1500 range,
1501 initialNumBuckets,
1502 HASH(),
1503 EQUAL(),
1504 basicAllocator);
1505 this->swap(other);
1506 }
1507
1508 template <class RANGE>
1512 const ALLOCATOR& basicAllocator)
1513 : d_impl(HASH(), EQUAL(), 0, 1.0f, basicAllocator)
1514 {
1515 // Defined inline to avoid `clang` error.
1516
1518 range,
1519 0,
1520 HASH(),
1521 EQUAL(),
1522 basicAllocator);
1523 this->swap(other);
1524 }
1525
1526 /// Create an unordered map having the same value, hasher, key-equality
1527 /// comparator, and @ref max_load_factor as the specified `original`. Use
1528 /// the allocator returned by 'bsl::allocator_traits<ALLOCATOR>::
1529 /// select_on_container_copy_construction(original.get_allocator())' to
1530 /// supply memory. If the `ALLOCATOR` type is `bsl::allocator` (the
1531 /// default), the currently installed default allocator is used to
1532 /// supply memory.
1534
1535 /// Create an unordered map having the same value, hasher, key-equality
1536 /// comparator, and @ref max_load_factor as the specified `original`, and
1537 /// using the specified `basicAllocator` to supply memory. If the
1538 /// `ALLOCATOR` type is `bsl::allocator` (the default), then
1539 /// `basicAllocator` shall be convertible to `bslma::Allocator *`.
1541 const unordered_map& original,
1542 const typename type_identity<ALLOCATOR>::type& basicAllocator);
1543
1544 /// Create an unordered map having the same value as the specified
1545 /// `original` object by moving (in constant time) the contents of
1546 /// `original` to the new unordered map. Use a copy of
1547 /// `original.hash_function()` to generate hash values for the keys
1548 /// contained in this unordered map. Use a copy of `original.key_eq()`
1549 /// to verify that two keys are equivalent. The allocator associated
1550 /// with `original` is propagated for use in the newly-created unordered
1551 /// map. `original` is left in a valid but unspecified state.
1553 BloombergLP::bslmf::MovableRef<unordered_map> original); // IMPLICIT
1554
1555 /// Create an unordered map having the same value, hasher, key-equality
1556 /// comparator, and @ref max_load_factor as the specified `original`. Use
1557 /// the specified `basicAllocator` to supply memory. This method
1558 /// requires that the (template parameter) type `value_type` be
1559 /// `move-insertable` into this `unordered_map` (see {Requirements on `value_type`}).
1560 ///
1561 /// \note Note that a `bslma::Allocator *` can be supplied
1562 /// for `basicAllocator` if the (template parameter) `ALLOCATOR` type is
1563 /// `bsl::allocator` (the default).
1565 BloombergLP::bslmf::MovableRef<unordered_map> original,
1566 const typename type_identity<ALLOCATOR>::type& basicAllocator);
1567
1568 /// Destroy this object and each of its elements.
1570
1571 // MANIPULATORS
1572
1573 /// Assign to this object the value, hasher, key-equality functor, and
1574 /// @ref max_load_factor of the specified `rhs` object, propagate to this
1575 /// object the allocator of `rhs` if the `ALLOCATOR` type has trait
1576 /// @ref propagate_on_container_copy_assignment , and return a reference providing modifiable access to this object.
1577 ///
1578 /// \note Note that this method
1579 /// requires that the (template parameter) types `KEY` and `VALUE` both
1580 /// be `copy-constructible` (see {Requirements on `value_type`}).
1582
1583 /// Assign to this object the value, hash function, and key-equality
1584 /// comparator of the specified `rhs` object, propagate to this object
1585 /// the allocator of `rhs` if the `ALLOCATOR` type has trait
1586 /// @ref propagate_on_container_move_assignment , and return a reference
1587 /// providing modifiable access to this object. The contents of `rhs`
1588 /// are moved (in constant time) to this unordered map if
1589 /// `get_allocator() == rhs.get_allocator()` (after accounting for the
1590 /// aforementioned trait); otherwise, all elements in this container are
1591 /// either destroyed or move-assigned to, and each additional element in
1592 /// `rhs` is move-inserted into this unordered_map. `rhs` is left in a
1593 /// valid but unspecified state, and if an exception is thrown, `*this`
1594 /// is left in a valid but unspecified state. This method requires that
1595 /// the type `value_type` be `move-constructible` (see {Requirements on
1596 /// `value_type`}).
1598 operator=(BloombergLP::bslmf::MovableRef<unordered_map> rhs)
1600 AllocatorTraits::is_always_equal::value &&
1601 std::is_nothrow_move_assignable<HASH>::value &&
1602 std::is_nothrow_move_assignable<EQUAL>::value);
1603
1604#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1605 /// Assign to this unordered map the value of the of the specified
1606 /// initializer list `rhs`, and return a reference providing modifiable
1607 /// access to this object. This method requires that the (template
1608 /// parameter) type `value_type` be `copy-insertable` into this list.
1609 unordered_map& operator=(std::initializer_list<value_type> rhs);
1610#endif
1611
1612 /// Return a reference providing modifiable access to the mapped-value
1613 /// associated with the specified `key` in this unordered map; if this
1614 /// unordered map does not already contain a `value_type` object with
1615 /// `key`, first insert a new `value_type` object having `key` and a default-constructed `VALUE` object.
1616 ///
1617 /// \note Note that this method requires
1618 /// that the (template parameter) type `KEY` is `copy-constructible` and
1619 /// the (template parameter) `VALUE` is "default-constructible" (see
1620 /// {Requirements on `value_type`}).
1622
1623 /// Return a reference providing modifiable access to the mapped-value
1624 /// associated with the specified `key` in this unordered map; if this
1625 /// unordered map does not already contain a `value_type` object with
1626 /// `key`, first insert a new `value_type` object having `key` and a default-constructed `VALUE` object.
1627 ///
1628 /// \note Note that this method requires
1629 /// that the (template parameter) `VALUE` is "default-constructible" (see {Requirements on `value_type`}).
1630 ///
1631 /// \note Note that `key` may be
1632 /// modified; it is guaranteed to be left in a valid state.
1634 BloombergLP::bslmf::MovableRef<key_type> key);
1635
1636#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1637 /// Return a reference providing modifiable access to the mapped-value
1638 /// associated with a key that is equivalent with the specified `key`; if
1639 /// this `map` does not already contain a `value_type` object having an
1640 /// equivalent key, first insert a new `value_type` object having the
1641 /// move-inserted `key` and a default-constructed `VALUE` object, and
1642 /// return a reference to the newly mapped (default) value. This method
1643 /// requires that the (template parameter) type `KEY` be `move-insertable`
1644 /// into this map and the (template parameter) type `VALUE` be
1645 /// `default-insertable` into this map (see {Requirements on `KEY` and
1646 /// `VALUE`}).
1647 ///
1648 /// Note: implemented inline due to Sun CC compilation error.
1649 template <class LOOKUP_KEY>
1650 typename bsl::enable_if<
1651 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1652 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1653 typename add_lvalue_reference<VALUE>::type>::type
1654 operator [](LOOKUP_KEY&& key)
1655 {
1656 return try_emplace(
1657 BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key)).first->second;
1658 }
1659#endif
1660
1661 /// Return a reference providing modifiable access to the mapped-value
1662 /// associated with the specified `key`, if such an entry exists; otherwise throw `std::out_of_range` exception.
1663 ///
1664 /// \note Note that this
1665 /// method is not exception-neutral.
1667
1668 /// Return a reference providing modifiable access to the
1669 /// mapped-value associated with a key that is equivalent to the
1670 /// specified `key`, if such an entry exists; otherwise, throw a `std::out_of_range` exception.
1671 ///
1672 /// \note Note that this method may also throw
1673 /// a different kind of exception if the (user-supplied) comparator
1674 /// throws.
1675 ///
1676 /// Note: implemented inline due to Sun CC compilation error
1677 template <class LOOKUP_KEY>
1678 typename bsl::enable_if<
1679 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1680 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1681 typename add_lvalue_reference<VALUE>::type>::type
1682 at(const LOOKUP_KEY& key) {
1683 HashTableLink *node = d_impl.find(key);
1684
1685 if (!node) {
1686 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(
1687 "unordered_map<...>::at(LOOKUP_KEY): invalid key value");
1688 }
1689 return static_cast<HashTableNode *>(node)->value().second;
1690 }
1691
1692 /// Return an iterator providing modifiable access to the first
1693 /// `value_type` object in the sequence of `value_type` objects
1694 /// maintained by this unordered map, or the `end` iterator if this
1695 /// unordered map is empty.
1697
1698 /// Return an iterator providing modifiable access to the past-the-end
1699 /// position in the sequence of `value_type` objects maintained by this
1700 /// unordered map.
1702
1703 /// Return a local iterator providing modifiable access to the first
1704 /// `value_type` object in the sequence of `value_type` objects of the
1705 /// bucket having the specified `index` in the array of buckets
1706 /// maintained by this unordered map, or the `end(index)` iterator if the bucket is empty.
1707 ///
1708 /// \pre The behavior is undefined unless 'index <
1709 /// bucket_count()'.
1711
1712 /// Return a local iterator providing modifiable access to the
1713 /// past-the-end position in the sequence of `value_type` objects of the
1714 /// bucket having the specified `index` in the array of buckets maintained by this unordered map.
1715 ///
1716 /// \pre The behavior is undefined unless
1717 /// `index < bucket_count()`.
1719
1720 /// Remove all entries from this unordered map.
1721 /// \note Note that this
1722 /// unordered map will be empty after calling this method, but allocated
1723 /// memory may be retained for future use.
1725
1726#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1727 /// Insert into this unordered map a newly-created `value_type` object,
1728 /// constructed by forwarding `get_allocator()` (if required) and the
1729 /// specified (variable number of) `args` to the corresponding
1730 /// constructor of `value_type`, if a key equivalent to such a value
1731 /// does not already exist in this map; otherwise, this method has no
1732 /// effect (other than possibly creating a temporary `value_type`
1733 /// object). Return a pair whose `first` member is an iterator
1734 /// referring to the (possibly newly created and inserted) object in
1735 /// this map whose key is equivalent to that of an object constructed
1736 /// from `args`, and whose `second` member is `true` if a new value was
1737 /// inserted, and `false` if an equivalent key was already present.
1738 /// This method requires that the (template parameter) types `KEY` and
1739 /// `VALUE` both be `emplace-constructible` from `args` (see
1740 /// {Requirements on `value_type`}).
1741 template <class... Args>
1743
1744 /// Insert into this unordered map a newly-created `value_type` object,
1745 /// constructed by forwarding `get_allocator()` (if required) and the
1746 /// specified (variable number of) `args` to the corresponding
1747 /// constructor of `value_type`, if a key equivalent to such a value
1748 /// does not already exist in this map; otherwise, this method has no
1749 /// effect (other than possibly creating a temporary `value_type`
1750 /// object). Return an iterator referring to the (possibly newly
1751 /// created and inserted) object in this map whose key is equivalent to
1752 /// that of an object constructed from `args`. The average and worst
1753 /// case complexity of this operation is not affected by the specified
1754 /// `hint`. This method requires that the (template parameter) types
1755 /// `KEY` and `VALUE` both be `emplace-constructible` from `args` (see {Requirements on `value_type`}).
1756 ///
1757 /// \pre The behavior is undefined unless
1758 /// `hint` is an iterator in the range `[begin() .. end()]` (both endpoints included).
1759 ///
1760 /// \note Note that `hint` is ignored (other than
1761 /// possibly asserting its validity in some build modes).
1762 template <class... Args>
1763 iterator emplace_hint(const_iterator hint, Args&&... args);
1764#endif
1765
1766 /// Insert into this map the value of each `value_type` object in the
1767 /// specified `range` if a key equivalent to the object is not already
1768 /// contained in this set. The (template parameter) type `RANGE` must
1769 /// meet the requirements the C++20 standard [ranges] providing access
1770 /// to values of a type convertible to `value_type`, and `value_type`
1771 /// must be `emplace-constructible` from `*i` into this set, where `i`
1772 /// is a dereferenceable iterator obtained from `range` (see {Requirements on `KEY`}).
1773 ///
1774 /// \pre The behavior is undefined if `range`
1775 /// overlaps this map.
1776 template <class RANGE>
1779 {
1780 // Defined inline to avoid `clang` and Windows errors.
1781#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1782 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1783 if constexpr (ranges::sized_range<RANGE>) {
1784 insertFromRange(bsl::ranges::begin(range),
1785 bsl::ranges::end (range),
1786 bsl::ranges::size (range));
1787 } else // ...
1788#endif
1789 {
1790 insertFromRange(bsl::ranges::begin(range),
1791 bsl::ranges::end (range));
1792 }
1793 }
1794
1795 /// Remove from this unordered map the `value_type` object at the
1796 /// specified `position`, and return an iterator referring to the
1797 /// element immediately following the removed element, or to the
1798 /// past-the-end position if the removed element was the last element in
1799 /// the sequence of elements maintained by this unordered map. This
1800 /// method invalidates only iterators and references to the removed
1801 /// element and previously saved values of the `end()` iterator, and
1802 /// preserves the relative order of the elements not removed.
1803 ///
1804 /// \pre The behavior is undefined unless `position` refers to a `value_type`
1805 /// object in this unordered map.
1808
1809 /// Remove from this unordered map the `value_type` object having the
1810 /// specified `key`, if it exists, and return 1; otherwise (there is no
1811 /// object with a key equivalent to `key` in this unordered map) return
1812 /// 0 with no other effect. This method invalidates only iterators and
1813 /// references to the removed element and previously saved values of the
1814 /// `end()` iterator, and preserves the relative order of the elements
1815 /// not removed.
1817 template <class t_KEY>
1818 typename enable_if<
1819 BloombergLP::bslmf::IsTransparentPredicate<HASH, t_KEY>::value &&
1820 BloombergLP::bslmf::IsTransparentPredicate<EQUAL,t_KEY>::value &&
1822 iterator>::value &&
1824 const_iterator>::value,
1826 {
1827 // Implemented inline due to Sun CC compilation error.
1828 iterator it = this->find(key);
1829 if (it == end()) {
1830 return 0; // RETURN
1831 }
1832 erase(it);
1833 return 1;
1834 }
1835
1836 /// Remove from this unordered map the `value_type` objects starting at
1837 /// the specified `first` position up to, but not including, the
1838 /// specified `last` position, and return `last`. This method
1839 /// invalidates only iterators and references to the removed element and
1840 /// previously saved values of the `end()` iterator, and preserves the
1841 /// relative order of the elements not removed.
1842 ///
1843 /// \pre The behavior is undefined unless `first` and `last` either refer to elements in this
1844 /// unordered map or are the `end` iterator, and the `first` position is
1845 /// at or before the `last` position in the iteration sequence provided
1846 /// by this container.
1848
1849 /// Return an iterator providing modifiable access to the `value_type`
1850 /// object in this unordered map with a key equivalent to the specified
1851 /// `key`, if such an entry exists, and the past-the-end iterator (`end`) otherwise.
1852 ///
1853 /// \pre The behavior is undefined unless `key` is
1854 /// equivalent to the key of at most one element in this unordered map.
1855 template <class LOOKUP_KEY>
1856 typename enable_if<
1857 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1858 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1859 iterator>::type
1860 find(const LOOKUP_KEY& key)
1861 {
1862 // Note: implemented inline due to Sun CC compilation error.
1863 return iterator(d_impl.find(key));
1864 }
1865
1866 /// Return an iterator providing modifiable access to the `value_type`
1867 /// object in this unordered map with a key equivalent to the specified
1868 /// `key`, if such an entry exists, and the past-the-end iterator
1869 /// (`end`) otherwise.
1871
1872 /// Insert the specified `value` into this unordered map if the key (the
1873 /// `first` element) of the object referred to by `value` does not
1874 /// already exist in this unordered map; otherwise, this method has no
1875 /// effect (a `value_type` object having the key equivalent to the key
1876 /// of `value` already exists in this unordered map). Return a `pair`
1877 /// whose `first` member is an iterator referring to the (possibly newly
1878 /// inserted) `value_type` object in this unordered map whose key is
1879 /// equivalent to that of the object to be inserted, and whose `second`
1880 /// member is `true` if a new value was inserted, and `false` if a value having an equivalent key was already present.
1881 ///
1882 /// \note Note that this method
1883 /// requires that the (template parameter) types `KEY` and `VALUE` both
1884 /// be `copy-insertable` into this unordered map (see {Requirements on
1885 /// `value_type`}).
1887
1888#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1889 template <class ALT_VALUE_TYPE>
1891#elif !defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER)
1892 template <class ALT_VALUE_TYPE>
1894 pair<iterator, bool> >::type
1895#else
1896 /// Insert the specified `value` into this unordered map if the key (the
1897 /// `first` element) of the object referred to by `value` does not
1898 /// already exist in this unordered map; otherwise, this method has no
1899 /// effect (a `value_type` object having the same key as the converted
1900 /// `value` already exists in this unordered map) . Return a `pair`
1901 /// whose `first` member is an iterator referring to the (possibly newly
1902 /// inserted) `value_type` object in this unordered map whose key is the
1903 /// equivalent to that of the object to be inserted, and whose `second`
1904 /// member is `true` if a new value was inserted, and `false` if a value having an equivalent key was already present.
1905 ///
1906 /// \note Note that this method
1907 /// requires that the (template parameter) types `KEY` and `VALUE` both
1908 /// be `move-constructible` (see {Requirements on `value_type`}), and
1909 /// that the `value_type` be constructible from the (template parameter)
1910 /// `ALT_VALUE_TYPE`. Also note that this one template stands in for
1911 /// three `insert` functions in the C++11 standard.
1912 template <class ALT_VALUE_TYPE>
1913 typename enable_if<std::is_constructible<value_type,
1914 ALT_VALUE_TYPE&&>::value,
1915 pair<iterator, bool> >::type
1916#endif
1918 {
1919 // Note that some compilers require functions declared with `enable_if`
1920 // to be defined inline.
1921
1922 typedef bsl::pair<iterator, bool> ResultType;
1923
1924 bool isInsertedFlag = false;
1925
1926 HashTableLink *result = d_impl.insertIfMissing(
1927 &isInsertedFlag,
1928 BSLS_COMPILERFEATURES_FORWARD(ALT_VALUE_TYPE, value));
1929
1930 return ResultType(iterator(result), isInsertedFlag);
1931 }
1932
1933 /// Insert the specified `value` into this unordered map if the key (the
1934 /// `first` element) of the object referred to by `value` does not
1935 /// already exist in this unordered map; otherwise, this method has no
1936 /// effect (a `value_type` object having the key equivalent to the key
1937 /// of `value` already exists in this unordered map). Return an
1938 /// iterator referring to ether the newly inserted `value_type` object
1939 /// or to the existing object whose key is equivalent to the key of
1940 /// `value`. The average and worst case complexity of this operation is
1941 /// not affected by the specified `hint`. This method requires that the
1942 /// (template parameter) types `KEY` and `VALUE` both be
1943 /// `copy-insertable` into this unordered map (see {Requirements on `value_type`}).
1944 ///
1945 /// \pre The behavior is undefined unless `hint` is an
1946 /// iterator in the range `[begin() .. end()]` (both endpoints included).
1947 ///
1948 /// \note Note that `hint` is ignored (other than possibly
1949 /// asserting its validity in some build modes).
1951
1952#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1953 template <class ALT_VALUE_TYPE>
1954 iterator
1955#elif !defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER)
1956 template <class ALT_VALUE_TYPE>
1958 iterator>::type
1959#else
1960 /// Insert the specified `value` into this unordered map if the key (the
1961 /// `first` element) of the object referred to by `value` does not
1962 /// already exist in this unordered map; otherwise, this method has no
1963 /// effect (a `value_type` object having the same key as the converted
1964 /// `value` already exists in this unordered map) . Return an iterator
1965 /// referring to ether the newly inserted) `value_type` object or to the
1966 /// existing object whose key is equivalent to the key of `value`. The
1967 /// average and worst case complexity of this operation is not affected
1968 /// by the specified `hint`. This method requires that the (template
1969 /// parameter) types `KEY` and `VALUE` both be `move-constructible` (see
1970 /// {Requirements on `value_type`}) and that the `value_type` be
1971 /// constructible from the (template parameter) `ALT_VALUE_TYPE`.
1972 ///
1973 /// \pre The behavior is undefined unless `hint` is an iterator in the range `[begin() .. end()]` (both endpoints included).
1974 ///
1975 /// \note Note that `hint` is
1976 /// ignored (other than possibly asserting its validity in some build
1977 /// modes). Also note that this one template stands in for three
1978 /// `insert` functions in the C++11 standard.
1979 template <class ALT_VALUE_TYPE>
1980 typename enable_if<std::is_constructible<value_type,
1981 ALT_VALUE_TYPE&&>::value,
1982 iterator>::type
1983#endif
1985 BSLS_COMPILERFEATURES_FORWARD_REF(ALT_VALUE_TYPE) value)
1986 {
1987 // Note that some compilers require functions declared with 'enable_if'
1988 // to be defined inline.
1989
1990 // There is no realistic use-case for the 'hint' in an 'unordered_map'
1991 // of unique values. We could quickly test for a duplicate key, and
1992 // have a fast return path for when the method fails, but in the
1993 // typical use case where a new element is inserted, we are adding an
1994 // extra key check for no benefit. In order to insert an element into
1995 // a bucket, we need to walk the whole bucket looking for duplicates,
1996 // and the hint is no help in finding the start of a bucket.
1997
1998 (void)hint; // suppress 'unused' warnings
1999
2000 bool isInsertedFlag; // not used
2001
2002 HashTableLink *result = d_impl.insertIfMissing(
2003 &isInsertedFlag,
2004 BSLS_COMPILERFEATURES_FORWARD(ALT_VALUE_TYPE, value));
2005
2006 return iterator(result);
2007 }
2008
2009 /// Create a `value_type` object for each iterator in the range starting
2010 /// at the specified `first` iterator and ending immediately before the
2011 /// specified `last` iterator, by converting from the object referred to
2012 /// by each iterator. Insert into this unordered map each such object
2013 /// whose key is not already contained. The (template parameter) type
2014 /// `INPUT_ITERATOR` shall meet the requirements of an input iterator
2015 /// defined in the C++11 standard [24.2.3] providing access to values of
2016 /// a type convertible to `value_type`.
2017 ///
2018 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid values where `first` is at a position at or before `last`.
2019 ///
2020 /// \note Note that this method
2021 /// requires that the (template parameter) types `KEY` and `VALUE` both
2022 /// be `copy-constructible` (see {Requirements on `value_type`}).
2023 template <class INPUT_ITERATOR>
2024 void insert(INPUT_ITERATOR first, INPUT_ITERATOR last);
2025
2026#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2027 /// Create a `value_type` object for each element in the specified
2028 /// `values`. Insert into this unordered map each such object whose key is not already contained.
2029 ///
2030 /// \note Note that this method requires that the
2031 /// (template parameter) types `KEY` and `VALUE` both be
2032 /// `copy-constructible` (see {Requirements on `value_type`}).
2033 void insert(std::initializer_list<value_type> values);
2034#endif
2035
2036#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2037 /// If a key equivalent to the specified `key` already exists in this
2038 /// unordered_map, assign the specified `obj` to the value associated
2039 /// with that key, and return a pair containing an iterator referring to
2040 /// the existing item and `false`. Otherwise, insert into this map a
2041 /// newly-created `value_type` object, constructed from
2042 /// `(key, std::forward<BDE_OTHER_TYPE>(obj)...))`, and return a pair
2043 /// containing an iterator referring to the newly-created entry and
2044 /// `true`.
2045 template <class BDE_OTHER_TYPE>
2047 BDE_OTHER_TYPE&& obj);
2048
2049 /// If a key equivalent to the specified `key` already exists in this
2050 /// unordered_map, assign the specified `obj` to the value associated
2051 /// with that key, and return a pair containing an iterator referring to
2052 /// the existing item and `false`. Otherwise, insert into this map a
2053 /// newly-created `value_type` object, constructed from
2054 /// `(std::forward<KEY>(key), std::forward<BDE_OTHER_TYPE>(obj)...))`,
2055 /// and return a pair containing an iterator referring to the
2056 /// newly-created entry and `true`.
2057 template <class BDE_OTHER_TYPE>
2059 BloombergLP::bslmf::MovableRef<KEY> key,
2060 BDE_OTHER_TYPE&& obj);
2061
2062 /// If a key equivalent to the specified `key` already exists in this
2063 /// unordered_map, assign the specified `obj` to the value associated
2064 /// with that key, and return a pair containing an iterator referring to
2065 /// the existing item and `false`. Otherwise, insert into this map a
2066 /// newly-created `value_type` object, constructed from
2067 /// `(std::forward<KEY>(key), std::forward<BDE_OTHER_TYPE>(obj)...))`,
2068 /// and return a pair containing an iterator referring to the
2069 /// newly-created entry and `true`.
2070 ///
2071 /// Note: implemented inline due to Sun CC compilation error.
2072 template<class LOOKUP_KEY, class BDE_OTHER_TYPE>
2073 typename bsl::enable_if<
2074 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2075 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
2076 , pair<iterator, bool> >::type
2077 insert_or_assign(LOOKUP_KEY&& key, BDE_OTHER_TYPE&& obj)
2078 {
2079 typedef bsl::pair<iterator, bool> ResultType;
2080 bool isInsertedFlag = false;
2081 HashTableLink *result = d_impl.insertOrAssignTransparent(
2082 &isInsertedFlag,
2083 NULL,
2084 BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key),
2085 BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj));
2086 return ResultType(iterator(result), isInsertedFlag);
2087 }
2088
2089 /// If a key equivalent to the specified `key` already exists in this
2090 /// unordered_map, assign the specified `obj` to the value associated
2091 /// with that key, and return an iterator referring to the existing
2092 /// item. Otherwise, insert into this map a newly-created `value_type`
2093 /// object, constructed from
2094 /// `(std::forward<KEY>(key), std::forward<BDE_OTHER_TYPE>(obj)...))`,
2095 /// and return a pair containing an iterator referring to the
2096 /// newly-created entry and `true`. Use the specified `hint` as a
2097 /// starting point for checking to see if the key already in the
2098 /// unordered_map.
2099 template <class BDE_OTHER_TYPE>
2101 const KEY& key,
2102 BDE_OTHER_TYPE&& obj);
2103
2104 /// If a key equivalent to the specified `key` already exists in this
2105 /// unordered_map, assign the specified `obj` to the value associated
2106 /// with that key, and return an iterator referring to the existing
2107 /// item. Otherwise, insert into this map a newly-created `value_type`
2108 /// object, constructed from
2109 /// `(std::forward<KEY>(key), std::forward<BDE_OTHER_TYPE>(obj)...))`,
2110 /// and return an iterator referring to the newly-created entry. Use
2111 /// the specified `hint` as a starting point for checking to see if the
2112 /// key already in the unordered_map.
2113 template <class BDE_OTHER_TYPE>
2115 BloombergLP::bslmf::MovableRef<KEY> key,
2116 BDE_OTHER_TYPE&& obj);
2117
2118 /// If a key equivalent to the specified `key` already exists in this
2119 /// unordered_map, assign the specified `obj` to the value associated
2120 /// with that key, and return an iterator referring to the existing
2121 /// item. Otherwise, insert into this map a newly-created `value_type`
2122 /// object, constructed from
2123 /// `(std::forward<KEY>(key), std::forward<BDE_OTHER_TYPE>(obj)...))`,
2124 /// and return an iterator referring to the newly-created entry. Use
2125 /// the specified `hint` as a starting point for checking to see if the
2126 /// key already in the unordered_map.
2127 ///
2128 /// Note: implemented inline due to Sun CC compilation error.
2129 template<class LOOKUP_KEY, class BDE_OTHER_TYPE>
2130 typename bsl::enable_if<
2131 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2132 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
2133 , iterator>::type
2135 LOOKUP_KEY&& key,
2136 BDE_OTHER_TYPE&& obj)
2137 {
2138 bool isInsertedFlag = false;
2139 HashTableLink *result = d_impl.insertOrAssignTransparent(
2140 &isInsertedFlag,
2141 hint.node(),
2142 BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key),
2143 BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj));
2144 return iterator(result);
2145 }
2146#endif
2147
2148 /// Return a pair of iterators providing modifiable access to the
2149 /// sequence of `value_type` objects in this unordered map having the
2150 /// specified `key`, where the first iterator is positioned at the start
2151 /// of the sequence, and the second is positioned one past the end of
2152 /// the sequence. If this unordered map contains no `value_type` object
2153 /// having `key`, then the two returned iterators will have the same value, `end()`.
2154 ///
2155 /// \pre The behavior is undefined unless `key` is
2156 /// equivalent to at most one key in this unordered map.
2157 ///
2158 /// \note Note that since an unordered map maintains unique keys, the range will contain
2159 /// at most one element.
2160 ///
2161 /// Note: implemented inline due to Sun CC compilation error.
2162 template <class LOOKUP_KEY>
2163 typename enable_if<
2164 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2165 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
2167 equal_range(const LOOKUP_KEY& key)
2168 {
2169 typedef bsl::pair<iterator, iterator> ResultType;
2170
2171 HashTableLink *first = d_impl.find(key);
2172 return first
2173 ? ResultType(iterator(first), iterator(first->nextLink()))
2174 : ResultType(iterator(0), iterator(0));
2175 }
2176
2177 /// Return a pair of iterators providing modifiable access to the
2178 /// sequence of `value_type` objects in this unordered map having the
2179 /// specified `key`, where the first iterator is positioned at the start
2180 /// of the sequence, and the second is positioned one past the end of
2181 /// the sequence. If this unordered map contains no `value_type` object
2182 /// having `key`, then the two returned iterators will have the same value, `end()`.
2183 ///
2184 /// \note Note that since an unordered map maintains unique
2185 /// keys, the range will contain at most one element.
2187
2188 /// Set the maximum load factor of this unordered map to the specified
2189 /// `newMaxLoadFactor`. If `newMaxLoadFactor < loadFactor()`, this
2190 /// operator will cause an immediate rehash (in violation of the C++11
2191 /// standard); otherwise, it has a constant-time cost.
2192 ///
2193 /// \pre The behavior is undefined unless `0 < newMaxLoadFactor`.
2194 void max_load_factor(float newMaxLoadFactor);
2195
2196 /// Change the size of the array of buckets maintained by this unordered
2197 /// map to at least the specified `numBuckets`, and redistribute all the
2198 /// contained elements into the new sequence of buckets, according to
2199 /// their hash values. After this call, @ref load_factor will be less than
2200 /// or equal to @ref max_load_factor . This operation has no effect if
2201 /// rehashing the elements into `numBuckets` would cause this map to
2202 /// exceed its @ref max_load_factor .
2203 void rehash(size_type numBuckets);
2204
2205 /// Increase the number of buckets of this set to a quantity such that
2206 /// the ratio between the specified `numElements` and this quantity does not exceed `max_load_factor`.
2207 ///
2208 /// \note Note that this guarantees that, after
2209 /// the reserve, elements can be inserted to grow the container to
2210 /// `size() == numElements` without rehashing. Also note that memory
2211 /// allocations may still occur when growing the container to `size() ==
2212 /// numElements`. Also note that this operation has no effect if
2213 /// `numElements <= size()`.
2214 void reserve(size_type numElements);
2215
2216 /// Exchange the value, hasher, key-equality functor, and
2217 /// @ref max_load_factor of this object with those of the specified `other`
2218 /// object; also exchange the allocator of this object with that of
2219 /// `other` if the (template parameter) type `ALLOCATOR` has the
2220 /// @ref propagate_on_container_swap trait, and do not modify either
2221 /// allocator otherwise. This method provides the no-throw
2222 /// exception-safety guarantee if and only if both the (template
2223 /// parameter) types `HASH` and `EQUAL` provide no-throw swap
2224 /// operations; if an exception is thrown, both objects are left in
2225 /// valid but unspecified states. This operation guarantees `O[1]` complexity.
2226 ///
2227 /// \pre The behavior is undefined unless either this object was
2228 /// created with the same allocator as `other` or `ALLOCATOR` has the
2229 /// @ref propagate_on_container_swap trait.
2231 AllocatorTraits::is_always_equal::value &&
2232 bsl::is_nothrow_swappable<HASH>::value &&
2233 bsl::is_nothrow_swappable<EQUAL>::value);
2234
2235#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2236 /// If a key equivalent to the specified `key` already exists in this
2237 /// unordered_map, return a pair containing an iterator referring to the
2238 /// existing item, and `false`. Otherwise, insert into this map a
2239 /// newly-created `value_type` object, constructed from `key` and the
2240 /// specified `args`, and return a pair containing an iterator referring
2241 /// to the newly-created entry and `true`. This method requires that
2242 /// the (template parameter) types `KEY` and `VALUE` are
2243 /// `emplace-constructible` from `key` and `args` respectively. For
2244 /// C++03, `VALUE` must also be `copy-constructible`.
2245 template <class... Args>
2246 pair<iterator, bool> try_emplace(const KEY& key, Args&&... args);
2247
2248 /// If a key equivalent to the specified `key` already exists in this
2249 /// unordered_map, return a pair containing an iterator referring to the
2250 /// existing item and `false`. Otherwise, insert into this map a
2251 /// newly-created `value_type` object, constructed from
2252 /// `std::forward<KEY>(key)` and the specified `args`, and return a pair
2253 /// containing an iterator referring to the newly-created entry, and
2254 /// `true`. This method requires that the (template parameter) types
2255 /// `KEY` and `VALUE` are `emplace-constructible` from `key` and `args`
2256 /// respectively. For C++03, `VALUE` must also be `copy-constructible`.
2257 template <class... Args>
2259 BloombergLP::bslmf::MovableRef<KEY> key,
2260 Args&&... args);
2261
2262 /// If a key equivalent to the specified `key` already exists in this
2263 /// unordered_map, return a pair containing an iterator referring to the
2264 /// existing item and `false`. Otherwise, insert into this map a
2265 /// newly-created `value_type` object, constructed from
2266 /// `std::forward<LOOKUP_KEY>(key)` and the specified `args`, and return
2267 /// a pair containing an iterator referring to the newly-created entry,
2268 /// and `true`. This method requires that the (template parameter)
2269 /// types `KEY` and `VALUE` are `emplace-constructible` from `key` and
2270 /// `args` respectively. For C++03, `VALUE` must also be
2271 /// `copy-constructible`.
2272 ///
2273 /// Note: implemented inline due to Sun CC compilation error.
2274 template<class LOOKUP_KEY, class... Args>
2275 typename bsl::enable_if<
2276 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2277 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
2280 pair<iterator, bool> >::type
2281 try_emplace(LOOKUP_KEY&& key, Args&&... args)
2282 {
2283 typedef bsl::pair<iterator, bool> ResultType;
2284 bool isInsertedFlag = false;
2285 HashTableLink *result = d_impl.tryEmplace(
2286 &isInsertedFlag,
2287 NULL,
2288 BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key),
2289 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
2290
2291 return ResultType(iterator(result), isInsertedFlag);
2292 }
2293
2294 /// If a key equivalent to the specified `key` already exists in this
2295 /// unordered_map, return an iterator referring to the existing item.
2296 /// Otherwise, insert into this map a newly-created `value_type` object,
2297 /// constructed from `key` and the specified `args`, and return an
2298 /// iterator referring to the newly-created entry. Use the specified
2299 /// `hint` as a starting point for checking to see if the key already
2300 /// in the unordered_map. This method requires that the
2301 /// (template parameter) types `KEY` and `VALUE` are
2302 /// `emplace-constructible` from `key` and `args` respectively. For
2303 /// C++03, `VALUE` must also be `copy-constructible`.
2304 template<class... Args>
2305 iterator
2306 try_emplace(const_iterator hint, const KEY& key, Args&&... args);
2307
2308 /// If a key equivalent to the specified `key` already exists in this
2309 /// unordered_map, return an iterator referring to the existing item.
2310 /// Otherwise, insert into this map a newly-created `value_type` object,
2311 /// constructed from `std::forward<KEY>(key)` and the specified `args`,
2312 /// and return an iterator referring to the newly-created entry. Use
2313 /// the specified `hint` as a starting point for checking to see if the
2314 /// key already in the unordered_map. This method requires that the
2315 /// (template parameter) types `KEY` and `VALUE` are
2316 /// `emplace-constructible` from `key` and `args` respectively. For
2317 /// C++03, `VALUE` must also be `copy-constructible`.
2318 template <class... Args>
2320 BloombergLP::bslmf::MovableRef<KEY> key,
2321 Args&&... args);
2322
2323 /// If a key equivalent to the specified `key` already exists in this
2324 /// unordered_map, return an iterator referring to the existing item.
2325 /// Otherwise, insert into this map a newly-created `value_type` object,
2326 /// constructed from `std::forward<LOOKUP_KEY>(key)` and the specified
2327 /// `args`, and return an iterator referring to the newly-created entry.
2328 /// Use the specified `hint` as a starting point for checking to see if
2329 /// the key already in the unordered_map. This method requires that the
2330 /// (template parameter) types `KEY` and `VALUE` are
2331 /// `emplace-constructible` from `key` and `args` respectively. For
2332 /// C++03, `VALUE` must also be `copy-constructible`.
2333 ///
2334 /// Note: implemented inline due to Sun CC compilation error.
2335 template<class LOOKUP_KEY, class... Args>
2336 typename bsl::enable_if<
2337 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2338 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
2339 iterator>::type
2340 try_emplace(const_iterator hint, LOOKUP_KEY&& key, Args&&... args)
2341 {
2342 bool isInsertedFlag = false;
2343 HashTableLink *result = d_impl.tryEmplace(
2344 &isInsertedFlag,
2345 hint.node(),
2346 BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key),
2347 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
2348
2349 return iterator(result);
2350 }
2351#endif
2352
2353 public:
2354 // ACCESSORS
2355
2356 /// Return a reference providing non-modifiable access to the
2357 /// mapped-value associated with the specified `key`, if such an entry
2358 /// exists; otherwise throw a `std::out_of_range` exception.
2359 ///
2360 /// \note Note that this method is not exception-neutral.
2362 const;
2363
2364 /// Return a reference providing non-modifiable access to the
2365 /// mapped-value associated with a key that is equivalent to the
2366 /// specified `key`, if such an entry exists; otherwise, throw a `std::out_of_range` exception.
2367 ///
2368 /// \note Note that this method may also throw
2369 /// a different kind of exception if the (user-supplied) comparator
2370 /// throws.
2371 ///
2372 /// Note: implemented inline due to Sun CC compilation error
2373 template <class LOOKUP_KEY>
2374 typename bsl::enable_if<
2375 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2376 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
2378 at(const LOOKUP_KEY& key) const {
2379 HashTableLink *node = d_impl.find(key);
2380
2381 if (!node) {
2382 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(
2383 "unordered_map<...>::at(LOOKUP_KEY) const: invalid key value");
2384 }
2385 return static_cast<HashTableNode *>(node)->value().second;
2386 }
2387
2389
2390 /// Return an iterator providing non-modifiable access to the first
2391 /// `value_type` object in the sequence of `value_type` objects
2392 /// maintained by this unordered map, or the `end` iterator if this
2393 /// unordered map is empty.
2395
2397
2398 /// Return an iterator providing non-modifiable access to the
2399 /// past-the-end position in the sequence of `value_type` objects
2400 /// maintained by this unordered map.
2402
2404
2405 /// Return a local iterator providing non-modifiable access to the first
2406 /// `value_type` object in the sequence of `value_type` objects of the
2407 /// bucket having the specified `index` in the array of buckets
2408 /// maintained by this unordered map, or the `end(index)` iterator if the bucket is empty.
2409 ///
2410 /// \pre The behavior is undefined unless
2411 /// `index < bucket_count()`.
2413
2415
2416 /// Return a local iterator providing non-modifiable access to the
2417 /// past-the-end position in the sequence of `value_type` objects of the
2418 /// bucket having the specified `index` in the array of buckets maintained by this unordered map.
2419 ///
2420 /// \pre The behavior is undefined unless
2421 /// `index < bucket_count()`.
2423
2424 /// Return the index of the bucket, in the array of buckets maintained
2425 /// by this unordered map, where values having a key equivalent to the
2426 /// specified `key` would be inserted.
2427 size_type bucket(const key_type& key) const;
2428
2429 /// Return the index of the bucket, in the array of buckets maintained
2430 /// by this unordered map, where values having a key equivalent to the
2431 /// specified `key` would be inserted.
2432 ///
2433 /// Note: implemented inline due to Sun CC compilation error.
2434 template <class LOOKUP_KEY>
2435 typename enable_if<
2436 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2437 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
2438 size_type>::type
2439 bucket(const LOOKUP_KEY& key) const
2440 {
2441 return d_impl.bucketIndexForKey(key);
2442 }
2443
2444 /// Return the number of buckets in the array of buckets maintained by
2445 /// this unordered map.
2447
2448 /// Return a theoretical upper bound on the largest number of buckets that this unordered map could possibly manage.
2449 ///
2450 /// \note Note that there is
2451 /// no guarantee that the unordered map can successfully grow to the
2452 /// returned size, or even close to that size, without running out of
2453 /// resources.
2455
2456 /// Return the number of elements contained in the bucket at the
2457 /// specified `index` in the array of buckets maintained by this unordered map.
2458 ///
2459 /// \pre The behavior is undefined unless
2460 /// `index < bucket_count()`.
2462
2463 /// Return the number of `value_type` objects within this unordered map
2464 /// that have a key equivalent to the specified `key`.
2465 ///
2466 /// \pre The behavior is undefined unless `key` is equivalent to at most one key in this unordered map.
2467 ///
2468 /// \note Note that since an unordered map maintains unique
2469 /// keys, the returned value will be either 0 or 1.
2470 ///
2471 /// Note: implemented inline due to Sun CC compilation error.
2472 template <class LOOKUP_KEY>
2473 typename enable_if<
2474 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2475 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
2476 size_type>::type
2477 count(const LOOKUP_KEY& key) const
2478 {
2479 return d_impl.find(key) != 0;
2480 }
2481
2482 /// Return the number of `value_type` objects contained within this unordered map having the specified `key`.
2483 ///
2484 /// \note Note that since an
2485 /// unordered map maintains unique keys, the returned value will be
2486 /// either 0 or 1.
2487 size_type count(const key_type& key) const;
2488
2489 /// Return `true` if this unordered map contains an element whose key is
2490 /// equivalent to the specified `key`.
2491 bool contains(const key_type &key) const;
2492
2493 /// Return `true` if this unordered map contains an element whose key is
2494 /// equivalent to the specified `key`.
2495 ///
2496 /// Note: implemented inline due to Sun CC compilation error
2497 template <class LOOKUP_KEY>
2498 typename enable_if<
2499 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value &&
2500 BloombergLP::bslmf::IsTransparentPredicate<EQUAL,
2501 LOOKUP_KEY>::value,
2502 bool>::type
2503 contains(const LOOKUP_KEY& key) const
2504 {
2505 return find(key) != end();
2506 }
2507
2508 /// Return `true` if this unordered map contains no elements, and
2509 /// `false` otherwise.
2511
2512 /// Return a pair of iterators providing non-modifiable access to the
2513 /// sequence of `value_type` objects in this unordered map with a key
2514 /// equivalent to specified `key`, where the first iterator is
2515 /// positioned at the start of the sequence, and the second is
2516 /// positioned one past the end of the sequence. If this unordered map
2517 /// contains no `value_type` objects having a key equivalent to `key`,
2518 /// then the two returned iterators will have the same value, `end()`.
2519 ///
2520 /// \pre The behavior is undefined unless `key` is equivalent to at most one key in this unordered map.
2521 ///
2522 /// \note Note that since an unordered map
2523 /// maintains unique keys, the range will contain at most one element.
2524 ///
2525 /// Note: implemented inline due to Sun CC compilation error.
2526 template <class LOOKUP_KEY>
2527 typename enable_if<
2528 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2529 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
2531 equal_range(const LOOKUP_KEY& key) const
2532 {
2534
2535 HashTableLink *first = d_impl.find(key);
2536 return first
2537 ? ResultType(iterator(first), iterator(first->nextLink()))
2538 : ResultType(iterator(0), iterator(0));
2539 }
2540
2541 /// Return a pair of iterators providing non-modifiable access to the
2542 /// sequence of `value_type` objects in this unordered map having the
2543 /// specified `key`, where the first iterator is positioned at the start
2544 /// of the sequence, and the second is positioned one past the end of
2545 /// the sequence. If this unordered map contains no `value_type` object
2546 /// having `key`, then the two returned iterators will have the same value, `end()`.
2547 ///
2548 /// \note Note that since an unordered map maintains unique
2549 /// keys, the range will contain at most one element.
2551 const key_type& key) const;
2552
2553 /// Return an iterator providing non-modifiable access to the
2554 /// `value_type` object in this unordered map with a key equivalent to
2555 /// the specified `key`, if such an entry exists, and the past-the-end iterator (`end`) otherwise.
2556 ///
2557 /// \pre The behavior is undefined unless `key`
2558 /// is equivalent to at most one key in this unordered map.
2559 ///
2560 /// Note: implemented inline due to Sun CC compilation error.
2561 template <class LOOKUP_KEY>
2562 typename enable_if<
2563 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
2564 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
2565 const_iterator>::type
2566 find(const LOOKUP_KEY& key) const
2567 {
2568 return const_iterator(d_impl.find(key));
2569 }
2570
2571 /// Return an iterator providing non-modifiable access to the
2572 /// `value_type` object in this unordered map with a key equivalent to
2573 /// the specified `key`, if such an entry exists, and the past-the-end
2574 /// iterator (`end`) otherwise.
2575 const_iterator find(const key_type& key) const;
2576
2577 /// Return (a copy of) the allocator used for memory allocation by this
2578 /// unordered map.
2580
2581 /// Return (a copy of) the unary hash functor used by this unordered map
2582 /// to generate a hash value (of type `size_type`) for a `key_type`
2583 /// object.
2584 HASH hash_function() const;
2585
2586 /// Return (a copy of) binary the key-equality functor used by this
2587 /// unordered map that returns `true` if two `key_type` objects are
2588 /// equivalent, and `false` otherwise.
2589 EQUAL key_eq() const;
2590
2591 /// Return the current ratio between the `size` of this unordered map
2592 /// and the number of buckets. The load factor is a measure of how
2593 /// full the container is, and a higher load factor typically leads to
2594 /// an increased number of collisions, thus resulting in a loss of
2595 /// performance.
2597
2598 /// Return the maximum load factor allowed for this unordered map.
2599 ///
2600 /// \note Note that if an insert operation would cause the load factor to exceed
2601 /// the @ref max_load_factor , that same insert operation will increase the
2602 /// number of buckets and rehash the elements of the container into
2603 /// those buckets (see `rehash`).
2605
2606 /// Return the number of elements in this unordered map.
2608
2609 /// Return a theoretical upper bound on the largest number of elements that this unordered map could possibly hold.
2610 ///
2611 /// \note Note that there is no
2612 /// guarantee that the unordered map can successfully grow to the
2613 /// returned size, or even close to that size, without running out of
2614 /// resources.
2616};
2617
2618#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
2619// CLASS TEMPLATE DEDUCTION GUIDES
2620
2621/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2622/// of the iterators supplied to the constructor of `unordered_map`. Deduce
2623/// the template parameters `HASH`, `EQUAL` and `ALLOCATOR` from the other
2624/// parameters passed to the constructor of `unordered_map`. This deduction
2625/// guide does not participate unless: (1) the supplied `HASH` is invokable
2626/// with a `KEY`, (2) the supplied `EQUAL` is invokable with two `KEY`s, and
2627/// (3) the supplied allocator meets the requirements of a standard
2628/// allocator.
2629template <
2630 class INPUT_ITERATOR,
2631 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2632 class VALUE =
2633 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2634 class HASH = bsl::hash<KEY>,
2635 class EQUAL = bsl::equal_to<KEY>,
2636 class ALLOCATOR = bsl::allocator<pair<const KEY, VALUE>>,
2637 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
2638 class = bsl::enable_if_t<
2639 std::is_invocable_v<EQUAL, const KEY &, const KEY &>>,
2640 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2641 >
2642unordered_map(INPUT_ITERATOR,
2643 INPUT_ITERATOR,
2644 typename bsl::allocator_traits<ALLOCATOR>::size_type = 0,
2645 HASH = HASH(),
2646 EQUAL = EQUAL(),
2647 ALLOCATOR = ALLOCATOR())
2648-> unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>;
2649
2650/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2651/// of the iterators supplied to the constructor of `unordered_map`. Deduce
2652/// the template parameters `HASH` and "EQUAL' from the other parameters
2653/// passed to the constructor of `unordered_map`. This deduction guide does
2654/// not participate unless the supplied allocator is convertible to
2655/// `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2656template <
2657 class INPUT_ITERATOR,
2658 class HASH,
2659 class EQUAL,
2660 class ALLOC,
2661 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2662 class VALUE =
2663 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2664 class DEFAULT_ALLOCATOR = bsl::allocator<pair<const KEY, VALUE>>,
2665 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2666 >
2667unordered_map(INPUT_ITERATOR,
2668 INPUT_ITERATOR,
2669 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2670 HASH,
2671 EQUAL,
2672 ALLOC *)
2673-> unordered_map<KEY, VALUE, HASH, EQUAL>;
2674
2675/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2676/// of the iterators supplied to the constructor of `unordered_map`. Deduce
2677/// the template parameters `HASH` and `ALLOCATOR` from the other
2678/// parameters passed to the constructor of `unordered_map`. This deduction
2679/// guide does not participate unless the supplied hash is invokable with a
2680/// `KEY` and the supplied allocator meets the requirements of a standard
2681/// allocator.
2682template <
2683 class INPUT_ITERATOR,
2684 class HASH,
2685 class ALLOCATOR,
2686 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2687 class VALUE =
2688 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2689 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
2690 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2691 >
2692unordered_map(INPUT_ITERATOR,
2693 INPUT_ITERATOR,
2694 typename bsl::allocator_traits<ALLOCATOR>::size_type,
2695 HASH,
2696 ALLOCATOR)
2697-> unordered_map<KEY, VALUE, HASH, bsl::equal_to<KEY>, ALLOCATOR>;
2698
2699/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2700/// of the iterators supplied to the constructor of `unordered_map`. Deduce
2701/// the template parameter `HASH` from the other parameters passed to the
2702/// constructor of `unordered_map`. This deduction guide does not
2703/// participate unless the supplied allocator is convertible to
2704/// `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2705template <
2706 class INPUT_ITERATOR,
2707 class HASH,
2708 class ALLOC,
2709 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2710 class VALUE =
2711 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2712 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2713 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2714 >
2715unordered_map(INPUT_ITERATOR,
2716 INPUT_ITERATOR,
2717 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2718 HASH,
2719 ALLOC *)
2720-> unordered_map<KEY, VALUE, HASH>;
2721
2722/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2723/// of the iterators supplied to the constructor of `unordered_map`. Deduce
2724/// the template parameter `ALLOCATOR` from the other parameter passed to
2725/// the constructor of `unordered_map`. This deduction guide does not
2726/// participate unless the supplied allocator meets the requirements of a
2727/// standard allocator.
2728template <
2729 class INPUT_ITERATOR,
2730 class ALLOCATOR,
2731 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2732 class VALUE =
2733 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2734 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2735 >
2736unordered_map(INPUT_ITERATOR,
2737 INPUT_ITERATOR,
2738 typename bsl::allocator_traits<ALLOCATOR>::size_type,
2739 ALLOCATOR)
2740-> unordered_map<KEY, VALUE, bsl::hash<KEY>, bsl::equal_to<KEY>, ALLOCATOR>;
2741
2742/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2743/// of the iterators supplied to the constructor of `unordered_map`. This
2744/// deduction guide does not participate unless the supplied allocator is
2745/// convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2746template <
2747 class INPUT_ITERATOR,
2748 class ALLOC,
2749 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2750 class VALUE =
2751 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2752 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2753 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2754 >
2755unordered_map(INPUT_ITERATOR,
2756 INPUT_ITERATOR,
2757 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2758 ALLOC *)
2759-> unordered_map<KEY, VALUE>;
2760
2761/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2762/// of the iterators supplied to the constructor of `unordered_map`. Deduce
2763/// the template parameter `ALLOCATOR` from the other parameter passed to
2764/// the constructor of `unordered_map`. This deduction guide does not
2765/// participate unless the supplied allocator meets the requirements of a
2766/// standard allocator.
2767template <
2768 class INPUT_ITERATOR,
2769 class ALLOCATOR,
2770 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2771 class VALUE =
2772 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2773 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2774 >
2775unordered_map(INPUT_ITERATOR, INPUT_ITERATOR, ALLOCATOR)
2776-> unordered_map<KEY, VALUE, bsl::hash<KEY>, bsl::equal_to<KEY>, ALLOCATOR>;
2777
2778/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2779/// of the iterators supplied to the constructor of `unordered_map`. This
2780/// deduction guide does not participate unless the supplied allocator is
2781/// convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2782template <
2783 class INPUT_ITERATOR,
2784 class ALLOC,
2785 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2786 class VALUE =
2787 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2788 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2789 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2790 >
2791unordered_map(INPUT_ITERATOR, INPUT_ITERATOR, ALLOC *)
2792-> unordered_map<KEY, VALUE>;
2793
2794/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2795/// of the initializer_list supplied to the constructor of `unordered_map`.
2796/// Deduce the template parameters `HASH`, `EQUAL` and `ALLOCATOR` from the
2797/// other parameters supplied to the constructor of `unordered_map`. This
2798/// deduction guide does not participate unless: (1) the supplied `HASH` is
2799/// invokable with a `KEY`, (2) the supplied `EQUAL` is invokable with two
2800/// `KEY`s, and (3) the supplied allocator meets the requirements of a
2801/// standard allocator.
2802template <
2803 class KEY,
2804 class VALUE,
2805 class HASH = bsl::hash<KEY>,
2806 class EQUAL = bsl::equal_to<KEY>,
2807 class ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2808 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
2809 class = bsl::enable_if_t<
2810 std::is_invocable_v<EQUAL, const KEY &, const KEY &>>,
2811 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2812 >
2813unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2814 typename bsl::allocator_traits<ALLOCATOR>::size_type = 0,
2815 HASH = HASH(),
2816 EQUAL = EQUAL(),
2817 ALLOCATOR = ALLOCATOR())
2818-> unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>;
2819
2820/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2821/// of the initializer_list supplied to the constructor of `unordered_map`.
2822/// Deduce the template parameters `HASH` and `EQUAL` from the other
2823/// parameters supplied to the constructor of `unordered_map`. This
2824/// deduction guide does not participate unless the supplied allocator is
2825/// convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2826template <
2827 class KEY,
2828 class VALUE,
2829 class HASH,
2830 class EQUAL,
2831 class ALLOC,
2832 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2833 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2834 >
2835unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2836 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2837 HASH,
2838 EQUAL,
2839 ALLOC *)
2840-> unordered_map<KEY, VALUE, HASH, EQUAL>;
2841
2842/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2843/// of the initializer_list supplied to the constructor of `unordered_map`.
2844/// Deduce the template parameters `HASH` and `ALLOCATOR` from the other
2845/// parameters supplied to the constructor of `unordered_map`. This
2846/// deduction guide does not participate unless the supplied `HASH` is
2847/// invokable with a `KEY`, and the supplied allocator meets the
2848/// requirements of a standard allocator.
2849template <
2850 class KEY,
2851 class VALUE,
2852 class HASH,
2853 class ALLOCATOR,
2854 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
2855 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2856 >
2857unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2858 typename bsl::allocator_traits<ALLOCATOR>::size_type,
2859 HASH,
2860 ALLOCATOR)
2861-> unordered_map<KEY, VALUE, HASH, bsl::equal_to<KEY>, ALLOCATOR>;
2862
2863/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2864/// of the initializer_list supplied to the constructor of `unordered_map`.
2865/// Deduce the template parameter `HASH` from the other parameters supplied
2866/// to the constructor of `unordered_map`. This deduction guide does not
2867/// participate unless the supplied allocator is convertible to
2868/// `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2869template <
2870 class KEY,
2871 class VALUE,
2872 class HASH,
2873 class ALLOC,
2874 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2875 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2876 >
2877unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2878 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2879 HASH,
2880 ALLOC *)
2881-> unordered_map<KEY, VALUE, HASH>;
2882
2883/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2884/// of the initializer_list supplied to the constructor of `unordered_map`.
2885/// This deduction guide does not participate unless the supplied allocator
2886/// meets the requirements of a standard allocator.
2887template <
2888 class KEY,
2889 class VALUE,
2890 class ALLOCATOR,
2891 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2892 >
2893unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2894 typename bsl::allocator_traits<ALLOCATOR>::size_type,
2895 ALLOCATOR)
2896-> unordered_map<KEY, VALUE, bsl::hash<KEY>, bsl::equal_to<KEY>, ALLOCATOR>;
2897
2898/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2899/// of the initializer_list supplied to the constructor of `unordered_map`.
2900/// This deduction guide does not participate unless the supplied allocator
2901/// is convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2902template <
2903 class KEY,
2904 class VALUE,
2905 class ALLOC,
2906 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2907 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2908 >
2909unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2910 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2911 ALLOC *)
2912-> unordered_map<KEY, VALUE>;
2913
2914/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2915/// of the initializer_list supplied to the constructor of `unordered_map`.
2916/// Deduce the template parameter `ALLOCATOR` from the other parameters
2917/// supplied to the constructor of `unordered_map`. This deduction guide
2918/// does not participate unless the supplied allocator meets the
2919/// requirements of a standard allocator.
2920template <
2921 class KEY,
2922 class VALUE,
2923 class ALLOCATOR,
2924 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2925 >
2926unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>, ALLOCATOR)
2927-> unordered_map<KEY, VALUE, bsl::hash<KEY>, bsl::equal_to<KEY>, ALLOCATOR>;
2928
2929/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2930/// of the initializer_list supplied to the constructor of `unordered_map`.
2931/// This deduction guide does not participate unless the supplied allocator
2932/// is convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2933template <
2934 class KEY,
2935 class VALUE,
2936 class ALLOC,
2937 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2938 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2939 >
2940unordered_map(std::initializer_list<bsl::pair<const KEY, VALUE>>, ALLOC *)
2941-> unordered_map<KEY, VALUE>;
2942#endif
2943
2944// FREE OPERATORS
2945
2946/// Return `true` if the specified `lhs` and `rhs` objects have the same
2947/// value, and `false` otherwise. Two `unordered_map` objects have the
2948/// same value if they have the same number of key-value pairs, and for each
2949/// key-value pair that is contained in `lhs` there is a key-value pair
2950/// contained in `rhs` having the same value, and vice versa.
2951///
2952/// \note Note that this method requires that the (template parameter) types `KEY` and
2953/// `VALUE` both be `equality-comparable` (see {Requirements on
2954/// `value_type`}).
2955template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2956bool operator==(const unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& lhs,
2957 const unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& rhs);
2958
2959#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
2960template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2961bool operator!=(const unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& lhs,
2962 const unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& rhs);
2963 // Return 'true' if the specified 'lhs' and 'rhs' objects do not have the
2964 // same value, and 'false' otherwise. Two 'unordered_map' objects do not
2965 // have the same value if they do not have the same number of key-value
2966 // pairs, or for some key-value pair that is contained in 'lhs' there is
2967 // not a key-value pair in 'rhs' having the same value or vice-versa. Note
2968 // that this method requires that the (template parameter) types 'KEY' and
2969 // 'VALUE' both be 'equality-comparable' (see {Requirements on
2970 // 'value_type'}).
2971#endif
2972
2973// FREE FUNCTIONS
2974
2975/// Erase all the elements in the specified unordered_map `m` that satisfy
2976/// the specified predicate `predicate`. Return the number of elements
2977/// erased.
2978template <class KEY,
2979 class VALUE,
2980 class HASH,
2981 class EQUAL,
2982 class ALLOCATOR,
2983 class PREDICATE>
2984typename unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>::size_type
2985erase_if(unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& m,
2986 PREDICATE predicate);
2987
2988/// Exchange the value, hasher, key-equality functor, and @ref max_load_factor
2989/// of the specified `a` object with those of the specified `b` object; also
2990/// exchange the allocator of `a` with that of `b` if the (template
2991/// parameter) type `ALLOCATOR` has the @ref propagate_on_container_swap trait,
2992/// and do not modify either allocator otherwise. This function provides
2993/// the no-throw exception-safety guarantee if and only if both the
2994/// (template parameter) types `HASH` and `EQUAL` provide no-throw swap
2995/// operations; if an exception is thrown, both objects are left in valid
2996/// but unspecified states. This operation guarantees `O[1]` complexity.
2997///
2998/// \pre The behavior is undefined unless either `a` was created with the same
2999/// allocator as `b` or `ALLOCATOR` has the @ref propagate_on_container_swap
3000/// trait.
3001template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3002void swap(unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& a,
3003 unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& b)
3005
3006} // close namespace bsl
3007
3008// ============================================================================
3009// TEMPLATE AND INLINE FUNCTION DEFINITIONS
3010// ============================================================================
3011
3012namespace bsl {
3013 //--------------------
3014 // class unordered_map
3015 //--------------------
3016
3017// PRIVATE MANIPULATORS
3018template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3019template <class INPUT_ITERATOR, class SENTINEL>
3020inline
3022 INPUT_ITERATOR first,
3023 SENTINEL last)
3024{
3025 ///Implementation Notes
3026 ///--------------------
3027 // If we can calculate the number of elements, reserve space for them
3028 // upfront to reduce rehashing. The calculation is done once since
3029 // `IteratorUtil::insertdistance` may be expensive for non-random-access
3030 // iterators.
3031
3032 if (first == last) {
3033 return; // RETURN
3034 }
3035
3037 BloombergLP::bslstl::IteratorUtil::
3038 canCalculateInsertDistance<INPUT_ITERATOR,SENTINEL>()) {
3039 this->reserve(
3040 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last));
3041 }
3042
3043 bool isInsertedFlag; // value is not used
3044
3045 while (first != last) {
3046 d_impl.insertIfMissing(&isInsertedFlag, *first);
3047 ++first;
3048 }
3049}
3050
3051#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
3052 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
3053
3054template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3055template <class INPUT_ITERATOR, class SENTINEL>
3056inline
3058 INPUT_ITERATOR first,
3059 SENTINEL last,
3060 size_t numElements)
3061{
3063 !BloombergLP::bslstl::IteratorUtil
3064 ::canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()
3065 || numElements == static_cast<size_t>(
3066 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last))));
3067
3068 if (0 < numElements) {
3069 this->reserve(numElements);
3070 }
3071
3072 bool isInsertedFlag; // value is not used
3073
3074 while (first != last) {
3075 d_impl.insertIfMissing(&isInsertedFlag, *first);
3076 ++first;
3077 }
3078}
3079
3080#endif
3081
3082// CREATORS
3083template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3084inline
3086unordered_map(size_type initialNumBuckets,
3087 const HASH& hashFunction,
3088 const EQUAL& keyEqual,
3089 const ALLOCATOR& basicAllocator)
3090: d_impl(hashFunction, keyEqual, initialNumBuckets, 1.0f, basicAllocator)
3091{
3092}
3093
3094template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3095inline
3097 size_type initialNumBuckets,
3098 const HASH& hashFunction,
3099 const ALLOCATOR& basicAllocator)
3100: d_impl(hashFunction, EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
3101{
3102}
3103
3104template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3105inline
3107 size_type initialNumBuckets,
3108 const ALLOCATOR& basicAllocator)
3109: d_impl(HASH(), EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
3110{
3111}
3112
3113template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3114inline
3116 const ALLOCATOR& basicAllocator)
3117: d_impl(basicAllocator)
3118{
3119}
3120
3121template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3122inline
3127
3128template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3129template <class INPUT_ITERATOR>
3130inline
3132 INPUT_ITERATOR first,
3133 INPUT_ITERATOR last,
3134 size_type initialNumBuckets,
3135 const HASH& hashFunction,
3136 const EQUAL& keyEqual,
3137 const ALLOCATOR& basicAllocator)
3138: d_impl(hashFunction, keyEqual, initialNumBuckets, 1.0f, basicAllocator)
3139{
3140 constructFromRange(first, last);
3141}
3142
3143template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3144template <class INPUT_ITERATOR>
3145inline
3147 INPUT_ITERATOR first,
3148 INPUT_ITERATOR last,
3149 size_type initialNumBuckets,
3150 const HASH& hashFunction,
3151 const ALLOCATOR& basicAllocator)
3152: d_impl(hashFunction, EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
3153{
3154 this->insert(first, last);
3155}
3156
3157template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3158template <class INPUT_ITERATOR>
3159inline
3161 INPUT_ITERATOR first,
3162 INPUT_ITERATOR last,
3163 size_type initialNumBuckets,
3164 const ALLOCATOR& basicAllocator)
3165: d_impl(HASH(), EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
3166{
3167 this->insert(first, last);
3168}
3169
3170template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3171template <class INPUT_ITERATOR>
3172inline
3174 INPUT_ITERATOR first,
3175 INPUT_ITERATOR last,
3176 const ALLOCATOR& basicAllocator)
3177: d_impl(basicAllocator)
3178{
3179 this->insert(first, last);
3180}
3181
3182#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
3183template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3184# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
3185template <class, class, class>
3186# endif
3187inline
3189 std::initializer_list<value_type> values,
3190 size_type initialNumBuckets,
3191 const HASH& hashFunction,
3192 const EQUAL& keyEqual,
3193 const ALLOCATOR& basicAllocator)
3194: d_impl(hashFunction, keyEqual, initialNumBuckets, 1.0f, basicAllocator)
3195{
3196 insert(values.begin(), values.end());
3197}
3198
3199template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3200# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
3201template <class, class>
3202# endif
3203inline
3205 std::initializer_list<value_type> values,
3206 size_type initialNumBuckets,
3207 const HASH& hashFunction,
3208 const ALLOCATOR& basicAllocator)
3209: d_impl(hashFunction, EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
3210{
3211 insert(values.begin(), values.end());
3212}
3213
3214template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3215# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
3216template <class>
3217# endif
3218inline
3220 std::initializer_list<value_type> values,
3221 size_type initialNumBuckets,
3222 const ALLOCATOR& basicAllocator)
3223: d_impl(HASH(), EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
3224{
3225 insert(values.begin(), values.end());
3226}
3227
3228template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3229# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
3230template <class>
3231# endif
3232inline
3234 std::initializer_list<value_type> values,
3235 const ALLOCATOR& basicAllocator)
3236: d_impl(basicAllocator)
3237{
3238 insert(values.begin(), values.end());
3239}
3240#endif
3241
3242template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3243inline
3245 const unordered_map& original)
3246: d_impl(original.d_impl,
3247 AllocatorTraits::select_on_container_copy_construction(
3248 original.get_allocator()))
3249{
3250}
3251
3252template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3253inline
3255 const unordered_map& original,
3256 const typename type_identity<ALLOCATOR>::type& basicAllocator)
3257: d_impl(original.d_impl, basicAllocator)
3258{
3259}
3260
3261template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3262inline
3264 BloombergLP::bslmf::MovableRef<unordered_map> original)
3265: d_impl(MoveUtil::access(original).get_allocator())
3266{
3267 unordered_map& lvalue = original;
3268
3269 this->swap(lvalue);
3270}
3271
3272template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3273inline
3275 BloombergLP::bslmf::MovableRef<unordered_map> original,
3276 const typename type_identity<ALLOCATOR>::type& basicAllocator)
3277: d_impl(MoveUtil::move(MoveUtil::access(original).d_impl), basicAllocator)
3278{
3279}
3280
3281template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3282inline
3284{
3285 // All memory management is handled by the base 'd_impl' member.
3286}
3287
3288// MANIPULATORS
3289template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3290inline
3293 const unordered_map& rhs)
3294{
3295 // Note that we have delegated responsibility for correct handling of
3296 // allocator propagation to the 'HashTable' implementation.
3297
3298 d_impl = rhs.d_impl;
3299
3300 return *this;
3301}
3302
3303template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3304inline
3307 BloombergLP::bslmf::MovableRef<unordered_map> rhs)
3309 AllocatorTraits::is_always_equal::value &&
3310 std::is_nothrow_move_assignable<HASH>::value &&
3311 std::is_nothrow_move_assignable<EQUAL>::value)
3312{
3313 // Note that we have delegated responsibility for correct handling of
3314 // allocator propagation to the 'HashTable' implementation.
3315
3316 unordered_map& lvalue = rhs;
3317
3318 d_impl = MoveUtil::move(lvalue.d_impl);
3319
3320 return *this;
3321}
3322
3323#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
3324template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3325inline
3326unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>&
3328 std::initializer_list<value_type> rhs)
3329{
3330 unordered_map tmp(rhs.begin(), rhs.end(), d_impl.allocator());
3331
3332 this->swap(tmp);
3333
3334 return *this;
3335}
3336#endif
3337
3338template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3339inline
3342 const key_type& key)
3343{
3344 HashTableLink *node = d_impl.insertIfMissing(key);
3345 return static_cast<HashTableNode *>(node)->value().second;
3346}
3347
3348template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3349inline
3352 BloombergLP::bslmf::MovableRef<key_type> key)
3353{
3354 HashTableLink *node = d_impl.insertIfMissing(
3355 MoveUtil::move(MoveUtil::access(key)));
3356 return static_cast<HashTableNode *>(node)->value().second;
3357}
3358
3359template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3360inline
3363{
3364 HashTableLink *node = d_impl.find(key);
3365
3366 if (!node) {
3367 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(
3368 "unordered_map<...>::at(key_type): invalid key value");
3369 }
3370
3371 return static_cast<HashTableNode *>(node)->value().second;
3372}
3373
3374template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3375inline
3379{
3380 return iterator(d_impl.elementListRoot());
3381}
3382
3383template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3384inline
3390
3391template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3392inline
3395{
3396 BSLS_ASSERT_SAFE(index < this->bucket_count());
3397
3398 return local_iterator(&d_impl.bucketAtIndex(index));
3399}
3400
3401template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3402inline
3405{
3406 BSLS_ASSERT_SAFE(index < this->bucket_count());
3407
3408 return local_iterator(0, &d_impl.bucketAtIndex(index));
3409}
3410
3411template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3412inline
3413void
3419
3420#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
3421template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3422template <class... Args>
3423bsl::pair<
3425 bool>
3427{
3428 typedef bsl::pair<iterator, bool> ResultType;
3429
3430 bool isInsertedFlag = false;
3431
3432 HashTableLink *result = d_impl.emplaceIfMissing(
3433 &isInsertedFlag,
3434 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
3435
3436 return ResultType(iterator(result), isInsertedFlag);
3437}
3438
3439template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3440template <class... Args>
3443 const_iterator, Args&&... args)
3444{
3445 // There is no realistic use-case for the 'hint' in an 'unordered_map' of
3446 // unique values. We could quickly test for a duplicate key, and have a
3447 // fast return path for when the method fails, but in the typical use case
3448 // where a new element is inserted, we are adding an extra key check for no
3449 // benefit. In order to insert an element into a bucket, we need to walk
3450 // the whole bucket looking for duplicates, and the hint is no help in
3451 // finding the start of a bucket.
3452
3453 bool isInsertedFlag = false;
3454
3455 HashTableLink *result = d_impl.emplaceIfMissing(
3456 &isInsertedFlag,
3457 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
3458
3459 return iterator(result);
3460}
3461#endif
3462
3463template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3464inline
3467 const_iterator position)
3468{
3469 BSLS_ASSERT_SAFE(position != this->end());
3470
3471 return iterator(d_impl.remove(position.node()));
3472}
3473
3474template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3475inline
3481
3482template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3485{
3486 HashTableLink *target = d_impl.find(key);
3487 if (target) {
3488 d_impl.remove(target);
3489 return 1; // RETURN
3490 }
3491 else {
3492 return 0; // RETURN
3493 }
3494}
3495
3496template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3499 const_iterator last)
3500{
3501
3502#if defined BDE_BUILD_TARGET_SAFE_2
3503 if (first != last) {
3504 iterator it = this->begin();
3505 const iterator end = this->end();
3506 for (; it != first; ++it) {
3507 BSLS_ASSERT(last != it);
3508 BSLS_ASSERT(end != it);
3509 }
3510 for (; it != last; ++it) {
3511 BSLS_ASSERT(end != it);
3512 }
3513 }
3514#endif
3515
3516 while (first != last) {
3517 first = this->erase(first);
3518 }
3519
3520 return iterator(first.node()); // convert from const_iterator
3521}
3522
3523template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3524inline
3526 const key_type& key) const
3527{
3528 return find(key) != end();
3529}
3530
3531template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3532inline
3535{
3536 return iterator(d_impl.find(key));
3537}
3538
3539template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3540inline
3542 bool>
3544 const value_type& value)
3545{
3546 typedef bsl::pair<iterator, bool> ResultType;
3547
3548 bool isInsertedFlag = false;
3549
3550 HashTableLink *result = d_impl.insertIfMissing(&isInsertedFlag, value);
3551
3552 return ResultType(iterator(result), isInsertedFlag);
3553}
3554
3555template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3556inline
3560 const value_type& value)
3561{
3562 bool isInsertedFlag; // not used
3563
3564 HashTableLink *result = d_impl.insertIfMissing(&isInsertedFlag, value);
3565
3566 return iterator(result);
3567}
3568
3569template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3570template <class INPUT_ITERATOR>
3572 INPUT_ITERATOR first,
3573 INPUT_ITERATOR last)
3574{
3575 insertFromRange(first, last);
3576}
3577
3578#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
3579template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3581 std::initializer_list<value_type> values)
3582{
3583 insert(values.begin(), values.end());
3584}
3585#endif
3586
3587#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
3588template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3589template <class BDE_OTHER_TYPE>
3591 bool>
3593 const KEY& key,
3594 BDE_OTHER_TYPE&& obj)
3595{
3596 typedef bsl::pair<iterator, bool> ResultType;
3597 bool isInsertedFlag = false;
3598 HashTableLink *result = d_impl.insertOrAssign(
3599 &isInsertedFlag,
3600 NULL,
3601 key,
3602 BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj));
3603 return ResultType(iterator(result), isInsertedFlag);
3604}
3605
3606template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3607template <class BDE_OTHER_TYPE>
3609 bool>
3611 BloombergLP::bslmf::MovableRef<KEY> key,
3612 BDE_OTHER_TYPE&& obj)
3613{
3614 typedef bsl::pair<iterator, bool> ResultType;
3615 bool isInsertedFlag = false;
3616 HashTableLink *result = d_impl.insertOrAssign(
3617 &isInsertedFlag,
3618 NULL,
3620 BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj));
3621 return ResultType(iterator(result), isInsertedFlag);
3622}
3623
3624template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3625template <class BDE_OTHER_TYPE>
3628 const_iterator hint,
3629 const KEY& key,
3630 BDE_OTHER_TYPE&& obj)
3631{
3632 bool isInsertedFlag = false;
3633 HashTableLink *result = d_impl.insertOrAssign(
3634 &isInsertedFlag,
3635 hint.node(),
3636 key,
3637 BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj));
3638 return iterator(result);
3639}
3640
3641template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3642template <class BDE_OTHER_TYPE>
3645 const_iterator hint,
3646 BloombergLP::bslmf::MovableRef<KEY> key,
3647 BDE_OTHER_TYPE&& obj)
3648{
3649 bool isInsertedFlag = false;
3650 HashTableLink *result = d_impl.insertOrAssign(
3651 &isInsertedFlag,
3652 hint.node(),
3654 BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj));
3655 return iterator(result);
3656}
3657#endif
3658
3659template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3660bsl::pair<
3664 const key_type& key)
3665{
3666 typedef bsl::pair<iterator, iterator> ResultType;
3667
3668 HashTableLink *first = d_impl.find(key);
3669 return first ? ResultType(iterator(first), iterator(first->nextLink()))
3670 : ResultType(iterator(0), iterator(0));
3671}
3672
3673template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3674inline
3675void
3677 float newMaxLoadFactor)
3678{
3679 d_impl.setMaxLoadFactor(newMaxLoadFactor);
3680}
3681
3682template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3683inline
3684void
3686 size_type numBuckets)
3687{
3688 d_impl.rehashForNumBuckets(numBuckets);
3689}
3690
3691template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3692inline
3693void
3695 size_type numElements)
3696{
3697 d_impl.reserveForNumElements(numElements);
3698}
3699
3700template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3701inline
3702void
3705 AllocatorTraits::is_always_equal::value &&
3706 bsl::is_nothrow_swappable<HASH>::value &&
3707 bsl::is_nothrow_swappable<EQUAL>::value)
3708{
3709 d_impl.swap(other.d_impl);
3710}
3711
3712#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
3713template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3714template <class... Args>
3715inline
3716bsl::pair<
3718 bool>
3720 const KEY& key,
3721 Args&&... args)
3722{
3723 typedef bsl::pair<iterator, bool> ResultType;
3724 bool isInsertedFlag = false;
3725 HashTableLink *result = d_impl.tryEmplace(
3726 &isInsertedFlag,
3727 NULL,
3728 key,
3729 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
3730
3731 return ResultType(iterator(result), isInsertedFlag);
3732}
3733
3734template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3735template <class... Args>
3736inline
3737bsl::pair<
3739 bool>
3741 BloombergLP::bslmf::MovableRef<KEY> key,
3742 Args&&... args)
3743{
3744 typedef bsl::pair<iterator, bool> ResultType;
3745 bool isInsertedFlag = false;
3746 HashTableLink *result = d_impl.tryEmplace(
3747 &isInsertedFlag,
3748 NULL,
3750 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
3751
3752 return ResultType(iterator(result), isInsertedFlag);
3753}
3754
3755template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3756template <class... Args>
3757inline
3760 const_iterator hint,
3761 const KEY& key,
3762 Args&&... args)
3763{
3764 bool isInsertedFlag = false;
3765 HashTableLink *result = d_impl.tryEmplace(
3766 &isInsertedFlag,
3767 hint.node(),
3768 key,
3769 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
3770
3771 return iterator(result);
3772}
3773
3774template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3775template <class... Args>
3776inline
3779 const_iterator hint,
3780 BloombergLP::bslmf::MovableRef<KEY> key,
3781 Args&&... args)
3782{
3783 bool isInsertedFlag = false;
3784 HashTableLink *result = d_impl.tryEmplace(
3785 &isInsertedFlag,
3786 hint.node(),
3788 BSLS_COMPILERFEATURES_FORWARD(Args, args)...);
3789
3790 return iterator(result);
3791}
3792#endif
3793
3794template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3795template <class INPUT_ITERATOR, class SENTINEL>
3796inline
3798 INPUT_ITERATOR first,
3799 SENTINEL last)
3800{
3801 ///Implementation Notes
3802 ///--------------------
3803 // If we can calculate the number of elements, reserve space for them
3804 // upfront to reduce rehashing. The calculation is done once since
3805 // `IteratorUtil::insertDistance` may be expensive for non-random-access
3806 // iterators.
3807
3808 if BSLS_KEYWORD_CONSTEXPR_CPP17 (BloombergLP::bslstl::IteratorUtil
3809 ::canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()) {
3810 this->reserve(this->size()
3811 + BloombergLP::bslstl::IteratorUtil::insertDistance(first, last));
3812 }
3813
3814 bool isInsertedFlag; // value is not used
3815
3816 while (first != last) {
3817 d_impl.insertIfMissing(&isInsertedFlag, *first);
3818 ++first;
3819 }
3820}
3821
3822#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
3823 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
3824
3825template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3826template <class INPUT_ITERATOR, class SENTINEL>
3827inline
3828void unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>::insertFromRange(
3829 INPUT_ITERATOR first,
3830 SENTINEL last,
3831 size_t numElements)
3832{
3834 !BloombergLP::bslstl::IteratorUtil
3835 ::canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()
3836 || numElements == static_cast<size_t>(
3837 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last))));
3838
3839 this->reserve(this->size() + numElements);
3840
3841 bool isInsertedFlag; // value is not used
3842
3843 while (first != last) {
3844 d_impl.insertIfMissing(&isInsertedFlag, *first);
3845 ++first;
3846 }
3847}
3848
3849#endif
3850
3851// ACCESSORS
3852template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3855 const key_type& key) const
3856{
3857 HashTableLink *target = d_impl.find(key);
3858 if (!target ){
3859 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(
3860 "unordered_map<...>::at(key_type): invalid key value");
3861 }
3862 return static_cast<HashTableNode *>(target)->value().second;
3863}
3864
3865template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3866inline
3870{
3871 return const_iterator(d_impl.elementListRoot());
3872}
3873
3874template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3875inline
3882
3883template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3884inline
3888{
3889 return const_iterator(d_impl.elementListRoot());
3890}
3891
3892template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3893inline
3900
3901template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3902inline
3903typename
3906{
3907 BSLS_ASSERT_SAFE(index < this->bucket_count());
3908
3909 return const_local_iterator(&d_impl.bucketAtIndex(index));
3910}
3911
3912template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3913inline
3914typename
3917{
3918 BSLS_ASSERT_SAFE(index < this->bucket_count());
3919
3920 return const_local_iterator(0, &d_impl.bucketAtIndex(index));
3921}
3922
3923template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3924inline
3925typename
3928 size_type index) const
3929{
3930 BSLS_ASSERT_SAFE(index < this->bucket_count());
3931
3932 return const_local_iterator(&d_impl.bucketAtIndex(index));
3933}
3934
3935template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3936inline
3937typename
3940{
3941 BSLS_ASSERT_SAFE(index < this->bucket_count());
3942
3943 return const_local_iterator(0, &d_impl.bucketAtIndex(index));
3944}
3945
3946template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3947inline
3950 const key_type& key) const
3951{
3952 return d_impl.bucketIndexForKey(key);
3953}
3954
3955template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3956inline
3960{
3961 return d_impl.numBuckets();
3962}
3963
3964template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3965inline
3969{
3970 return d_impl.maxNumBuckets();
3971}
3972
3973template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3974inline
3977 size_type index) const
3978{
3979 BSLS_ASSERT_SAFE(index < this->bucket_count());
3980
3981 return d_impl.countElementsInBucket(index);
3982}
3983
3984template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3985inline
3988 const key_type& key) const
3989{
3990 return d_impl.find(key) != 0;
3991}
3992
3993template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3994inline
3995bool
3998{
3999 return 0 == d_impl.size();
4000}
4001
4002template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4003bsl::pair<typename unordered_map<KEY,
4004 VALUE,
4005 HASH,
4006 EQUAL,
4007 ALLOCATOR>::const_iterator,
4008 typename unordered_map<KEY,
4009 VALUE,
4010 HASH,
4011 EQUAL,
4012 ALLOCATOR>::const_iterator>
4014 const key_type& key) const
4015{
4017
4018 HashTableLink *first = d_impl.find(key);
4019 return first
4020 ? ResultType(const_iterator(first), const_iterator(first->nextLink()))
4021 : ResultType(const_iterator(0), const_iterator(0));
4022}
4023
4024template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4025inline
4026typename
4029 const key_type& key) const
4030{
4031 return const_iterator(d_impl.find(key));
4032}
4033
4034template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4035inline
4036ALLOCATOR
4042
4043template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4044inline
4046{
4047 return d_impl.hasher();
4048}
4049
4050template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4051inline
4053{
4054 return d_impl.comparator();
4055}
4056
4057template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4058inline
4059float
4062{
4063 return d_impl.loadFactor();
4064}
4065
4066template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4067inline
4068float
4071{
4072 return d_impl.maxLoadFactor();
4073}
4074
4075template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4076inline
4080{
4081 return d_impl.size();
4082}
4083
4084template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4085inline
4089{
4090 return d_impl.maxSize();
4091}
4092
4093} // close namespace bsl
4094
4095// FREE OPERATORS
4096template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4097inline
4098bool bsl::operator==(
4101{
4102 return lhs.d_impl == rhs.d_impl;
4103}
4104
4105#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
4106template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4107inline
4108bool bsl::operator!=(
4111{
4112 return !(lhs == rhs);
4113}
4114#endif
4115
4116// FREE FUNCTIONS
4117template <class KEY,
4118 class VALUE,
4119 class HASH,
4120 class EQUAL,
4121 class ALLOCATOR,
4122 class PREDICATE>
4123inline
4125bsl::erase_if(unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& m,
4126 PREDICATE predicate)
4127{
4128 return BloombergLP::bslstl::AlgorithmUtil::containerEraseIf(m, predicate);
4129}
4130
4131template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4132inline
4133void
4137{
4138 a.swap(b);
4139}
4140
4141// ============================================================================
4142// TYPE TRAITS
4143// ============================================================================
4144
4145// Type traits for STL *unordered* *associative* containers:
4146//: o An unordered associative container defines STL iterators.
4147//: o An unordered associative container is bit-wise movable if both functors
4148//: and the allocator are bit-wise movable.
4149//: o An unordered associative container uses 'bslma' allocators if the
4150//: (template parameter) type 'ALLOCATOR' is convertible from
4151//: 'bslma::Allocator *'.
4152
4153
4154namespace bslalg {
4155
4156template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4157struct HasStlIterators<bsl::unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR> >
4159{};
4160
4161} // close namespace bslalg
4162
4163namespace bslma {
4164
4165template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4166struct UsesBslmaAllocator<bsl::unordered_map<KEY,
4167 VALUE,
4168 HASH,
4169 EQUAL,
4170 ALLOCATOR> >
4171 : bsl::is_convertible<Allocator*, ALLOCATOR>::type
4172{};
4173
4174} // close namespace bslma
4175
4176namespace bslmf {
4177
4178template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
4180 bsl::unordered_map<KEY, VALUE, HASH, EQUAL, ALLOCATOR> >
4181 : ::BloombergLP::bslmf::IsBitwiseMoveable<BloombergLP::bslstl::HashTable<
4182 ::BloombergLP::bslstl::
4183 UnorderedMapKeyConfiguration<KEY, bsl::pair<const KEY, VALUE> >,
4184 HASH,
4185 EQUAL,
4186 ALLOCATOR> >::type
4187{};
4188
4189} // close namespace bslma
4190
4191
4192#endif // End C++11 code
4193
4194#endif
4195
4196// ----------------------------------------------------------------------------
4197// Copyright 2013 Bloomberg Finance L.P.
4198//
4199// Licensed under the Apache License, Version 2.0 (the "License");
4200// you may not use this file except in compliance with the License.
4201// You may obtain a copy of the License at
4202//
4203// http://www.apache.org/licenses/LICENSE-2.0
4204//
4205// Unless required by applicable law or agreed to in writing, software
4206// distributed under the License is distributed on an "AS IS" BASIS,
4207// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4208// See the License for the specific language governing permissions and
4209// limitations under the License.
4210// ----------------------------- END-OF-FILE ----------------------------------
4211
4212/** @} */
4213/** @} */
4214/** @} */
Definition bslma_bslallocator.h:588
Definition bslstl_string.h:1252
Definition bslstl_pair.h:1280
Definition bslstl_unorderedmap.h:1123
unordered_map &operator=(BloombergLP::bslmf::MovableRef< unordered_map > rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits add_lvalue_reference< VALUE >::type operator[](const key_type &key)
Definition bslstl_unorderedmap.h:3341
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, iterator >::type find(const LOOKUP_KEY &key)
Definition bslstl_unorderedmap.h:1860
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3886
size_type erase(const key_type &key)
Definition bslstl_unorderedmap.h:3484
pair< iterator, bool > insert_or_assign(const KEY &key, BDE_OTHER_TYPE &&obj)
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, iterator >::type try_emplace(const_iterator hint, LOOKUP_KEY &&key, Args &&... args)
Definition bslstl_unorderedmap.h:2340
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this unordered map.
Definition bslstl_unorderedmap.h:4078
unordered_map(INPUT_ITERATOR first, INPUT_ITERATOR last, size_type initialNumBuckets, const ALLOCATOR &basicAllocator)
Definition bslstl_unorderedmap.h:3160
~unordered_map()
Destroy this object and each of its elements.
Definition bslstl_unorderedmap.h:3283
iterator insert_or_assign(const_iterator hint, BloombergLP::bslmf::MovableRef< KEY > key, BDE_OTHER_TYPE &&obj)
Definition bslstl_unorderedmap.h:3644
void insert_range(BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
Definition bslstl_unorderedmap.h:1778
enable_if< is_convertible< ALT_VALUE_TYPE, value_type >::value, iterator >::type insert(const_iterator hint, BSLS_COMPILERFEATURES_FORWARD_REF(ALT_VALUE_TYPE) value)
Definition bslstl_unorderedmap.h:1984
void insert(INPUT_ITERATOR first, INPUT_ITERATOR last)
Definition bslstl_unorderedmap.h:3571
AllocatorTraits::size_type size_type
Definition bslstl_unorderedmap.h:1227
float load_factor() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:4060
friend bool operator==(const unordered_map< KEY2, VALUE2, HASH2, EQUAL2, ALLOCATOR2 > &, const unordered_map< KEY2, VALUE2, HASH2, EQUAL2, ALLOCATOR2 > &)
pair< iterator, bool > try_emplace(BloombergLP::bslmf::MovableRef< KEY > key, Args &&... args)
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3386
unordered_map(size_type initialNumBuckets, const HASH &hashFunction=HASH(), const EQUAL &keyEqual=EQUAL(), const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_unorderedmap.h:3086
AllocatorTraits::pointer pointer
Definition bslstl_unorderedmap.h:1229
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, pair< iterator, bool > >::type insert_or_assign(LOOKUP_KEY &&key, BDE_OTHER_TYPE &&obj)
Definition bslstl_unorderedmap.h:2077
unordered_map(BloombergLP::bslmf::MovableRef< unordered_map > original, const typename type_identity< ALLOCATOR >::type &basicAllocator)
Definition bslstl_unorderedmap.h:3274
value_type & reference
Definition bslstl_unorderedmap.h:1224
const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3868
unordered_map(BloombergLP::bslmf::MovableRef< unordered_map > original)
Definition bslstl_unorderedmap.h:3263
EQUAL key_equal
Definition bslstl_unorderedmap.h:1221
pair< iterator, iterator > equal_range(const key_type &key)
Definition bslstl_unorderedmap.h:3663
AllocatorTraits::const_pointer const_pointer
Definition bslstl_unorderedmap.h:1230
iterator erase(iterator position)
Definition bslstl_unorderedmap.h:3477
void max_load_factor(float newMaxLoadFactor)
Definition bslstl_unorderedmap.h:3676
pair< const_iterator, const_iterator > equal_range(const key_type &key) const
Definition bslstl_unorderedmap.h:4013
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, typenameadd_lvalue_reference< VALUE >::type >::type at(const LOOKUP_KEY &key)
Definition bslstl_unorderedmap.h:1682
ALLOCATOR allocator_type
Definition bslstl_unorderedmap.h:1222
unordered_map(const ALLOCATOR &basicAllocator)
Definition bslstl_unorderedmap.h:3115
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition bslstl_unorderedmap.h:3442
unordered_map(INPUT_ITERATOR first, INPUT_ITERATOR last, size_type initialNumBuckets, const HASH &hashFunction, const ALLOCATOR &basicAllocator)
Definition bslstl_unorderedmap.h:3146
size_type bucket(const key_type &key) const
Definition bslstl_unorderedmap.h:3949
unordered_map(size_type initialNumBuckets, const ALLOCATOR &basicAllocator)
Definition bslstl_unorderedmap.h:3106
void rehash(size_type numBuckets)
Definition bslstl_unorderedmap.h:3685
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, pair< iterator, iterator > >::type equal_range(const LOOKUP_KEY &key)
Definition bslstl_unorderedmap.h:2167
iterator find(const key_type &key)
Definition bslstl_unorderedmap.h:3534
HASH hash_function() const
Definition bslstl_unorderedmap.h:4045
enable_if< is_convertible< ALT_VALUE_TYPE, value_type >::value, pair< iterator, bool > >::type insert(BSLS_COMPILERFEATURES_FORWARD_REF(ALT_VALUE_TYPE) value)
Definition bslstl_unorderedmap.h:1917
iterator insert_or_assign(const_iterator hint, const KEY &key, BDE_OTHER_TYPE &&obj)
Definition bslstl_unorderedmap.h:3627
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, bool >::type contains(const LOOKUP_KEY &key) const
Definition bslstl_unorderedmap.h:2503
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:4037
pair< iterator, bool > insert_or_assign(BloombergLP::bslmf::MovableRef< KEY > key, BDE_OTHER_TYPE &&obj)
HASH hasher
Definition bslstl_unorderedmap.h:1220
size_type count(const key_type &key) const
Definition bslstl_unorderedmap.h:3987
BloombergLP::bslstl::HashTableBucketIterator< value_type, difference_type > local_iterator
Definition bslstl_unorderedmap.h:1237
void reserve(size_type numElements)
Definition bslstl_unorderedmap.h:3694
iterator try_emplace(const_iterator hint, const KEY &key, Args &&... args)
unordered_map(size_type initialNumBuckets, const HASH &hashFunction, const ALLOCATOR &basicAllocator)
Definition bslstl_unorderedmap.h:3096
pair< iterator, bool > insert(const value_type &value)
Definition bslstl_unorderedmap.h:3543
iterator erase(const_iterator position)
Definition bslstl_unorderedmap.h:3466
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, typenameadd_lvalue_reference< constVALUE >::type >::type at(const LOOKUP_KEY &key) const
Definition bslstl_unorderedmap.h:2378
EQUAL key_eq() const
Definition bslstl_unorderedmap.h:4052
add_lvalue_reference< VALUE >::type operator[](BloombergLP::bslmf::MovableRef< key_type > key)
Definition bslstl_unorderedmap.h:3351
pair< iterator, bool > emplace(Args &&... args)
const value_type & const_reference
Definition bslstl_unorderedmap.h:1225
const_iterator find(const key_type &key) const
Definition bslstl_unorderedmap.h:4028
unordered_map(INPUT_ITERATOR first, INPUT_ITERATOR last, size_type initialNumBuckets=0, const HASH &hashFunction=HASH(), const EQUAL &keyEqual=EQUAL(), const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_unorderedmap.h:3131
size_type max_size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:4087
BloombergLP::bslstl::HashTableBucketIterator< const value_type, difference_type > const_local_iterator
Definition bslstl_unorderedmap.h:1239
unordered_map(const unordered_map &original)
Definition bslstl_unorderedmap.h:3244
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3895
void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3414
unordered_map()
Definition bslstl_unorderedmap.h:3123
float max_load_factor() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:4069
unordered_map & operator=(const unordered_map &rhs)
Definition bslstl_unorderedmap.h:3292
BloombergLP::bslstl::HashTableIterator< value_type, difference_type > iterator
Definition bslstl_unorderedmap.h:1233
AllocatorTraits::difference_type difference_type
Definition bslstl_unorderedmap.h:1228
bsl::pair< const KEY, VALUE > value_type
Definition bslstl_unorderedmap.h:1219
size_type max_bucket_count() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3967
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, size_type >::type count(const LOOKUP_KEY &key) const
Definition bslstl_unorderedmap.h:2477
iterator insert(const_iterator hint, const value_type &value)
Definition bslstl_unorderedmap.h:3558
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, t_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, t_KEY >::value &&!is_convertible< BSLS_COMPILERFEATURES_FORWARD_REF(t_KEY), iterator >::value &&!is_convertible< BSLS_COMPILERFEATURES_FORWARD_REF(t_KEY), const_iterator >::value, size_type >::type erase(BSLS_COMPILERFEATURES_FORWARD_REF(t_KEY) key)
Definition bslstl_unorderedmap.h:1825
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value &&!bsl::is_convertible< LOOKUP_KEY &&, const_iterator >::value &&!bsl::is_convertible< LOOKUP_KEY &&, iterator >::value, pair< iterator, bool > >::type try_emplace(LOOKUP_KEY &&key, Args &&... args)
Definition bslstl_unorderedmap.h:2281
KEY key_type
Definition bslstl_unorderedmap.h:1217
add_lvalue_reference< VALUE >::type at(const key_type &key)
Definition bslstl_unorderedmap.h:3362
unordered_map(INPUT_ITERATOR first, INPUT_ITERATOR last, const ALLOCATOR &basicAllocator)
Definition bslstl_unorderedmap.h:3173
VALUE mapped_type
Definition bslstl_unorderedmap.h:1218
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, iterator >::type insert_or_assign(const_iterator hint, LOOKUP_KEY &&key, BDE_OTHER_TYPE &&obj)
Definition bslstl_unorderedmap.h:2134
size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3958
void swap(unordered_map &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits pair< iterator, bool > try_emplace(const KEY &key, Args &&... args)
Definition bslstl_unorderedmap.h:2246
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, const_iterator >::type find(const LOOKUP_KEY &key) const
Definition bslstl_unorderedmap.h:2566
bool contains(const key_type &key) const
Definition bslstl_unorderedmap.h:3525
add_lvalue_reference< constVALUE >::type at(const key_type &key) const
Definition bslstl_unorderedmap.h:3854
iterator try_emplace(const_iterator hint, BloombergLP::bslmf::MovableRef< KEY > key, Args &&... args)
unordered_map(const unordered_map &original, const typename type_identity< ALLOCATOR >::type &basicAllocator)
Definition bslstl_unorderedmap.h:3254
iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3377
iterator erase(const_iterator first, const_iterator last)
Definition bslstl_unorderedmap.h:3498
BloombergLP::bslstl::HashTableIterator< const value_type, difference_type > const_iterator
Definition bslstl_unorderedmap.h:1235
bool empty() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmap.h:3996
size_type bucket_size(size_type index) const
Definition bslstl_unorderedmap.h:3976
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR_CPP17
Definition bsls_keyword.h:639
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
#define BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(...)
Definition bsls_keyword.h:676
#define BSLSTL_UNORDEREDMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
Definition bslstl_unorderedmap.h:1083
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
int reserve(TYPE *array, int numElements)
Definition bdlat_valuetypefunctions.h:939
void swap(array< VALUE_TYPE, SIZE > &lhs, array< VALUE_TYPE, SIZE > &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4424
T::iterator begin(T &container)
Definition bslstl_iterator.h:1593
const from_range_t from_range
ALLOCATOR & lhs
Definition bslstl_string.h:3917
T::iterator end(T &container)
Definition bslstl_iterator.h:1621
deque< VALUE_TYPE, ALLOCATOR >::size_type erase_if(deque< VALUE_TYPE, ALLOCATOR > &deq, PREDICATE predicate)
Definition bslstl_deque.h:4433
bool operator!=(const memory_resource &a, const memory_resource &b)
Definition bdlc_flathashmap.h:2218
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bdldfp_decimal.h:5549
t_TYPE & type
This typedef defines the return type of this meta function.
Definition bslmf_addlvaluereference.h:131
Definition bslma_allocatortraits.h:1089
BloombergLP::bslma::AllocatorTraits_ConstPointerType< ALLOCATOR >::type const_pointer
Definition bslma_allocatortraits.h:1183
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR >::type size_type
Definition bslma_allocatortraits.h:1196
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR >::type pointer
Definition bslma_allocatortraits.h:1180
BloombergLP::bslma::AllocatorTraits_DifferenceType< ALLOCATOR >::type difference_type
Definition bslma_allocatortraits.h:1193
Definition bslmf_enableif.h:530
Definition bslstl_equalto.h:316
Definition bslstl_ranges.h:301
Definition bslstl_hash.h:495
Definition bslmf_isconvertible.h:875
Definition bslalg_hasstliterators.h:99
Definition bslma_usesbslmaallocator.h:344
Definition bslmf_isbitwisemoveable.h:718