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