BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_unorderedmultimap.h
Go to the documentation of this file.
1/// @file bslstl_unorderedmultimap.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_unorderedmultimap.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_UNORDEREDMULTIMAP
9#define INCLUDED_BSLSTL_UNORDEREDMULTIMAP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_unorderedmultimap bslstl_unorderedmultimap
15/// @brief Provide an STL-compliant `unordered_multimap` container.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_unorderedmultimap
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_unorderedmultimap-purpose"> Purpose</a>
25/// * <a href="#bslstl_unorderedmultimap-classes"> Classes </a>
26/// * <a href="#bslstl_unorderedmultimap-canonical-header"> Canonical Header </a>
27/// * <a href="#bslstl_unorderedmultimap-description"> Description </a>
28/// * <a href="#bslstl_unorderedmultimap-requirements-on-key-and-value"> Requirements on KEY and VALUE </a>
29/// * <a href="#bslstl_unorderedmultimap-requirements-on-hash-and-equal"> Requirements on HASH and EQUAL </a>
30/// * <a href="#bslstl_unorderedmultimap-memory-allocation"> Memory Allocation </a>
31/// * <a href="#bslstl_unorderedmultimap-bslma-style-allocators"> bslma-Style Allocators </a>
32/// * <a href="#bslstl_unorderedmultimap-operations"> Operations </a>
33/// * <a href="#bslstl_unorderedmultimap-iterator-pointer-and-reference-invalidation"> Iterator, Pointer, and Reference Invalidation </a>
34/// * <a href="#bslstl_unorderedmultimap-unordered-multimap-configuration"> Unordered Multimap Configuration </a>
35/// * <a href="#bslstl_unorderedmultimap-practical-requirements-on-hash"> Practical Requirements on HASH </a>
36/// * <a href="#bslstl_unorderedmultimap-usage"> Usage </a>
37/// * <a href="#bslstl_unorderedmultimap-example-1-creating-a-concordance"> Example 1: Creating a Concordance </a>
38///
39/// # Purpose {#bslstl_unorderedmultimap-purpose}
40/// Provide an STL-compliant @ref unordered_multimap container.
41///
42/// # Classes {#bslstl_unorderedmultimap-classes}
43///
44/// - bsl::unordered_multimap : hashed-map container
45///
46/// # Canonical Header {#bslstl_unorderedmultimap-canonical-header}
47/// bsl_unordered_map.h
48///
49/// @see package bos+stdhdrs in the bos package group
50///
51/// # Description {#bslstl_unorderedmultimap-description}
52/// This component defines a single class template,
53/// `bsl::unordered_multimap`, implementing the standard container holding a
54/// collection of (possibly equivalent) keys, each mapped to an associated value
55/// (with minimal guarantees on ordering).
56///
57/// An instantiation of @ref unordered_multimap is an allocator-aware,
58/// value-semantic type whose salient attributes are its size (number of keys)
59/// and the set of key-value pairs the @ref unordered_multimap contains, without
60/// regard to their order. If @ref unordered_multimap is instantiated with a key
61/// type or mapped-value type that is not itself value-semantic, then it will
62/// not retain all of its value-semantic qualities. In particular, if ether the
63/// key or value type cannot be tested for equality, then an
64/// @ref unordered_multimap containing that type cannot be tested for equality. It
65/// is even possible to instantiate @ref unordered_multimap with a key or value
66/// type that does not have an accessible copy-constructor, in which case the
67/// @ref unordered_multimap will not be copyable. Note that the equality operator
68/// for each key-value pair is used to determine when two @ref unordered_multimap
69/// objects have the same value, and not the object of `EQUAL` type supplied at
70/// construction.
71///
72/// An @ref unordered_multimap meets the requirements of an unordered associative
73/// container with forward iterators in the C++11 standard [23.2.5]. The
74/// @ref unordered_multimap implemented here adheres to the C++11 standard when
75/// compiled with a C++11 compiler, and makes the best approximation when
76/// compiled with a C++03 compiler. In particular, for C++03 we emulate move
77/// semantics, but limit forwarding (in `emplace`) to `const` lvalues, and make
78/// no effort to emulate `noexcept` or initializer-lists.
79///
80/// ## Requirements on KEY and VALUE {#bslstl_unorderedmultimap-requirements-on-key-and-value}
81///
82///
83/// An @ref unordered_multimap is a fully Value-Semantic Type (see
84/// @ref bsldoc_glossary ) only if the supplied `KEY` and `VALUE` template
85/// parameters are themselves fully value-semantic. It is possible to
86/// instantiate an @ref unordered_multimap with `KEY` and `VALUE` parameter
87/// arguments that do not provide a full set of value-semantic operations, but
88/// then some methods of the container may not be instantiable. The following
89/// terminology, adopted from the C++11 standard, is used in the function
90/// documentation of @ref unordered_multimap to describe a function's requirements
91/// for the `KEY` and `VALUE` template parameters. These terms are also defined
92/// in section [17.6.3.1] of the C++11 standard. Note that, in the context of
93/// an @ref unordered_multimap instantiation, the requirements apply specifically
94/// to the unordered multimap's element type, `value_type`, which is an alias
95/// for `pair<const KEY, VALUE>`.
96///
97/// Legend
98/// ------
99/// `X` - denotes an allocator-aware container type (@ref unordered_multimap )
100/// `T` - `value_type` associated with `X`
101/// `A` - type of the allocator used by `X`
102/// `m` - lvalue of type `A` (allocator)
103/// `p`, - address (`T *`) of uninitialized storage for a `T` within an `X`
104/// `rv` - rvalue of type (non-`const`) `T`
105/// `v` - rvalue or lvalue of type (possibly `const`) `T`
106/// `args` - 0 or more arguments
107///
108/// The following terms are used to more precisely specify the requirements on
109/// template parameter types in function-level documentation.
110///
111/// *default-insertable*: `T` has a default constructor. More precisely, `T`
112/// is `default-insertable` into `X` means that the following expression is
113/// well-formed:
114///
115/// `allocator_traits<A>::construct(m, p)`
116///
117/// *move-insertable*: `T` provides a constructor that takes an rvalue of type
118/// (non-`const`) `T`. More precisely, `T` is `move-insertable` into `X`
119/// means that the following expression is well-formed:
120///
121/// `allocator_traits<A>::construct(m, p, rv)`
122///
123/// *copy-insertable*: `T` provides a constructor that takes an lvalue or
124/// rvalue of type (possibly `const`) `T`. More precisely, `T` is
125/// `copy-insertable` into `X` means that the following expression is
126/// well-formed:
127///
128/// `allocator_traits<A>::construct(m, p, v)`
129///
130/// *move-assignable*: `T` provides an assignment operator that takes an rvalue
131/// of type (non-`const`) `T`.
132///
133/// *copy-assignable*: `T` provides an assignment operator that takes an lvalue
134/// or rvalue of type (possibly `const`) `T`.
135///
136/// *emplace-constructible*: `T` is `emplace-constructible` into `X` from
137/// `args` means that the following expression is well-formed:
138///
139/// `allocator_traits<A>::construct(m, p, args)`
140///
141/// *erasable*: `T` provides a destructor. More precisely, `T` is `erasable`
142/// from `X` means that the following expression is well-formed:
143///
144/// `allocator_traits<A>::destroy(m, p)`
145///
146/// *equality-comparable*: The type provides an equality-comparison operator
147/// that defines an equivalence relationship and is both reflexive and
148/// transitive.
149///
150/// ## Requirements on HASH and EQUAL {#bslstl_unorderedmultimap-requirements-on-hash-and-equal}
151///
152///
153/// The (template parameter) types `HASH` and `EQUAL` must be copy-constructible
154/// function-objects. Note that this requirement is somewhat stronger than the
155/// requirement currently in the standard; see the discussion for Issue 2215
156/// (http://cplusplus.github.com/LWG/lwg-active.html#2215);
157///
158/// `HASH` shall support a function call operator compatible with the following
159/// statements:
160/// @code
161/// HASH hash;
162/// KEY key;
163/// std::size_t result = hash(key);
164/// @endcode
165/// where the definition of the called function meets the requirements of a
166/// hash function, as specified in {@ref bslstl_hash |Standard Hash Function}.
167///
168/// `EQUAL` shall support a function call operator compatible with the following
169/// statements:
170/// @code
171/// EQUAL equal;
172/// KEY key1, key2;
173/// bool result = equal(key1, key2);
174/// @endcode
175/// where the definition of the called function defines an equivalence
176/// relationship on keys that is both reflexive and transitive.
177///
178/// `HASH` and `EQUAL` function-objects are further constrained such that any
179/// two objects whose keys compare equivalent by the comparator shall also
180/// produce the same value from the hasher.
181///
182/// ## Memory Allocation {#bslstl_unorderedmultimap-memory-allocation}
183///
184///
185/// The type supplied as an unordered multimap's `ALLOCATOR` template parameter
186/// determines how that unordered multimap will allocate memory. The
187/// @ref unordered_multimap template supports allocators meeting the requirements
188/// of the C++11 standard [17.6.3.5]. In addition, it supports
189/// scoped-allocators derived from the `bslma::Allocator` memory allocation
190/// protocol. Clients intending to use `bslma`-style allocators should use the
191/// template's default `ALLOCATOR` type. The default type for the `ALLOCATOR`
192/// template parameter, `bsl::allocator`, provides a C++11 standard-compatible
193/// adapter for a `bslma::Allocator` object.
194///
195/// ### bslma-Style Allocators {#bslstl_unorderedmultimap-bslma-style-allocators}
196///
197///
198/// If the (template parameter) type `ALLOCATOR` of an @ref unordered_multimap
199/// instantiation is `bsl::allocator`, then objects of that unordered multimap
200/// type will conform to the standard behavior of a `bslma`-allocator-enabled
201/// type. Such an unordered multimap accepts an optional `bslma::Allocator`
202/// argument at construction. If the address of a `bslma::Allocator` object is
203/// explicitly supplied at construction, it is used to supply memory for the
204/// unordered multimap throughout its lifetime; otherwise, the unordered
205/// multimap will use the default allocator installed at the time of the
206/// unordered multimap's construction (see @ref bslma_default ). In addition to
207/// directly allocating memory from the indicated `bslma::Allocator`, an
208/// unordered multimap supplies that allocator's address to the constructors of
209/// contained objects of the (template parameter) types `KEY` and `VALUE`, if
210/// respectively, the types define the `bslma::UsesBslmaAllocator` trait.
211///
212/// ## Operations {#bslstl_unorderedmultimap-operations}
213///
214///
215/// This section describes the run-time complexity of operations on instances
216/// of @ref unordered_multimap :
217/// @code
218/// Legend
219/// ------
220/// 'K' - (template parameter) type 'KEY' of 'unordered_multimap'
221/// 'V' - (template parameter) type 'VALUE' of 'unordered_multimap'
222/// 'a', 'b' - two distinct objects of type 'unordered_multimap<K, V>'
223/// 'rv' - modifiable rvalue of type 'unordered_multimap<K, V>'
224/// 'n', 'm' - number of elements in 'a' and 'b', respectively
225/// 'w' - number of buckets of 'a'
226/// 'value_type' - 'pair<const K, V>'
227/// 'hf' - hash function for objects of type 'K'
228/// 'eq' - equivalence comparator for objects of type 'K'
229/// 'al' - STL-style memory allocator
230/// 'k' - an object of type 'K'
231/// 'v' - object of type 'V'
232/// 'vt' - object of type 'value_type'
233/// 'rvt' - modifiable rvalue of type 'value_type'
234/// 'idx' - bucket index
235/// 'li' - object of type 'initializer_list<value_type>'
236/// 'i1', 'i2' - two iterators defining a sequence of 'value_type' objects
237/// 'rg' - range of objects convertable to 'value_type'
238/// 'p1', 'p2' - two iterators belonging to 'a'
239/// distance(i1,i2) - the number of elements in the range '[i1 .. i2)'
240/// distance(p1,p2) - the number of elements in the range '[p1 .. p2)'
241/// 'z' - floating point value representing a load factor
242///
243/// +----------------------------------------------------+--------------------+
244/// | Operation | Complexity |
245/// +====================================================+====================+
246/// | unordered_multimap<K, V> a; (dflt construction) | O[1] |
247/// | unordered_multimap<K, V> a(al); | |
248/// +----------------------------------------------------+--------------------+
249/// | unordered_multimap<K, V> a(rv);(move construction) | O[1] if 'a' and |
250/// | unordered_multimap<K, V> a(rv, al); | 'rv' use the same |
251/// | | allocator, |
252/// | | O[n] otherwise |
253/// +----------------------------------------------------+--------------------+
254/// | unordered_multimap<K, V> a(b); (copy construction) | Average: O[n] |
255/// | unordered_multimap<K, V> a(b, al); | Worst: O[n^2] |
256/// +----------------------------------------------------+--------------------+
257/// | unordered_multimap<K, V> a(w); | O[n] |
258/// | unordered_multimap<K, V> a(w, al); | |
259/// | unordered_multimap<K, V> a(w, hf); | |
260/// | unordered_multimap<K, V> a(w, hf, al); | |
261/// | unordered_multimap<K, V> a(w, hf, eq); | |
262/// | unordered_multimap<K, V> a(w, hf, eq, al); | |
263/// +----------------------------------------------------+--------------------+
264/// | unordered_multimap<K, V> a(i1, i2); | Average: O[N] |
265/// | unordered_multimap<K, V> a(i1, i2, al); | Worst: O[N^2] |
266/// | unordered_multimap<K, V> a(i1, i2, w); | where N = |
267/// | unordered_multimap<K, V> a(i1, i2, w, al); | distance(i1, i2)] |
268/// | unordered_multimap<K, V> a(i1, i2, w, hf); | |
269/// | unordered_multimap<K, V> a(i1, i2, w, hf, al); | |
270/// | unordered_multimap<K, V> a(i1, i2, w, hf, eq); | |
271/// | unordered_multimap<K, V> a(i1, i2, w, hf, eq, al); | |
272/// +----------------------------------------------------+--------------------+
273/// | unordered_multimap<K, V> a(from_range, rg); | Average: O[N] |
274/// | unordered_multimap<K, V> a(from_range, rg, w); | Worst: O[N^2] |
275/// | unordered_multimap<K, V> a(from_range, rg, w, hf); | where N = range:: |
276/// | unordered_multimap<K, V> a(from_range, rg, w, hf, | distance(rg)|
277/// | eq); | |
278/// | unordered_multimap<K, V> a(from_range, rg, w, hf, | |
279/// | eq, al); | |
280/// +----------------------------------------------------+--------------------+
281/// | unordered_multimap<K, V> a(li); | Average: O[N] |
282/// | unordered_multimap<K, V> a(li, al); | Worst: O[N^2] |
283/// | unordered_multimap<K, V> a(li, w); | where N = |
284/// | unordered_multimap<K, V> a(li, w, al); | 'li.size()'|
285/// | unordered_multimap<K, V> a(li, w, hf); | |
286/// | unordered_multimap<K, V> a(li, w, hf, al); | |
287/// | unordered_multimap<K, V> a(li, w, hf, eq); | |
288/// | unordered_multimap<K, V> a(li, w, hf, eq, al); | |
289/// +----------------------------------------------------+--------------------+
290/// | a.~unordered_multimap<K, V>(); (destruction) | O[n] |
291/// +----------------------------------------------------+--------------------+
292/// | a = rv; (move assignment) | O[1] if 'a' and |
293/// | | 'rv' use the same |
294/// | | allocator, |
295/// | | O[n] otherwise |
296/// +----------------------------------------------------+--------------------+
297/// | a = b; (copy assignment) | Average: O[n] |
298/// | | Worst: O[n^2] |
299/// +----------------------------------------------------+--------------------+
300/// | a = li; | Average: O[N] |
301/// | | Worst: O[N^2] |
302/// | | where N = |
303/// | | 'li.size()'|
304/// +----------------------------------------------------+--------------------+
305/// | a.begin(), a.end(), a.cbegin(), a.cend() | O[1] |
306/// +----------------------------------------------------+--------------------+
307/// | a.begin(idx), a.end(idx), a.cbegin(idx), | O[1] |
308/// | a.cend(idx) | |
309/// +----------------------------------------------------+--------------------+
310/// | a == b, a != b | Best: O[n] |
311/// | | Worst: O[n^2] |
312/// +----------------------------------------------------+--------------------+
313/// | a.swap(b), swap(a, b) | O[1] |
314/// +----------------------------------------------------+--------------------+
315/// | a.key_eq() | O[1] |
316/// +----------------------------------------------------+--------------------+
317/// | a.hash_function() | O[1] |
318/// +----------------------------------------------------+--------------------+
319/// | a.size() | O[1] |
320/// +----------------------------------------------------+--------------------+
321/// | a.max_size() | O[1] |
322/// +----------------------------------------------------+--------------------+
323/// | a.empty() | O[1] |
324/// +----------------------------------------------------+--------------------+
325/// | a.allocator() | O[1] |
326/// +----------------------------------------------------+--------------------+
327/// | a.insert(vt) | Average: O[1] |
328/// | a.insert(rvt) | Worst: O[n] |
329/// | a.emplace(Args&&...) | |
330/// +----------------------------------------------------+--------------------+
331/// | a.insert(p1, vt) | Average: O[1] |
332/// | a.insert(p1, rvt) | Worst: O[n] |
333/// | a.emplace(p1, Args&&...) | |
334/// +----------------------------------------------------+--------------------+
335/// | a.insert(i1, i2) | Average: O[ |
336/// | | distance(i1, i2)]|
337/// | | Worst: O[n * |
338/// | | distance(i1, i2)]|
339/// +----------------------------------------------------+--------------------+
340/// | a.insert(li); | Average: O[N] |
341/// | | Worst: O[n * N] |
342/// | | where N = |
343/// | | 'li.size()'|
344/// +----------------------------------------------------+--------------------+
345/// | a.insert_range(rg) | Average: O[ |
346/// | | ranges:: |
347/// | | distance(rg)]|
348/// | | Worst: O[ n * |
349/// | | ranges:: |
350/// | | distance(rg)]|
351/// +----------------------------------------------------+--------------------+
352/// | a.erase(p1) | Average: O[1] |
353/// | | Worst: O[n] |
354/// +----------------------------------------------------+--------------------+
355/// | a.erase(k) | Average: |
356/// | | O[a.count(k)]|
357/// | | Worst: |
358/// | | O[n] |
359/// +----------------------------------------------------+--------------------+
360/// | a.erase(p1, p2) | Average: O[ |
361/// | | distance(p1, p2)]|
362/// | | Worst: O[n] |
363/// +----------------------------------------------------+--------------------+
364/// | a.clear() | O[n] |
365/// +----------------------------------------------------+--------------------+
366/// | a.contains(k) | Average: O[1] |
367/// | | Worst: O[n] |
368/// +----------------------------------------------------+--------------------+
369/// | a.find(k) | Average: O[1] |
370/// | | Worst: O[n] |
371/// +----------------------------------------------------+--------------------+
372/// | a.count(k) | Average: O[1] |
373/// | | Worst: O[n] |
374/// +----------------------------------------------------+--------------------+
375/// | a.equal_range(k) | Average: O[ |
376/// | | a.count(k)]|
377/// | | Worst: O[n] |
378/// +----------------------------------------------------+--------------------+
379/// | a.bucket_count() | O[1] |
380/// +----------------------------------------------------+--------------------+
381/// | a.max_bucket_count() | O[1] |
382/// +----------------------------------------------------+--------------------+
383/// | a.bucket(k) | O[1] |
384/// +----------------------------------------------------+--------------------+
385/// | a.bucket_size(idx) | O[1] |
386/// +----------------------------------------------------+--------------------+
387/// | a.load_factor() | O[1] |
388/// +----------------------------------------------------+--------------------+
389/// | a.max_load_factor() | O[1] |
390/// | a.max_load_factor(z) | Average: O[1] |
391/// +----------------------------------------------------+--------------------+
392/// | a.rehash(w) | Average: O[n] |
393/// | | Worst: O[n^2] |
394/// +----------------------------------------------------+--------------------+
395/// | a.reserve(w) | Average: O[n] |
396/// | | Worst: O[n^2] |
397/// +----------------------------------------------------+--------------------+
398/// @endcode
399///
400/// ## Iterator, Pointer, and Reference Invalidation {#bslstl_unorderedmultimap-iterator-pointer-and-reference-invalidation}
401///
402///
403/// No method of @ref unordered_multimap invalidates a pointer or reference to an
404/// element in the unordered multimap unless it erases that element, such as any
405/// `erase` overload, `clear`, or the destructor (which erases all elements).
406/// Pointers and references are stable through a rehash.
407///
408/// Iterators to elements in the container are invalidated by any rehash, so
409/// iterators may be invalidated by an `insert` or `emplace` call if it triggers
410/// a rehash (but not otherwise). Iterators to specific elements are also
411/// invalidated when those elements are erased. Note that although the `end`
412/// iterator does not refer to any element in the container, it may be
413/// invalidated by any non-`const` method.
414///
415/// ## Unordered Multimap Configuration {#bslstl_unorderedmultimap-unordered-multimap-configuration}
416///
417///
418/// The unordered multimap has interfaces that can provide insight into, and
419/// control of, its inner workings. The syntax and semantics of these
420/// interfaces for `bsl::unordered_multimap` are identical to those of
421/// `bsl::unordered_map`. See the discussion in
422/// {@ref bslstl_unorderedmap |Unordered Map Configuration} and the illustrative
423/// material in {@ref bslstl_unorderedmap |Example 2}.
424///
425/// ## Practical Requirements on HASH {#bslstl_unorderedmultimap-practical-requirements-on-hash}
426///
427///
428/// An important factor in the performance of an unordered multimap (and any of
429/// the other unordered containers) is the choice of a hash function. Please
430/// see the discussion in {@ref bslstl_unorderedmap |Practical Requirements on
431/// `HASH`}.
432///
433/// ## Usage {#bslstl_unorderedmultimap-usage}
434///
435///
436/// In this section we show intended use of this component.
437///
438/// ### Example 1: Creating a Concordance {#bslstl_unorderedmultimap-example-1-creating-a-concordance}
439///
440///
441/// Unordered multimaps are useful in situations when there is no meaningful way
442/// to compare key values, when the order of the keys is irrelevant to the
443/// problem domain, or (even if there is a meaningful ordering) the benefit of
444/// ordering the results is outweighed by the higher performance provided by
445/// unordered multimaps (compared to ordered multimaps).
446///
447/// One uses a multimap (ordered or unordered) when there may be more than one
448/// mapped value associated with a key value. In this example we will use
449/// @ref bslstl_unorderedmultimap to create a concordance (an index of where each
450/// unique word appears in the set of documents).
451///
452/// Our source of documents is a set of statically initialized arrays:
453/// @code
454/// static char document0[] =
455/// " IN CONGRESS, July 4, 1776.\n"
456/// "\n"
457/// " The unanimous Declaration of the thirteen united States of America,\n"
458/// "\n"
459/// " When in the Course of human events, it becomes necessary for one\n"
460/// " people to dissolve the political bands which have connected them with\n"
461/// " another, and to assume among the powers of the earth, the separate\n"
462/// " and equal station to which the Laws of Nature and of Nature's God\n"
463/// " entitle them, a decent respect to the opinions of mankind requires\n"
464/// " that they should declare the causes which impel them to the\n"
465/// " separation. We hold these truths to be self-evident, that all men\n"
466/// " are created equal, that they are endowed by their Creator with\n"
467/// " certain unalienable Rights, that among these are Life, Liberty and\n"
468/// " the pursuit of Happiness.--That to secure these rights, Governments\n"
469/// " are instituted among Men, deriving their just powers from the consent\n"
470/// " of the governed, --That whenever any Form of Government becomes\n"
471/// ...
472/// " States may of right do. And for the support of this Declaration,\n"
473/// " with a firm reliance on the protection of divine Providence, we\n"
474/// " mutually pledge to each other our Lives, our Fortunes and our sacred\n"
475/// " Honor.\n";
476///
477/// static char document1[] =
478/// "/The Universal Declaration of Human Rights\n"
479/// "/-----------------------------------------\n"
480/// "/Preamble\n"
481/// "/ - - - -\n"
482/// " Whereas recognition of the inherent dignity and of the equal and\n"
483/// " inalienable rights of all members of the human family is the\n"
484/// " foundation of freedom, justice and peace in the world,\n"
485/// ...
486/// "/Article 30\n"
487/// "/ - - - - -\n"
488/// " Nothing in this Declaration may be interpreted as implying for any\n"
489/// " State, group or person any right to engage in any activity or to\n"
490/// " perform any act aimed at the destruction of any of the rights and\n"
491/// " freedoms set forth herein.\n";
492///
493/// static char document2[] =
494/// "/CHARTER OF FUNDAMENTAL RIGHTS OF THE EUROPEAN UNION\n"
495/// "/---------------------------------------------------\n"
496/// " PREAMBLE\n"
497/// "\n"
498/// " The peoples of Europe, in creating an ever closer union among them,\n"
499/// " are resolved to share a peaceful future based on common values.\n"
500/// ...
501/// "/Article 54\n"
502/// "/- - - -\n"
503/// " Prohibition of abuse of rights\n"
504/// "\n"
505/// " Nothing in this Charter shall be interpreted as implying any right to\n"
506/// " engage in any activity or to perform any act aimed at the destruction\n"
507/// " of any of the rights and freedoms recognized in this Charter or at\n"
508/// " their limitation to a greater extent than is provided for herein.\n";
509///
510/// static char * const documents[] = { document0,
511/// document1,
512/// document2
513/// };
514/// const int numDocuments = sizeof documents / sizeof *documents;
515/// @endcode
516/// First, we define several aliases to make our code more comprehensible:
517/// @code
518/// /// Document code number (`first`) and word offset (`second`) in that
519/// /// document specify a word location. The first word in the document
520/// /// is at word offset 0.
521/// typedef bsl::pair<int, int> WordLocation;
522///
523/// typedef bsl::unordered_multimap<bsl::string, WordLocation>
524/// Concordance;
525/// typedef Concordance::const_iterator ConcordanceConstItr;
526/// @endcode
527/// Next, we create an (empty) unordered multimap to hold our word tallies:
528/// @code
529/// Concordance concordance;
530/// @endcode
531/// Then, we define the set of characters that define word boundaries:
532/// @code
533/// const char *delimiters = " \n\t,:;.()[]?!/";
534/// @endcode
535/// Next, we extract the words from our documents. Note that `strtok` modifies
536/// the document arrays (which were not made `const`).
537///
538/// As each word is located, we create a map value -- a pair of the word
539/// converted to a `bsl::string` and a `WordLocation` object (itself a pair of
540/// document code and (word) offset of that word in the document) -- and insert
541/// the map value into the unordered multimap. Note that (unlike maps and
542/// unordered maps) there is no status to check; the insertion succeeds even if
543/// the key is already present in the unordered multimap.
544/// @code
545/// for (int idx = 0; idx < numDocuments; ++idx) {
546/// int wordOffset = 0;
547/// for (char *cur = strtok(documents[idx], delimiters);
548/// cur;
549/// cur = strtok(NULL, delimiters)) {
550/// WordLocation location(idx, wordOffset++);
551/// Concordance::value_type value(bsl::string(cur), location);
552/// concordance.insert(value);
553/// }
554/// }
555/// @endcode
556/// Then, we can print a complete concordance by iterating through the unordered
557/// multimap:
558/// @code
559/// for (ConcordanceConstItr itr = concordance.begin(),
560/// end = concordance.end();
561/// end != itr; ++itr) {
562/// printf("\"%s\", %2d, %4d\n",
563/// itr->first.c_str(),
564/// itr->second.first,
565/// itr->second.second);
566/// }
567/// @endcode
568/// Standard output shows:
569/// @code
570/// "extent", 2, 3837
571/// "greater", 2, 3836
572/// "abuse", 2, 3791
573/// "constitutions", 2, 3782
574/// "affecting", 2, 3727
575/// ...
576/// "he", 1, 1746
577/// "he", 1, 714
578/// "he", 0, 401
579/// "include", 2, 847
580/// @endcode
581/// Next, if there are some particular words of interest, we seek them out using
582/// the @ref equal_range method of the `concordance` object:
583/// @code
584/// const bsl::string wordsOfInterest[] = { "human",
585/// "rights",
586/// "unalienable",
587/// "inalienable"
588/// };
589/// const size_t numWordsOfInterest = sizeof wordsOfInterest
590/// / sizeof *wordsOfInterest;
591///
592/// for (size_t idx = 0; idx < numWordsOfInterest; ++idx) {
593/// bsl::pair<ConcordanceConstItr,
594/// ConcordanceConstItr> found = concordance.equal_range(
595/// wordsOfInterest[idx]);
596/// for (ConcordanceConstItr itr = found.first,
597/// end = found.second;
598/// end != itr; ++itr) {
599/// printf("\"%s\", %2d, %4d\n",
600/// itr->first.c_str(),
601/// itr->second.first,
602/// itr->second.second);
603/// }
604/// printf("\n");
605/// }
606/// @endcode
607/// Finally, we see on standard output:
608/// @code
609/// "human", 2, 3492
610/// "human", 2, 2192
611/// "human", 2, 534
612/// ...
613/// "human", 1, 65
614/// "human", 1, 43
615/// "human", 1, 25
616/// "human", 0, 20
617///
618/// "rights", 2, 3583
619/// "rights", 2, 3553
620/// "rights", 2, 3493
621/// ...
622/// "rights", 1, 44
623/// "rights", 1, 19
624/// "rights", 0, 496
625/// "rights", 0, 126
626///
627/// "unalienable", 0, 109
628///
629/// "inalienable", 1, 18
630///
631/// @endcode
632/// {@ref bslstl_unorderedmap |Example 3} shows how to use the concordance to create
633/// an inverse concordance, and how to use the inverse concordance to find the
634/// context (surrounding words) of a word of interest.
635/// @}
636/** @} */
637/** @} */
638
639/** @addtogroup bsl
640 * @{
641 */
642/** @addtogroup bslstl
643 * @{
644 */
645/** @addtogroup bslstl_unorderedmultimap
646 * @{
647 */
648
649#include <bslscm_version.h>
650
651#include <bslstl_algorithm.h>
652#include <bslstl_equalto.h>
653#include <bslstl_hash.h>
654#include <bslstl_hashtable.h>
657#include <bslstl_iteratorutil.h>
658#include <bslstl_pair.h>
659#include <bslstl_ranges.h>
661
665
667#include <bslma_isstdallocator.h>
668#include <bslma_bslallocator.h>
670
672#include <bslmf_enableif.h>
674#include <bslmf_isconvertible.h>
675#include <bslmf_movableref.h>
677#include <bslmf_typeidentity.h>
678#include <bslmf_util.h> // 'forward(V)'
679
680#include <bsls_assert.h>
682#include <bsls_keyword.h>
683#include <bsls_performancehint.h>
684#include <bsls_platform.h>
685#include <bsls_util.h> // 'forward<T>(V)'
686
687#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
688# include <initializer_list>
689#endif
690
691#ifdef BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER
692#include <type_traits> // 'std::is_constructible'
693 #ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
694 #error Rvalue references curiously absent despite native 'type_traits'.
695 #endif
696#endif
697
698#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
699 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
700# define BSLSTL_UNORDEREDMULTIMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T) \
701 requires ::BloombergLP::bslmf::ContainerCompatibleRange<R, T>
702#else
703# define BSLSTL_UNORDEREDMULTIMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
704#endif
705
706#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
707// clang-format off
708// Include version that can be compiled with C++03
709// Generated on Mon Jan 13 08:31:39 2025
710// Command line: sim_cpp11_features.pl bslstl_unorderedmultimap.h
711
712# define COMPILING_BSLSTL_UNORDEREDMULTIMAP_H
714# undef COMPILING_BSLSTL_UNORDEREDMULTIMAP_H
715
716// clang-format on
717#else
718
719namespace bsl {
720
721/// This class template implements a value-semantic container type holding a
722/// collection of (possibly equivalent) keys (of the template parameter type
723/// `KEY`), each mapped to their associated values (of another template
724/// parameter type `VALUE`).
725///
726/// This class:
727/// * supports a complete set of *value-semantic* operations
728/// - except for BDEX serialization
729/// * is *exception-neutral* (agnostic except for the `at` method)
730/// * is *alias-safe*
731/// * is `const` *thread-safe*
732/// For terminology see @ref bsldoc_glossary .
733///
734/// See @ref bslstl_unorderedmultimap
735template <class KEY,
736 class VALUE,
737 class HASH = bsl::hash<KEY>,
738 class EQUAL = bsl::equal_to<KEY>,
741
742 private:
743 // PRIVATE TYPES
744
745 /// This `typedef` is an alias for the allocator traits type associated
746 /// with this container.
748
749 /// This `typedef` is an alias for the type of key-value pair objects
750 /// maintained by this unordered multimap.
751 typedef pair<const KEY, VALUE> ValueType;
752
753 /// This `typedef` is an alias for the policy used internally by this
754 /// container to extract the `KEY` value from the values maintained by
755 /// this unordered multimap.
756 typedef ::BloombergLP::bslstl::UnorderedMapKeyConfiguration<const KEY,
757 ValueType>
758 ListConfiguration;
759
760 /// This `typedef` is an alias for the template instantiation of the
761 /// underlying `bslstl::HashTable` used to implement this unordered
762 /// multimap.
763 typedef ::BloombergLP::bslstl::HashTable<ListConfiguration,
764 HASH,
765 EQUAL,
766 ALLOCATOR> Impl;
767
768 /// This `typedef` is an alias for the type of links maintained by the
769 /// linked list of elements held by the underlying `bslstl::HashTable`.
770 typedef ::BloombergLP::bslalg::BidirectionalLink HashTableLink;
771
772 /// This `typedef` is a convenient alias for the utility associated with
773 /// movable references.
774 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
775
776 // FRIENDS
777 template <class KEY2,
778 class VALUE2,
779 class HASH2,
780 class EQUAL2,
781 class ALLOCATOR2>
782 friend bool operator==(
785
786 public:
787 // PUBLIC TYPES
788 typedef KEY key_type;
789 typedef VALUE mapped_type;
791 typedef HASH hasher;
792 typedef EQUAL key_equal;
793 typedef ALLOCATOR allocator_type;
794
797
802
803 typedef ::BloombergLP::bslstl::HashTableIterator<
805
806 typedef ::BloombergLP::bslstl::HashTableIterator<
808
809 typedef ::BloombergLP::bslstl::HashTableBucketIterator<
811
812 typedef ::BloombergLP::bslstl::HashTableBucketIterator<
814
815 private:
816 // DATA
817 Impl d_impl;
818
819 public:
820 // CREATORS
821
822 /// Create an empty unordered multimap. Optionally specify an
823 /// `initialNumBuckets` indicating the minimum initial size of the array
824 /// of buckets of this container. If `initialNumBuckets` is not
825 /// supplied, a single empty bucket is used. Optionally specify a
826 /// `hashFunction` used to generate the hash values for the keys
827 /// contained in this unordered multimap. If `hashFunction` is not
828 /// supplied, a default-constructed object of the (template parameter)
829 /// type `HASH` is used. Optionally specify a key-equivalence functor
830 /// `keyEqual` used to verify that two keys are equivalent. If
831 /// `keyEqual` is not supplied, a default-constructed object of the
832 /// (template parameter) type `EQUAL` is used. Optionally specify a
833 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
834 /// supplied, a default-constructed object of the (template parameter)
835 /// type `ALLOCATOR` is used. If the type `ALLOCATOR` is
836 /// `bsl::allocator` (the default), then `basicAllocator`, if supplied,
837 /// shall be convertible to `bslma::Allocator *`. If the type
838 /// `ALLOCATOR` is `bsl::allocator` and `basicAllocator` is not
839 /// supplied, the currently installed default allocator is used.
841 explicit unordered_multimap(size_type initialNumBuckets,
842 const HASH& hashFunction = HASH(),
843 const EQUAL& keyEqual = EQUAL(),
844 const ALLOCATOR& basicAllocator = ALLOCATOR());
845 unordered_multimap(size_type initialNumBuckets,
846 const HASH& hashFunction,
847 const ALLOCATOR& basicAllocator);
848 unordered_multimap(size_type initialNumBuckets,
849 const ALLOCATOR& basicAllocator);
850 explicit unordered_multimap(const ALLOCATOR& basicAllocator);
851
852 /// Create an unordered multimap having the same value as the specified
853 /// `original` object. Use a copy of `original.hash_function()` to
854 /// generate hash values for the keys contained in this unordered
855 /// multimap. Use a copy of `original.key_eq()` to verify that two keys
856 /// are equivalent. Use the allocator returned by
857 /// `bsl::allocator_traits<ALLOCATOR>::
858 /// select_on_container_copy_construction(original.get_allocator())` to
859 /// allocate memory. This method requires that the (template parameter)
860 /// types `KEY` and `VALUE` both be `copy-insertable` into this
861 /// unordered multimap (see {Requirements on `KEY` and `VALUE`}).
862 unordered_multimap(const unordered_multimap& original);
863
864 /// Create an unordered multimap having the same value as the specified
865 /// `original` object by moving (in constant time) the contents of
866 /// `original` to the new unordered multimap. Use a copy of
867 /// `original.hash_function()` to generate hash values for the keys
868 /// contained in this unordered multimap. Use a copy of
869 /// `original.key_eq()` to verify that two keys are equivalent. The
870 /// allocator associated with `original` is propagated for use in the
871 /// newly-created unordered multimap. `original` is left in a valid but
872 /// unspecified state.
874 BloombergLP::bslmf::MovableRef<unordered_multimap> original);
875
876 /// Create an unordered multimap having the same value as the specified
877 /// `original` object that uses the specified `basicAllocator` to supply
878 /// memory. Use a copy of `original.hash_function()` to generate hash
879 /// values for the keys contained in this unordered multimap. Use a
880 /// copy of `original.key_eq()` to verify that two keys are equivalent.
881 /// This method requires that the (template parameter) types `KEY` and
882 /// `VALUE` both be `copy-insertable` into this unordered multimap (see {Requirements on `KEY` and `VALUE`}).
883 ///
884 /// \note Note that a
885 /// `bslma::Allocator *` can be supplied for `basicAllocator` if the
886 /// (template parameter) type `ALLOCATOR` is `bsl::allocator` (the
887 /// default).
889 const unordered_multimap& original,
890 const typename type_identity<ALLOCATOR>::type& basicAllocator);
891
892 /// Create an unordered multimap having the same value as the specified
893 /// `original` object that uses the specified `basicAllocator` to supply
894 /// memory. The contents of `original` are moved (in constant time) to
895 /// the new unordered multimap if `basicAllocator ==
896 /// original.get_allocator()`, and are move-inserted (in linear time)
897 /// using `basicAllocator` otherwise. `original` is left in a valid but
898 /// unspecified state. Use a copy of `original.hash_function()` to
899 /// generate hash values for the keys contained in this unordered
900 /// multimap. Use a copy of `original.key_eq()` to verify that two keys
901 /// are equivalent. This method requires that the (template parameter)
902 /// types `KEY` and `VALUE` both be `move-insertable` into this
903 /// unordered multimap (see {Requirements on `KEY` and `VALUE`}).
904 ///
905 /// \note Note that a `bslma::Allocator *` can be supplied for `basicAllocator` if
906 /// the (template parameter) type `ALLOCATOR` is `bsl::allocator` (the
907 /// default).
909 BloombergLP::bslmf::MovableRef<unordered_multimap> original,
910 const typename type_identity<ALLOCATOR>::type& basicAllocator);
911
912 /// Create an unordered multimap, and insert each `value_type` object in
913 /// the sequence starting at the specified `first` element, and ending
914 /// immediately before the specified `last` element. Optionally specify
915 /// an `initialNumBuckets` indicating the minimum initial size of the
916 /// array of buckets of this container. If `initialNumBuckets` is not
917 /// supplied, a single empty bucket is used if `first` and `last` denote
918 /// an empty range, and an unspecified number of buckets is used
919 /// otherwise. Optionally specify a `hashFunction` used to generate
920 /// hash values for the keys contained in this unordered multimap. If
921 /// `hashFunction` is not supplied, a default-constructed object of
922 /// (template parameter) type `HASH` is used. Optionally specify a
923 /// key-equivalence functor `keyEqual` used to verify that two keys are
924 /// equivalent. If `keyEqual` is not supplied, a default-constructed
925 /// object of (template parameter) type `EQUAL` is used. Optionally
926 /// specify a `basicAllocator` used to supply memory. If
927 /// `basicAllocator` is not supplied, a default-constructed object of
928 /// the (template parameter) type `ALLOCATOR` is used. If the type
929 /// `ALLOCATOR` is `bsl::allocator` and `basicAllocator` is not
930 /// supplied, the currently installed default allocator is used to
931 /// supply memory. The (template parameter) type `INPUT_ITERATOR` shall
932 /// meet the requirements of an input iterator defined in the C++11
933 /// standard [24.2.3] providing access to values of a type convertible
934 /// to `value_type`, and `value_type` must be `emplace-constructible`
935 /// from `*i` into this unordered multimap, where `i` is a
936 /// dereferenceable iterator in the range `[first .. last)` (see
937 /// {Requirements on `KEY` and `VALUE`}).
938 ///
939 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid values where `first` is at a position at or before `last`.
940 ///
941 /// \note Note that a
942 /// `bslma::Allocator *` can be supplied for `basicAllocator` if the
943 /// type `ALLOCATOR` is `bsl::allocator` (the default).
944 template <class INPUT_ITERATOR>
945 unordered_multimap(INPUT_ITERATOR first,
946 INPUT_ITERATOR last,
947 size_type initialNumBuckets = 0,
948 const HASH& hashFunction = HASH(),
949 const EQUAL& keyEqual = EQUAL(),
950 const ALLOCATOR& basicAllocator = ALLOCATOR());
951 template <class INPUT_ITERATOR>
952 unordered_multimap(INPUT_ITERATOR first,
953 INPUT_ITERATOR last,
954 size_type initialNumBuckets,
955 const HASH& hashFunction,
956 const ALLOCATOR& basicAllocator);
957 template <class INPUT_ITERATOR>
958 unordered_multimap(INPUT_ITERATOR first,
959 INPUT_ITERATOR last,
960 size_type initialNumBuckets,
961 const ALLOCATOR& basicAllocator);
962 template <class INPUT_ITERATOR>
963 unordered_multimap(INPUT_ITERATOR first,
964 INPUT_ITERATOR last,
965 const ALLOCATOR& basicAllocator);
966
967#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
968# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
969 template <
970 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
971 class = bsl::enable_if_t<
972 std::is_invocable_v<EQUAL, const KEY &, const KEY &>>,
973 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
974 >
975# endif
977 std::initializer_list<value_type> values,
978 size_type initialNumBuckets = 0,
979 const HASH& hashFunction = HASH(),
980 const EQUAL& keyEqual = EQUAL(),
981 const ALLOCATOR& basicAllocator = ALLOCATOR());
982# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
983 template <
984 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
985 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
986 >
987# endif
988 unordered_multimap(std::initializer_list<value_type> values,
989 size_type initialNumBuckets,
990 const HASH& hashFunction,
991 const ALLOCATOR& basicAllocator);
992# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
993 template <
994 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
995 >
996# endif
997 unordered_multimap(std::initializer_list<value_type> values,
998 size_type initialNumBuckets,
999 const ALLOCATOR& basicAllocator);
1000# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1001 /// Create an unordered multimap and insert each `value_type` object in
1002 /// the specified `values` initializer list. Optionally specify an
1003 /// `initialNumBuckets` indicating the minimum initial size of the array
1004 /// of buckets of this container. If `initialNumBuckets` is not
1005 /// supplied, a single empty bucket is used if `values` is empty, and an
1006 /// unspecified number of buckets is used otherwise. Optionally specify
1007 /// a `hashFunction` used to generate the hash values for the keys
1008 /// contained in this unordered multimap. If `hashFunction` is not
1009 /// supplied, a default-constructed object of the (template parameter)
1010 /// type `HASH` is used. Optionally specify a key-equivalence functor
1011 /// `keyEqual` used to verify that two keys are equivalent. If
1012 /// `keyEqual` is not supplied, a default-constructed object of the
1013 /// (template parameter) type `EQUAL` is used. Optionally specify a
1014 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1015 /// supplied, a default-constructed object of the (template parameter)
1016 /// type `ALLOCATOR` is used. If the type `ALLOCATOR` is
1017 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
1018 /// installed default allocator is used to supply memory. This method
1019 /// requires that the (template parameter) types `KEY` and `VALUE` both
1020 /// be `copy-insertable` into this unordered multimap (see {Requirements on `KEY` and `VALUE`}).
1021 ///
1022 /// \note Note that a `bslma::Allocator *` can be
1023 /// supplied for `basicAllocator` if the type `ALLOCATOR` is
1024 /// `bsl::allocator` (the default).
1025 template <
1026 class = bsl::enable_if_t< bsl::IsStdAllocator_v<ALLOCATOR>>
1027 >
1028# endif
1029 unordered_multimap(std::initializer_list<value_type> values,
1030 const ALLOCATOR& basicAllocator);
1031#endif
1032
1033 /// Create an unordered multimap, and insert each `value_type` object in
1034 /// the specified `range`. Optionally specify an `initialNumBuckets`
1035 /// indicating the initial size of the array of buckets of this
1036 /// container. If `initialNumBuckets` is not supplied, an
1037 /// implementation-defined value is used. Optionally specify a
1038 /// `hashFunction` used to generate the hash values for each key value
1039 /// contained in this unordered multimap. If `hashFunction` is not
1040 /// supplied, a default-constructed object of the (template parameter)
1041 /// type `HASH` is used. Optionally specify a key-equality functor
1042 /// `keyEqual` used to determine whether two keys have the same value.
1043 /// If `keyEqual` is not supplied, a default-constructed object of the
1044 /// (template parameter) type `EQUAL` is used. Optionally specify a
1045 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1046 /// supplied, a default-constructed object of the (template parameter)
1047 /// type `ALLOCATOR` is used. If the type `ALLOCATOR` is
1048 /// `bsl::allocator` (the default), then `basicAllocator`, if supplied,
1049 /// shall be convertible to `bslma::Allocator *`. If the type
1050 /// `ALLOCATOR` is `bsl::allocator` and `basicAllocator` is not
1051 /// supplied, the currently installed default allocator is used. This
1052 /// operation has `O[N]` complexity, where `N` is the number of elements in `range`.
1053 ///
1054 /// \note Note that `RANGE` must meet the requirements of an
1055 /// input range and the values from `range` must have a type matching or
1056 /// convertible to `value_type`.
1057 template <class RANGE>
1059 value_type)
1061 bsl::from_range_t ,
1062 BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range,
1063 size_type initialNumBuckets = 0,
1064 const HASH& hashFunction = HASH(),
1065 const EQUAL& keyEqual = EQUAL(),
1066 const ALLOCATOR& basicAllocator = ALLOCATOR())
1067 : d_impl(hashFunction,
1068 keyEqual,
1069 initialNumBuckets,
1070 1.0f,
1071 basicAllocator)
1072 {
1073 // Defined inline to avoid `clang` and Windows errors.
1074#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1075 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1076 if constexpr (ranges::sized_range<RANGE>) {
1077 constructFromRange(bsl::ranges::begin(range),
1078 bsl::ranges::end (range),
1079 bsl::ranges::size (range));
1080 } else // ...
1081#endif
1082 {
1083 constructFromRange(bsl::ranges::begin(range),
1084 bsl::ranges::end (range));
1085 }
1086 }
1087
1088 template <class RANGE>
1090 value_type)
1093 size_type initialNumBuckets,
1094 const HASH& hashFunction,
1095 const ALLOCATOR& basicAllocator)
1096 : d_impl(hashFunction, EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
1097 {
1098 // Defined inline to avoid `clang` error.
1099
1101 range,
1102 initialNumBuckets,
1103 hashFunction,
1104 EQUAL(),
1105 basicAllocator);
1106 this->swap(other);
1107 }
1108
1109 template <class RANGE>
1111 value_type)
1114 size_type initialNumBuckets,
1115 const ALLOCATOR& basicAllocator)
1116 : d_impl(HASH(), EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
1117 {
1118 // Defined inline to avoid `clang` error.
1119
1121 range,
1122 initialNumBuckets,
1123 HASH(),
1124 EQUAL(),
1125 basicAllocator);
1126 this->swap(other);
1127 }
1128
1129 template <class RANGE>
1131 value_type)
1134 const ALLOCATOR& basicAllocator)
1135 : d_impl(HASH(), EQUAL(), 0, 1.0f, basicAllocator)
1136 {
1137 // Defined inline to avoid `clang` error.
1138
1140 range,
1141 0,
1142 HASH(),
1143 EQUAL(),
1144 basicAllocator);
1145 this->swap(other);
1146 }
1147
1148 /// Destroy this object.
1150
1151 // MANIPULATORS
1152
1153 /// Assign to this object the value, hash function, and key-equivalence
1154 /// comparator of the specified `rhs` object, propagate to this object
1155 /// the allocator of `rhs` if the `ALLOCATOR` type has trait
1156 /// @ref propagate_on_container_copy_assignment , and return a reference
1157 /// providing modifiable access to this object. If an exception is
1158 /// thrown, `*this` is left in a valid but unspecified state. This
1159 /// method requires that the (template parameter) types `KEY` and
1160 /// `VALUE` both be `copy-assignable` and `copy-insertable` into this
1161 /// unordered multimap (see {Requirements on `KEY` and `VALUE`}).
1163
1164 /// Assign to this object the value, hash function, and key-equivalence
1165 /// comparator of the specified `rhs` object, propagate to this object
1166 /// the allocator of `rhs` if the `ALLOCATOR` type has trait
1167 /// @ref propagate_on_container_move_assignment , and return a reference
1168 /// providing modifiable access to this object. The contents of `rhs`
1169 /// are moved (in constant time) to this unordered multimap if
1170 /// `get_allocator() == rhs.get_allocator()` (after accounting for the
1171 /// aforementioned trait); otherwise, all elements in this unordered
1172 /// multimap are either destroyed or move-assigned to, and each
1173 /// additional element in `rhs` is move-inserted into this unordered
1174 /// multimap. `rhs` is left in a valid but unspecified state, and if an
1175 /// exception is thrown, `*this` is left in a valid but unspecified
1176 /// state. This method requires that the (template parameter) types
1177 /// `KEY` and `VALUE` both be `move-assignable` and `move-insertable`
1178 /// into this unordered multimap (see {Requirements on `KEY` and
1179 /// `VALUE`}).
1181 operator=(BloombergLP::bslmf::MovableRef<unordered_multimap> rhs)
1183 AllocatorTraits::is_always_equal::value &&
1184 std::is_nothrow_move_assignable<HASH>::value &&
1185 std::is_nothrow_move_assignable<EQUAL>::value);
1186
1187#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1188 /// Assign to this object the value resulting from first clearing this
1189 /// unordered multimap and then inserting each `value_type` object in
1190 /// the specified `values` initializer list, and return a reference
1191 /// providing modifiable access to this object. This method requires
1192 /// that the (template parameter) types `KEY` and `VALUE` both be
1193 /// `copy-insertable` into this unordered multimap (see {Requirements on
1194 /// `KEY` and `VALUE`}).
1195 unordered_multimap& operator=(std::initializer_list<value_type> values);
1196#endif
1197
1198 /// Return an iterator providing modifiable access to the first
1199 /// `value_type` object (in the sequence of `value_type` objects)
1200 /// maintained by this unordered multimap, or the `end` iterator if this
1201 /// unordered multimap is empty.
1203
1204 /// Return an iterator providing modifiable access to the past-the-end
1205 /// position in the sequence of `value_type` objects maintained by this
1206 /// unordered multimap.
1208
1209 /// Return a local iterator providing modifiable access to the first
1210 /// `value_type` object in the sequence of `value_type` objects of the
1211 /// bucket having the specified `index` in the array of buckets
1212 /// maintained by this unordered multimap, or the `end(index)` iterator if the indexed bucket is empty.
1213 ///
1214 /// \pre The behavior is undefined unless
1215 /// `index < bucket_count()`.
1217
1218 /// Return a local iterator providing modifiable access to the
1219 /// past-the-end position in the sequence of `value_type` objects of the
1220 /// bucket having the specified `index` in the array of buckets
1221 /// maintained by this unordered multimap.
1222 ///
1223 /// \pre The behavior is undefined unless `index < bucket_count()`.
1225
1226 /// Remove all entries from this unordered multimap.
1227 /// \note Note that this
1228 /// object will be empty after this call, but allocated memory may be
1229 /// retained for future use.
1231
1232 /// Return a pair of iterators providing modifiable access to the
1233 /// sequence of `value_type` objects in this unordered multimap with a
1234 /// key equivalent to the specified `key`, where the first iterator is
1235 /// positioned at the start of the sequence, and the second is
1236 /// positioned one past the end of the sequence. If this unordered
1237 /// multimap contains no `value_type` objects with a key equivalent to
1238 /// `key`, then the two returned iterators will have the same value.
1239 ///
1240 /// \pre The behavior is undefined unless `key` is equivalent to the key of
1241 /// the elements of at most one equivalent-key group in this unordered
1242 /// multimap.
1243 template <class LOOKUP_KEY>
1244 typename enable_if<
1245 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1246 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1247 pair<iterator, iterator> >::type
1248 equal_range(const LOOKUP_KEY& key)
1249 {
1250 // Note: implemented inline due to Sun CC compilation error.
1251 typedef bsl::pair<iterator, iterator> ResultType;
1252 HashTableLink *first;
1253 HashTableLink *last;
1254 d_impl.findRange(&first, &last, key);
1255 return ResultType(iterator(first), iterator(last));
1256 }
1257
1258 /// Return a pair of iterators providing modifiable access to the
1259 /// sequence of `value_type` objects in this unordered multimap with a
1260 /// key equivalent to the specified `key`, where the first iterator is
1261 /// positioned at the start of the sequence, and the second is
1262 /// positioned one past the end of the sequence. If this unordered
1263 /// multimap contains no `value_type` objects with a key equivalent to
1264 /// `key`, then the two returned iterators will have the same value.
1265 pair<iterator, iterator> equal_range(const key_type& key);
1266
1267 /// Remove from this unordered multimap all `value_type` objects with a
1268 /// key equivalent to the specified `key`, if such exist, and return the
1269 /// number of objects erased; otherwise, if there are no `value_type`
1270 /// objects with a key equivalent to `key`, return 0 with no other
1271 /// effect. This method invalidates only iterators and references to
1272 /// the removed element and previously saved values of the `end()`
1273 /// iterator, and preserves the relative order of the elements not
1274 /// removed.
1275 size_type erase(const key_type& key);
1276 template <class t_KEY>
1277 typename enable_if<
1278 BloombergLP::bslmf::IsTransparentPredicate<HASH, t_KEY>::value &&
1279 BloombergLP::bslmf::IsTransparentPredicate<EQUAL,t_KEY>::value &&
1281 iterator>::value &&
1283 const_iterator>::value,
1285 {
1286 // Implemented inline due to Sun CC compilation error.
1287 size_type count = 0;
1288 // Our implementation always finds the first element
1289 iterator it = this->find(key);
1290 if (it != end()) {
1291 do {
1292 it = erase(it);
1293 count++;
1294 } while (it != end() && key_eq()(it->first, key));
1295 }
1296 return count;
1297 }
1298
1299 /// Remove from this unordered multimap the `value_type` object at the
1300 /// specified `position`, and return an iterator referring to the
1301 /// element immediately following the removed element, or to the
1302 /// past-the-end position if the removed element was the last element in
1303 /// the sequence of elements maintained by this unordered multimap.
1304 /// This method invalidates only iterators and references to the removed
1305 /// element and previously saved values of the `end()` iterator, and
1306 /// preserves the relative order of the elements not removed.
1307 ///
1308 /// \pre The behavior is undefined unless `position` refers to a `value_type`
1309 /// object in this unordered multimap.
1310 iterator erase(const_iterator position);
1311 iterator erase(iterator position);
1312
1313 /// Remove from this unordered multimap the `value_type` objects
1314 /// starting at the specified `first` position up to, but not including,
1315 /// the specified `last` position, and return `last`. This method
1316 /// invalidates only iterators and references to the removed element and
1317 /// previously saved values of the `end()` iterator, and preserves the
1318 /// relative order of the elements not removed.
1319 ///
1320 /// \pre The behavior is undefined unless `first` and `last` either refer to elements in this
1321 /// unordered multimap or are the `end` iterator, and the `first`
1322 /// position is at or before the `last` position in the sequence
1323 /// provided by this container.
1325
1326 /// Return an iterator providing modifiable access to the first
1327 /// `value_type` object in the sequence of all the `value_type` objects
1328 /// of this unordered multimap with a key equivalent to the specified
1329 /// `key`, if such entries exist, and the past-the-end (`end`) iterator otherwise.
1330 ///
1331 /// \pre The behavior is undefined unless `key` is equivalent to
1332 /// the key of the elements of at most one equivalent-key group in this
1333 /// unordered multimap.
1334 template <class LOOKUP_KEY>
1335 typename enable_if<
1336 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1337 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1338 iterator>::type
1339 find(const LOOKUP_KEY& key)
1340 {
1341 // Note: implemented inline due to Sun CC compilation error.
1342 return iterator(d_impl.find(key));
1343 }
1344
1345 /// Return an iterator providing modifiable access to the first
1346 /// `value_type` object in the sequence of all the `value_type` objects
1347 /// of this unordered multimap with a key equivalent to the specified
1348 /// `key`, if such entries exist, and the past-the-end (`end`) iterator
1349 /// otherwise.
1350 iterator find(const key_type& key);
1351
1352 /// Insert the specified `value` into this unordered multimap, and
1353 /// return an iterator referring to the newly inserted `value_type`
1354 /// object. This method requires that the (template parameter) types
1355 /// `KEY` and `VALUE` both be `copy-insertable` into this unordered
1356 /// multimap (see {Requirements on `KEY` and `VALUE`}).
1357 iterator insert(const value_type& value);
1358
1359#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1360 template <class ALT_VALUE_TYPE>
1361 iterator
1362#elif !defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER)
1363 template <class ALT_VALUE_TYPE>
1365 iterator>::type
1366#else
1367 /// Insert into this unordered multimap a `value_type` object created
1368 /// from the specified `value`, and return an iterator referring to the
1369 /// newly inserted `value_type` object. This method requires that the
1370 /// (template parameter) types `KEY` and `VALUE` both be
1371 /// `move-insertable` into this unordered multimap (see {Requirements on
1372 /// `KEY` and `VALUE`}), and the `value_type` be constructible from the
1373 /// (template parameter) `ALT_VALUE_TYPE`.
1374 template <class ALT_VALUE_TYPE>
1375 typename enable_if<std::is_constructible<value_type,
1376 ALT_VALUE_TYPE&&>::value,
1377 iterator>::type
1378#endif
1380 {
1381 // Note that some compilers fail when this method is defined
1382 // out-of-line.
1383
1384 return emplace(BSLS_COMPILERFEATURES_FORWARD(ALT_VALUE_TYPE, value));
1385 }
1386
1387 /// Insert the specified `value` into this unordered multimap (in
1388 /// constant time if the specified `hint` refers to an element in this
1389 /// container with a key equivalent to the key of `value`), and return
1390 /// an iterator referring to the newly inserted `value_type` object. If
1391 /// `hint` does not refer to an element in this container with a key
1392 /// equivalent to the key of `value`, this operation has worst case
1393 /// `O[N]` and average case constant-time complexity, where `N` is the
1394 /// size of this unordered multimap. This method requires that the
1395 /// (template parameter) types `KEY` and `VALUE` both be
1396 /// `copy-insertable` into this unordered multimap (see {Requirements on `KEY` and `VALUE`}).
1397 ///
1398 /// \pre The behavior is undefined unless `hint` is an
1399 /// iterator in the range `[begin() .. end()]` (both endpoints
1400 /// included).
1401 iterator insert(const_iterator hint, const value_type& value);
1402
1403#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1404 template <class ALT_VALUE_TYPE>
1405 iterator
1406#elif !defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER)
1407 template <class ALT_VALUE_TYPE>
1409 iterator>::type
1410#else
1411 /// Insert into this unordered multimap a `value_type` object created
1412 /// from the specified `value` (in constant time if the specified `hint`
1413 /// refers to an element in this container with a key equivalent to the
1414 /// key of `value`), and return an iterator referring to the newly
1415 /// inserted `value_type` object. If `hint` does not refer to an
1416 /// element in this container with a key equivalent to the key of
1417 /// `value`, this operation has worst case `O[N]` and average case
1418 /// constant-time complexity, where `N` is the size of this unordered
1419 /// multimap. This method requires that the (template parameter) types
1420 /// `KEY` and `VALUE` both be `move-insertable` into this unordered
1421 /// multimap (see {Requirements on `KEY` and `VALUE`}), and the
1422 /// `value_type` be constructible from the (template parameter) `ALT_VALUE_TYPE`.
1423 ///
1424 /// \pre The behavior is undefined unless `hint` is an
1425 /// iterator in the range `[begin() .. end()]` (both endpoints
1426 /// included).
1427 template <class ALT_VALUE_TYPE>
1428 typename enable_if<std::is_constructible<value_type,
1429 ALT_VALUE_TYPE&&>::value,
1430 iterator>::type
1431#endif
1433 BSLS_COMPILERFEATURES_FORWARD_REF(ALT_VALUE_TYPE) value)
1434 {
1435 // Note that some compilers fail when this method is defined
1436 // out-of-line.
1437
1438 return emplace_hint(hint,
1439 BSLS_COMPILERFEATURES_FORWARD(ALT_VALUE_TYPE, value));
1440 }
1441
1442 /// Insert into this unordered multimap the value of each `value_type`
1443 /// object in the range starting at the specified `first` iterator and
1444 /// ending immediately before the specified `last` iterator. The
1445 /// (template parameter) type `INPUT_ITERATOR` shall meet the
1446 /// requirements of an input iterator defined in the C++11 standard
1447 /// [24.2.3] providing access to values of a type convertible to
1448 /// `value_type`, and `value_type` must be `emplace-constructible` from
1449 /// `*i` into this unordered multimap, where `i` is a dereferenceable
1450 /// iterator in the range `[first .. last)` (see {Requirements on `KEY` and `VALUE`}).
1451 ///
1452 /// \pre The behavior is undefined unless `first` and `last`
1453 /// refer to a sequence of valid values where `first` is at a position
1454 /// at or before `last`.
1455 template <class INPUT_ITERATOR>
1456 void insert(INPUT_ITERATOR first, INPUT_ITERATOR last);
1457
1458 /// Insert into this unordered multimap the value of each `value_type` object in the specified `range`.
1459 ///
1460 /// \note Note that `RANGE` must meet the
1461 /// requirements of an input range and the values from `range` must have
1462 /// a type matching or convertible to `value_type`.
1463 template <class RANGE>
1465 value_type)
1466 void insert_range(BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
1467 {
1468 // Defined inline to avoid `clang` and Windows errors.
1469#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1470 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1471 if constexpr (ranges::sized_range<RANGE>) {
1472 insertFromRange(bsl::ranges::begin(range),
1473 bsl::ranges::end (range),
1474 bsl::ranges::size (range));
1475 } else // ...
1476#endif
1477 {
1478 insertFromRange(bsl::ranges::begin(range),
1479 bsl::ranges::end (range));
1480 }
1481 }
1482
1483#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1484 /// Insert into this unordered multimap the value of each `value_type`
1485 /// object in the specified `values` initializer list. This method
1486 /// requires that the (template parameter) types `KEY` and `VALUE` both
1487 /// be `copy-insertable` into this unordered multimap (see {Requirements
1488 /// on `KEY` and `VALUE`}).
1489 void insert(std::initializer_list<value_type> values);
1490#endif
1491
1492#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=2
1493
1494 /// Insert into this unordered multimap a newly created `value_type`
1495 /// object, constructed by forwarding `get_allocator()` (if required)
1496 /// and the specified (variable number of) `args` to the corresponding
1497 /// constructor of `value_type`. Return an iterator referring to the
1498 /// newly created and inserted object in this unordered multimap. This
1499 /// method requires that the (template parameter) types `KEY` and
1500 /// `VALUE` both be `emplace-constructible` from `args` (see
1501 /// {Requirements on `KEY` and `VALUE`}).
1502 template <class... Args>
1503 iterator emplace(Args&&... args);
1504
1505 /// Insert into this unordered multimap a newly created `value_type`
1506 /// object, constructed by forwarding `get_allocator()` (if required)
1507 /// and the specified (variable number of) `args` to the corresponding
1508 /// constructor of `value_type` (in constant time if the specified
1509 /// `hint` refers to an element in this container with a key equivalent
1510 /// to the key of the newly created `value_type` object), and return an
1511 /// iterator referring to the newly created and inserted object. If
1512 /// `hint` does not refer to an element in this container with a key
1513 /// equivalent to the key of the newly created `value_type` object, this
1514 /// operation has worst case `O[N]` and average case constant-time
1515 /// complexity, where `N` is the size of this unordered multimap. This
1516 /// method requires that the (template parameter) types `KEY` and
1517 /// `VALUE` both be `emplace-constructible` from `args` (see
1518 /// {Requirements on `KEY` and `VALUE`}).
1519 ///
1520 /// \pre The behavior is undefined unless `hint` is an iterator in the range `[begin() .. end()]` (both
1521 /// endpoints included).
1522 template <class... Args>
1523 iterator emplace_hint(const_iterator hint, Args&&... args);
1524
1525#endif
1526
1527 /// Set the maximum load factor of this container to the specified
1528 /// `newLoadFactor`.
1529 void max_load_factor(float newLoadFactor);
1530
1531 /// Change the size of the array of buckets maintained by this container
1532 /// to the specified `numBuckets`, and redistribute all the contained
1533 /// elements into the new sequence of buckets, according to their hash values.
1534 ///
1535 /// \note Note that this operation has no effect if rehashing the
1536 /// elements into `numBuckets` would cause this unordered multimap to
1537 /// exceed its @ref max_load_factor .
1538 void rehash(size_type numBuckets);
1539
1540 /// Increase the number of buckets of this unordered multimap to a
1541 /// quantity such that the ratio between the specified `numElements` and
1542 /// the new number of buckets does not exceed @ref max_load_factor .
1543 ///
1544 /// \note Note that this guarantees that, after the reserve, elements can be
1545 /// inserted to grow the container to `size() == numElements` without
1546 /// rehashing. Also note that memory allocations may still occur when
1547 /// growing the container to `size() == numElements`. Also note that
1548 /// this operation has no effect if `numElements <= size()`.
1549 void reserve(size_type numElements);
1550
1551 // Exchange the value, hasher, key-equality functor, and
1552 // @ref max_load_factor of this object with those of the specified `other`
1553 // object; also exchange the allocator of this object with that of
1554 // `other` if the (template parameter) type `ALLOCATOR` has the
1555 // @ref propagate_on_container_swap trait, and do not modify either
1556 // allocator otherwise. This method provides the no-throw
1557 // exception-safety guarantee if and only if both the (template
1558 // parameter) types `HASH` and `EQUAL` provide no-throw swap
1559 // operations; if an exception is thrown, both objects are left in
1560 // valid but unspecified states. This operation guarantees `O[1]`
1561 // complexity. The behavior is undefined unless either this object was
1562 // created with the same allocator as `other` or `ALLOCATOR` has the
1563 // @ref propagate_on_container_swap trait.
1565 AllocatorTraits::is_always_equal::value &&
1566 bsl::is_nothrow_swappable<HASH>::value &&
1567 bsl::is_nothrow_swappable<EQUAL>::value);
1568
1569 // ACCESSORS
1570
1571 /// Return (a copy of) the allocator used for memory allocation by this
1572 /// unordered multimap.
1574
1576
1577 /// Return an iterator providing non-modifiable access to the first
1578 /// `value_type` object in the sequence of `value_type` objects
1579 /// maintained by this unordered multimap, or the `end` iterator if this
1580 /// unordered multimap is empty.
1582
1584
1585 /// Return an iterator providing non-modifiable access to the
1586 /// past-the-end position in the sequence of `value_type` objects
1587 /// maintained by this unordered multimap.
1589
1590 /// Return `true` if this unordered map contains an element whose key is
1591 /// equivalent to the specified `key`.
1592 bool contains(const key_type &key) const;
1593
1594 /// Return `true` if this unordered map contains an element whose key is
1595 /// equivalent to the specified `key`.
1596 template <class LOOKUP_KEY>
1597 typename enable_if<
1598 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value &&
1599 BloombergLP::bslmf::IsTransparentPredicate<EQUAL,
1600 LOOKUP_KEY>::value,
1601 bool>::type
1602 contains(const LOOKUP_KEY& key) const
1603 {
1604 // Note: implemented inline due to Sun CC compilation error
1605 return find(key) != end();
1606 }
1607
1608 /// Return `true` if this unordered multimap contains no elements, and
1609 /// `false` otherwise.
1610 bool empty() const BSLS_KEYWORD_NOEXCEPT;
1611
1612 /// Return the number of elements in this unordered multimap.
1614
1615 /// Return a theoretical upper bound on the largest number of elements that this unordered multimap could possibly hold.
1616 ///
1617 /// \note Note that there
1618 /// is no guarantee that the unordered multimap can successfully grow to
1619 /// the returned size, or even close to that size without running out of
1620 /// resources.
1622
1623 /// Return (a copy of) the key-equivalence binary functor that returns
1624 /// `true` if the value of two `key_type` objects are equivalent, and
1625 /// `false` otherwise.
1626 EQUAL key_eq() const;
1627
1628 /// Return (a copy of) the hash unary functor used by this unordered
1629 /// multimap to generate a hash value (of type `size_type`) for a
1630 /// `key_type` object.
1631 HASH hash_function() const;
1632
1633 /// Return an iterator providing modifiable access to the first
1634 /// `value_type` object in this unordered multimap whose key is
1635 /// equivalent to the specified `key`, if such an entry exists, and the
1636 /// past-the-end (`end`) iterator otherwise.
1637 ///
1638 /// \pre The behavior is undefined unless `key` is equivalent to the key of the elements of at most one
1639 /// equivalent-key group in this unordered multimap.
1640 template <class LOOKUP_KEY>
1641 typename enable_if<
1642 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1643 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1644 const_iterator>::type
1645 find(const LOOKUP_KEY& key) const
1646 {
1647 // Note: implemented inline due to Sun CC compilation error.
1648 return const_iterator(d_impl.find(key));
1649 }
1650
1651 /// Return an iterator providing non-modifiable access to the first
1652 /// `value_type` object in the sequence of `value_type` objects of this
1653 /// unordered multimap with a key equivalent to the specified `key`, if
1654 /// such entries exist, and the past-the-end (`end`) iterator otherwise.
1655 const_iterator find(const key_type& key) const;
1656
1657 /// Return the number of `value_type` objects in this unordered multimap
1658 /// with a key equivalent to the specified `key`.
1659 ///
1660 /// \pre The behavior is undefined unless `key` is equivalent to the key of the elements of
1661 /// at most one equivalent-key group in this unordered multimap.
1662 template <class LOOKUP_KEY>
1663 typename enable_if<
1664 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1665 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1666 size_type>::type
1667 count(const LOOKUP_KEY& key) const
1668 {
1669 // Note: implemented inline due to Sun CC compilation error.
1670 typedef ::BloombergLP::bslalg::BidirectionalNode<value_type> BNode;
1671
1672 size_type result = 0;
1673 for (HashTableLink *cursor = d_impl.find(key);
1674 cursor;
1675 ++result, cursor = cursor->nextLink())
1676 {
1677 BNode *cursorNode = static_cast<BNode *>(cursor);
1678 if (!this->key_eq()(
1679 key,
1680 ListConfiguration::extractKey(cursorNode->value()))) {
1681
1682 break;
1683 }
1684 }
1685 return result;
1686 }
1687
1688 /// Return the number of `value_type` objects in this unordered multimap
1689 /// with a key equivalent to the specified `key`.
1690 size_type count(const key_type& key) const;
1691
1692 /// Return a pair of iterators providing non-modifiable access to the
1693 /// sequence of `value_type` objects in this unordered multimap with a
1694 /// key equivalent to the specified `key`, where the first iterator is
1695 /// positioned at the start of the sequence, and the second is
1696 /// positioned one past the end of the sequence. If this unordered
1697 /// multimap contains no `value_type` objects with a key equivalent to
1698 /// `key`, then the two returned iterators will have the same value.
1699 ///
1700 /// \pre The behavior is undefined unless `key` is equivalent to the key of
1701 /// the elements of at most one equivalent-key group in this unordered
1702 /// multimap.
1703 template <class LOOKUP_KEY>
1704 typename enable_if<
1705 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1706 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1708 equal_range(const LOOKUP_KEY& key) const
1709 {
1710 // Note: implemented inline due to Sun CC compilation error.
1712 HashTableLink *first;
1713 HashTableLink *last;
1714 d_impl.findRange(&first, &last, key);
1715 return ResultType(const_iterator(first), const_iterator(last));
1716 }
1717
1718 /// Return a pair of iterators providing non-modifiable access to the
1719 /// sequence of `value_type` objects in this unordered multimap with a
1720 /// key equivalent to the specified `key`, where the first iterator is
1721 /// positioned at the start of the sequence, and the second is
1722 /// positioned one past the end of the sequence. If this unordered
1723 /// multimap contains no `value_type` objects with a key equivalent to
1724 /// `key`, then the two returned iterators will have the same value.
1726 const key_type& key) const;
1727
1729
1730 /// Return a local iterator providing non-modifiable access to the first
1731 /// `value_type` object (in the sequence of `value_type` objects) of the
1732 /// bucket having the specified `index` in the array of buckets
1733 /// maintained by this unordered multimap, or the `end(index)` iterator if the indexed bucket is empty.
1734 ///
1735 /// \pre The behavior is undefined unless
1736 /// `index < bucket_count()`.
1738
1739 const_local_iterator end(size_type index) const;
1740
1741 /// Return a local iterator providing non-modifiable access to the
1742 /// past-the-end position (in the sequence of `value_type` objects) of
1743 /// the bucket having the specified `index` in the array of buckets
1744 /// maintained by this unordered multimap.
1745 ///
1746 /// \pre The behavior is undefined unless `index < bucket_count()`.
1747 const_local_iterator cend(size_type index) const;
1748
1749 /// Return the index of the bucket, in the array of buckets of this
1750 /// container, where a value with a key equivalent to the specified
1751 /// `key` would be inserted.
1752 size_type bucket(const key_type& key) const;
1753
1754 /// Return the index of the bucket, in the array of buckets maintained
1755 /// by this unordered map, where values having a key equivalent to the
1756 /// specified `key` would be inserted.
1757 ///
1758 /// Note: implemented inline due to Sun CC compilation error.
1759 template <class LOOKUP_KEY>
1760 typename enable_if<
1761 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1762 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value,
1763 size_type>::type
1764 bucket(const LOOKUP_KEY& key) const
1765 {
1766 return d_impl.bucketIndexForKey(key);
1767 }
1768
1769 /// Return the number of buckets in the array of buckets maintained by
1770 /// this unordered multimap.
1772
1773 /// Return a theoretical upper bound on the largest number of buckets that this container could possibly manage.
1774 ///
1775 /// \note Note that there is no
1776 /// guarantee that the unordered multimap can successfully grow to the
1777 /// returned size, or even close to that size without running out of
1778 /// resources.
1780
1781 /// Return the number of elements contained in the bucket at the
1782 /// specified `index` in the array of buckets maintained by this container.
1783 ///
1784 /// \pre The behavior is undefined unless
1785 /// `index < bucket_count()`.
1786 size_type bucket_size(size_type index) const;
1787
1788 /// Return the current ratio between the `size` of this container and
1789 /// the number of buckets. The load factor is a measure of how full the
1790 /// container is, and a higher load factor typically leads to an
1791 /// increased number of collisions, thus resulting in a loss of
1792 /// performance.
1793 float load_factor() const BSLS_KEYWORD_NOEXCEPT;
1794
1795 /// Return the maximum load factor allowed for this container.
1796 ///
1797 /// \note Note that if an insert operation would cause the load factor to exceed
1798 /// the @ref max_load_factor , that same insert operation will increase the
1799 /// number of buckets and rehash the elements of the container into
1800 /// those buckets (see `rehash`).
1802
1803 private:
1804 // PRIVATE MANIPULATORS
1805
1806 /// Create an empty unordered multimap, and insert each `value_type`
1807 /// object in the range starting at the specified `first` iterator and
1808 /// ending immediately before the specified `last` sentinel. Optionally
1809 /// specify the initial `numElements` size of the unordered multimap.
1810 /// Note: this method is intended for internal use only.
1811 template <class INPUT_ITERATOR, class SENTINEL>
1812 void constructFromRange(INPUT_ITERATOR first, SENTINEL last);
1813
1814#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1815 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1816 template <class INPUT_ITERATOR, class SENTINEL>
1817 void constructFromRange(INPUT_ITERATOR first,
1818 SENTINEL last,
1819 size_t numElements);
1820#endif
1821
1822 /// Insert into this unordered multimap the value of each `value_type`
1823 /// object in the range starting at the specified `first` iterator and
1824 /// ending immediately before the specified `last` sentinel. Optionally
1825 /// specify the initial `numElements` size of the range. Note: this
1826 /// method is intended for internal use only.
1827 template <class INPUT_ITERATOR, class SENTINEL>
1828 void insertFromRange(INPUT_ITERATOR first, SENTINEL last);
1829
1830#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1831 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1832 template <class INPUT_ITERATOR, class SENTINEL>
1833 void insertFromRange(INPUT_ITERATOR first,
1834 SENTINEL last,
1835 size_t numElements);
1836#endif
1837};
1838
1839#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1840// CLASS TEMPLATE DEDUCTION GUIDES
1841
1842/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
1843/// of the iterators supplied to the constructor of @ref unordered_multimap .
1844/// Deduce the template parameters `HASH`, `EQUAL` and `ALLOCATOR` from the
1845/// other parameters passed to the constructor of @ref unordered_multimap .
1846/// This deduction guide does not participate unless the supplied allocator
1847/// meets the requirements of a standard allocator.
1848template <
1849 class INPUT_ITERATOR,
1850 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
1851 class VALUE =
1852 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
1853 class HASH = bsl::hash<KEY>,
1854 class EQUAL = bsl::equal_to<KEY>,
1855 class ALLOCATOR = bsl::allocator<pair<const KEY, VALUE>>,
1856 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
1857 class = bsl::enable_if_t<
1858 std::is_invocable_v<EQUAL, const KEY &, const KEY &>>,
1859 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1860 >
1861unordered_multimap(INPUT_ITERATOR,
1862 INPUT_ITERATOR,
1863 typename bsl::allocator_traits<ALLOCATOR>::size_type = 0,
1864 HASH = HASH(),
1865 EQUAL = EQUAL(),
1866 ALLOCATOR = ALLOCATOR())
1867-> unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>;
1868
1869/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
1870/// of the iterators supplied to the constructor of @ref unordered_multimap .
1871/// Deduce the template parameters `HASH` and "EQUAL' from the other
1872/// parameters passed to the constructor of @ref unordered_multimap . This
1873/// deduction guide does not participate unless the supplied allocator is
1874/// convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
1875template <
1876 class INPUT_ITERATOR,
1877 class HASH,
1878 class EQUAL,
1879 class ALLOC,
1880 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
1881 class VALUE =
1882 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
1883 class DEFAULT_ALLOCATOR = bsl::allocator<pair<const KEY, VALUE>>,
1884 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1885 >
1886unordered_multimap(
1887 INPUT_ITERATOR,
1888 INPUT_ITERATOR,
1889 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
1890 HASH,
1891 EQUAL,
1892 ALLOC *)
1893-> unordered_multimap<KEY, VALUE, HASH, EQUAL>;
1894
1895/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
1896/// of the iterators supplied to the constructor of @ref unordered_multimap .
1897/// Deduce the template parameters `HASH` and `ALLOCATOR` from the other
1898/// parameters passed to the constructor of @ref unordered_multimap . This
1899/// deduction guide does not participate unless the supplied hash is
1900/// invokable with a `KEY`, and the supplied allocator meets the
1901/// requirements of a standard allocator.
1902template <
1903 class INPUT_ITERATOR,
1904 class HASH,
1905 class ALLOCATOR,
1906 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
1907 class VALUE =
1908 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
1909 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
1910 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1911 >
1912unordered_multimap(INPUT_ITERATOR,
1913 INPUT_ITERATOR,
1914 typename bsl::allocator_traits<ALLOCATOR>::size_type,
1915 HASH,
1916 ALLOCATOR)
1917-> unordered_multimap<KEY, VALUE, HASH, bsl::equal_to<KEY>, ALLOCATOR>;
1918
1919/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
1920/// of the iterators supplied to the constructor of @ref unordered_multimap .
1921/// Deduce the template parameter `HASH` from the other parameters passed to
1922/// the constructor of @ref unordered_multimap . This deduction guide does not
1923/// participate unless the supplied allocator is convertible to
1924/// `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
1925template <
1926 class INPUT_ITERATOR,
1927 class HASH,
1928 class ALLOC,
1929 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
1930 class VALUE =
1931 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
1932 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
1933 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1934 >
1935unordered_multimap(
1936 INPUT_ITERATOR,
1937 INPUT_ITERATOR,
1938 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
1939 HASH,
1940 ALLOC *)
1941-> unordered_multimap<KEY, VALUE, HASH>;
1942
1943/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
1944/// of the iterators supplied to the constructor of @ref unordered_multimap .
1945/// This deduction guide does not participate unless the supplied allocator
1946/// meets the requirements of a standard allocator.
1947template <
1948 class INPUT_ITERATOR,
1949 class ALLOCATOR,
1950 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
1951 class VALUE =
1952 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
1953 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1954 >
1955unordered_multimap(INPUT_ITERATOR,
1956 INPUT_ITERATOR,
1957 typename bsl::allocator_traits<ALLOCATOR>::size_type,
1958 ALLOCATOR)
1959-> unordered_multimap<KEY,
1960 VALUE,
1961 bsl::hash<KEY>,
1962 bsl::equal_to<KEY>,
1963 ALLOCATOR>;
1964
1965/// of the iterators supplied to the constructor of @ref unordered_multimap .
1966/// Deduce the template parameter `ALLOCATOR` from the other parameter
1967/// passed to the constructor of @ref unordered_multimap . This deduction guide
1968/// does not participate unless the supplied allocator meets the
1969/// requirements of a standard allocator.
1970template <
1971 class INPUT_ITERATOR,
1972 class ALLOC,
1973 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
1974 class VALUE =
1975 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
1976 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
1977 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1978 >
1979unordered_multimap(
1980 INPUT_ITERATOR,
1981 INPUT_ITERATOR,
1982 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
1983 ALLOC *)
1984-> unordered_multimap<KEY, VALUE>;
1985
1986/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
1987/// of the iterators supplied to the constructor of @ref unordered_multimap .
1988/// Deduce the template parameter `ALLOCATOR` from the other parameter
1989/// passed to the constructor of @ref unordered_multimap . This deduction guide
1990/// does not participate unless the supplied allocator meets the
1991/// requirements of a standard allocator.
1992template <
1993 class INPUT_ITERATOR,
1994 class ALLOCATOR,
1995 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
1996 class VALUE =
1997 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
1998 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1999 >
2000unordered_multimap(INPUT_ITERATOR, INPUT_ITERATOR, ALLOCATOR)
2001-> unordered_multimap<KEY,
2002 VALUE,
2003 bsl::hash<KEY>,
2004 bsl::equal_to<KEY>,
2005 ALLOCATOR>;
2006
2007/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2008/// of the iterators supplied to the constructor of @ref unordered_multimap .
2009/// This deduction guide does not participate unless the supplied allocator
2010/// is convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2011template <
2012 class INPUT_ITERATOR,
2013 class ALLOC,
2014 class KEY = BloombergLP::bslstl::IteratorUtil::IterKey_t<INPUT_ITERATOR>,
2015 class VALUE =
2016 BloombergLP::bslstl::IteratorUtil::IterMapped_t<INPUT_ITERATOR>,
2017 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2018 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2019 >
2020unordered_multimap(INPUT_ITERATOR, INPUT_ITERATOR, ALLOC *)
2021-> unordered_multimap<KEY, VALUE>;
2022
2023/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2024/// of the initializer_list supplied to the constructor of
2025/// @ref unordered_multimap . Deduce the template parameters `HASH`, `EQUAL`
2026/// and `ALLOCATOR` from the other parameters supplied to the constructor of
2027/// @ref unordered_multimap . This deduction guide does not participate unless:
2028/// (1) the supplied `HASH` is invokable with a `KEY`, (2) the supplied
2029/// `EQUAL` is invokable with two `KEY`s, and (3) the supplied allocator
2030/// meets the requirements of a standard allocator.
2031template <
2032 class KEY,
2033 class VALUE,
2034 class HASH = bsl::hash<KEY>,
2035 class EQUAL = bsl::equal_to<KEY>,
2036 class ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2037 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
2038 class = bsl::enable_if_t<
2039 std::is_invocable_v<EQUAL, const KEY &, const KEY &>>,
2040 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2041 >
2042unordered_multimap(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2043 typename bsl::allocator_traits<ALLOCATOR>::size_type = 0,
2044 HASH = HASH(),
2045 EQUAL = EQUAL(),
2046 ALLOCATOR = ALLOCATOR())
2047-> unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>;
2048
2049/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2050/// of the initializer_list supplied to the constructor of
2051/// @ref unordered_multimap . Deduce the template parameters `HASH`, `EQUAL`
2052/// and `ALLOCATOR` from the other parameters supplied to the constructor of
2053/// @ref unordered_multimap . This deduction guide does not participate unless
2054/// the supplied allocator is convertible to
2055/// `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2056template <
2057 class KEY,
2058 class VALUE,
2059 class HASH,
2060 class EQUAL,
2061 class ALLOC,
2062 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2063 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2064 >
2065unordered_multimap(
2066 std::initializer_list<bsl::pair<const KEY, VALUE>>,
2067 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2068 HASH,
2069 EQUAL,
2070 ALLOC *)
2071-> unordered_multimap<KEY, VALUE, HASH, EQUAL>;
2072
2073/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2074/// of the initializer_list supplied to the constructor of
2075/// @ref unordered_multimap . Deduce the template parameters `HASH` and
2076/// `ALLOCATOR` from the other parameters supplied to the constructor of
2077/// @ref unordered_multimap . This deduction guide does not participate unless
2078/// the supplied `HASH` is invokable with a `KEY`, and the supplied
2079/// allocator meets the requirements of a standard allocator.
2080template <
2081 class KEY,
2082 class VALUE,
2083 class HASH,
2084 class ALLOCATOR,
2085 class = bsl::enable_if_t<std::is_invocable_v<HASH, const KEY &>>,
2086 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2087 >
2088unordered_multimap(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2089 typename bsl::allocator_traits<ALLOCATOR>::size_type,
2090 HASH,
2091 ALLOCATOR)
2092-> unordered_multimap<KEY, VALUE, HASH, bsl::equal_to<KEY>, ALLOCATOR>;
2093
2094/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2095/// of the initializer_list supplied to the constructor of
2096/// @ref unordered_multimap . Deduce the template parameter `HASH` from the
2097/// other parameters supplied to the constructor of @ref unordered_multimap .
2098/// This deduction guide does not participate unless the supplied allocator
2099/// is convertible to `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2100template <
2101 class KEY,
2102 class VALUE,
2103 class HASH,
2104 class ALLOC,
2105 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2106 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2107 >
2108unordered_multimap(
2109 std::initializer_list<bsl::pair<const KEY, VALUE>>,
2110 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2111 HASH,
2112 ALLOC *)
2113-> unordered_multimap<KEY, VALUE, HASH>;
2114
2115/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2116/// of the initializer_list supplied to the constructor of
2117/// @ref unordered_multimap . This deduction guide does not participate unless
2118/// the supplied allocator meets the requirements of a standard allocator.
2119template <
2120 class KEY,
2121 class VALUE,
2122 class ALLOCATOR,
2123 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2124 >
2125unordered_multimap(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2126 typename bsl::allocator_traits<ALLOCATOR>::size_type,
2127 ALLOCATOR)
2128-> unordered_multimap<KEY,
2129 VALUE,
2130 bsl::hash<KEY>,
2131 bsl::equal_to<KEY>,
2132 ALLOCATOR>;
2133
2134/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2135/// of the initializer_list supplied to the constructor of
2136/// @ref unordered_multimap . This deduction guide does not participate unless
2137/// the supplied allocator is convertible to
2138/// `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2139template <
2140 class KEY,
2141 class VALUE,
2142 class ALLOC,
2143 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2144 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2145 >
2146unordered_multimap(
2147 std::initializer_list<bsl::pair<const KEY, VALUE>>,
2148 typename bsl::allocator_traits<DEFAULT_ALLOCATOR>::size_type,
2149 ALLOC *)
2150-> unordered_multimap<KEY, VALUE>;
2151
2152/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2153/// of the initializer_list supplied to the constructor of
2154/// @ref unordered_multimap . Deduce the template parameter `ALLOCATOR` from
2155/// the other parameters supplied to the constructor of
2156/// @ref unordered_multimap . This deduction guide does not participate unless
2157/// the supplied allocator meets the requirements of a standard allocator.
2158template <
2159 class KEY,
2160 class VALUE,
2161 class ALLOCATOR,
2162 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
2163 >
2164unordered_multimap(std::initializer_list<bsl::pair<const KEY, VALUE>>,
2165 ALLOCATOR)
2166-> unordered_multimap<KEY,
2167 VALUE,
2168 bsl::hash<KEY>,
2169 bsl::equal_to<KEY>,
2170 ALLOCATOR>;
2171
2172/// Deduce the template parameters `KEY` and `VALUE` from the `value_type`
2173/// of the initializer_list supplied to the constructor of
2174/// @ref unordered_multimap . This deduction guide does not participate unless
2175/// the supplied allocator is convertible to
2176/// `bsl::allocator<bsl::pair<const KEY, VALUE>>`.
2177template <
2178 class KEY,
2179 class VALUE,
2180 class ALLOC,
2181 class DEFAULT_ALLOCATOR = bsl::allocator<bsl::pair<const KEY, VALUE>>,
2182 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
2183 >
2184unordered_multimap(std::initializer_list<bsl::pair<const KEY, VALUE>>, ALLOC *)
2185-> unordered_multimap<KEY, VALUE>;
2186#endif
2187
2188// FREE OPERATORS
2189
2190/// Return `true` if the specified `lhs` and `rhs` objects have the same
2191/// value, and `false` otherwise. Two @ref unordered_multimap objects have the
2192/// same value if they have the same number of key-value pairs, and each
2193/// key-value pair that is contained in one of the objects is also contained
2194/// in the other object. This method requires that the (template parameter)
2195/// types `KEY` and `VALUE` both be `equality-comparable` (see {Requirements
2196/// on `KEY` and `VALUE`}).
2197template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2198bool operator==(
2199 const unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& lhs,
2200 const unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& rhs);
2201
2202#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
2203template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2204bool operator!=(
2205 const unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& lhs,
2206 const unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& rhs);
2207 // Return 'true' if the specified 'lhs' and 'rhs' objects do not have the
2208 // same value, and 'false' otherwise. Two @ref unordered_multimap objects do
2209 // not have the same value if they do not have the same number of key-value
2210 // pairs, or some key-value pair that is contained in one of the objects is
2211 // not also contained in the other object. This method requires that the
2212 // (template parameter) types 'KEY' and 'VALUE' both be
2213 // 'equality-comparable' (see {Requirements on 'KEY' and 'VALUE'}).
2214#endif
2215
2216// FREE FUNCTIONS
2217
2218/// Erase all the elements in the specified unordered_multimap `m` that satisfy
2219/// the specified predicate `predicate`. Return the number of elements
2220/// erased.
2221template <class KEY,
2222 class VALUE,
2223 class HASH,
2224 class EQUAL,
2225 class ALLOCATOR,
2226 class PREDICATE>
2227typename unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>::size_type
2228erase_if(unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& m,
2229 PREDICATE predicate);
2230
2231/// Exchange the value, hasher, key-equality functor, and @ref max_load_factor
2232/// of the specified `a` object with those of the specified `b` object; also
2233/// exchange the allocator of `a` with that of `b` if the (template
2234/// parameter) type `ALLOCATOR` has the @ref propagate_on_container_swap trait,
2235/// and do not modify either allocator otherwise. This function provides
2236/// the no-throw exception-safety guarantee if and only if both the
2237/// (template parameter) types `HASH` and `EQUAL` provide no-throw swap
2238/// operations; if an exception is thrown, both objects are left in valid
2239/// but unspecified states. This operation guarantees `O[1]` complexity.
2240///
2241/// \pre The behavior is undefined unless either `a` was created with the same
2242/// allocator as `b` or `ALLOCATOR` has the @ref propagate_on_container_swap
2243/// trait.
2244template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2245void swap(unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& a,
2246 unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& b)
2248
2249// ============================================================================
2250// TEMPLATE AND INLINE FUNCTION DEFINITIONS
2251// ============================================================================
2252
2253 //-------------------------
2254 // class unordered_multimap
2255 //-------------------------
2256
2257// PRIVATE MANIPULATORS
2258
2259template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2260template <class INPUT_ITERATOR, class SENTINEL>
2261void unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>::
2262 constructFromRange(INPUT_ITERATOR first,
2263 SENTINEL last)
2264{
2265 BSLS_ASSERT_SAFE(this->empty());
2266
2267 const difference_type maxInsertions =
2268 ::BloombergLP::bslstl::IteratorUtil::insertDistance(first, last);
2269 if (0 < maxInsertions) {
2270 this->reserve(maxInsertions);
2271 }
2272 else {
2273 BSLS_ASSERT_SAFE(0 == maxInsertions);
2274 }
2275
2276 while (first != last) {
2277 d_impl.emplace(*first);
2278 ++first;
2279 }
2280}
2281
2282#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
2283 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
2284template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2285template <class INPUT_ITERATOR, class SENTINEL>
2286void unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>::
2287 constructFromRange(INPUT_ITERATOR first,
2288 SENTINEL last,
2289 size_t numElements)
2290{
2291 BSLS_ASSERT_SAFE(this->empty());
2292
2293 if (0 < numElements) {
2294 this->reserve(numElements);
2295 }
2296
2297 while (first != last) {
2298 d_impl.emplace(*first);
2299 ++first;
2300 }
2301}
2302#endif
2303
2304template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2305template <class INPUT_ITERATOR, class SENTINEL>
2306void unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>::
2307 insertFromRange(INPUT_ITERATOR first,
2308 SENTINEL last)
2309{
2310 const difference_type maxInsertions =
2311 ::BloombergLP::bslstl::IteratorUtil::insertDistance(first, last);
2312 if (0 < maxInsertions) {
2313 this->reserve(this->size() + maxInsertions);
2314 }
2315 else {
2316 BSLS_ASSERT_SAFE(0 == maxInsertions);
2317 }
2318
2319 while (first != last) {
2320 d_impl.emplace(*first);
2321 ++first;
2322 }
2323}
2324
2325#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
2326 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
2327template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2328template <class INPUT_ITERATOR, class SENTINEL>
2329void unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>::
2330 insertFromRange(INPUT_ITERATOR first,
2331 SENTINEL last,
2332 size_t numElements)
2333{
2334 if (0 < numElements) {
2335 this->reserve(this->size() + numElements);
2336 }
2337
2338 while (first != last) {
2339 d_impl.emplace(*first);
2340 ++first;
2341 }
2342}
2343#endif
2344
2345// CREATORS
2346template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2347inline
2349: d_impl(HASH(), EQUAL(), 0, 1.0f, ALLOCATOR())
2350{
2351}
2352
2353template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2354inline
2356 size_type initialNumBuckets,
2357 const HASH& hashFunction,
2358 const EQUAL& keyEqual,
2359 const ALLOCATOR& basicAllocator)
2360: d_impl(hashFunction, keyEqual, initialNumBuckets, 1.0f, basicAllocator)
2361{
2362}
2363
2364template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2365inline
2367 size_type initialNumBuckets,
2368 const HASH& hashFunction,
2369 const ALLOCATOR& basicAllocator)
2370: d_impl(hashFunction, EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
2371{
2372}
2373
2374template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2375inline
2377 size_type initialNumBuckets,
2378 const ALLOCATOR& basicAllocator)
2379: d_impl(HASH(), EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
2380{
2381}
2382
2383template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2384inline
2386 const ALLOCATOR& basicAllocator)
2387: d_impl(basicAllocator)
2388{
2389}
2390
2391template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2392inline
2394 const unordered_multimap& original)
2395: d_impl(original.d_impl,
2396 AllocatorTraits::select_on_container_copy_construction(
2397 original.get_allocator()))
2398{
2399}
2400
2401template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2402inline
2404 BloombergLP::bslmf::MovableRef<unordered_multimap> original)
2405: d_impl(MoveUtil::move(MoveUtil::access(original).d_impl))
2406{
2407}
2408
2409template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2410inline
2412 const unordered_multimap& original,
2413 const typename type_identity<ALLOCATOR>::type& basicAllocator)
2414: d_impl(original.d_impl, basicAllocator)
2415{
2416}
2417
2418template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2419inline
2421 BloombergLP::bslmf::MovableRef<unordered_multimap> original,
2422 const typename type_identity<ALLOCATOR>::type& basicAllocator)
2423: d_impl(MoveUtil::move(MoveUtil::access(original).d_impl), basicAllocator)
2424{
2425}
2426
2427template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2428template <class INPUT_ITERATOR>
2429inline
2431 INPUT_ITERATOR first,
2432 INPUT_ITERATOR last,
2433 size_type initialNumBuckets,
2434 const HASH& hashFunction,
2435 const EQUAL& keyEqual,
2436 const ALLOCATOR& basicAllocator)
2437: d_impl(hashFunction, keyEqual, initialNumBuckets, 1.0f, basicAllocator)
2438{
2439 constructFromRange(first, last);
2440}
2441
2442template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2443template <class INPUT_ITERATOR>
2444inline
2446 INPUT_ITERATOR first,
2447 INPUT_ITERATOR last,
2448 size_type initialNumBuckets,
2449 const HASH& hashFunction,
2450 const ALLOCATOR& basicAllocator)
2451: d_impl(hashFunction, EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
2452{
2453 this->insert(first, last);
2454}
2455
2456template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2457template <class INPUT_ITERATOR>
2458inline
2460 INPUT_ITERATOR first,
2461 INPUT_ITERATOR last,
2462 size_type initialNumBuckets,
2463 const ALLOCATOR& basicAllocator)
2464: d_impl(HASH(), EQUAL(), initialNumBuckets, 1.0f, basicAllocator)
2465{
2466 this->insert(first, last);
2467}
2468
2469template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2470template <class INPUT_ITERATOR>
2471inline
2473 INPUT_ITERATOR first,
2474 INPUT_ITERATOR last,
2475 const ALLOCATOR& basicAllocator)
2476: d_impl(HASH(), EQUAL(), 0, 1.0f, basicAllocator)
2477{
2478 this->insert(first, last);
2479}
2480
2481#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2482template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2483# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
2484template <class, class, class>
2485# endif
2486inline
2488 std::initializer_list<value_type> values,
2489 size_type initialNumBuckets,
2490 const HASH& hashFunction,
2491 const EQUAL& keyEqual,
2492 const ALLOCATOR& basicAllocator)
2493: unordered_multimap(values.begin(),
2494 values.end(),
2495 initialNumBuckets,
2496 hashFunction,
2497 keyEqual,
2498 basicAllocator)
2499{
2500}
2501
2502template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2503# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
2504template <class, class>
2505# endif
2506inline
2508 std::initializer_list<value_type> values,
2509 size_type initialNumBuckets,
2510 const HASH& hashFunction,
2511 const ALLOCATOR& basicAllocator)
2512: unordered_multimap(values.begin(),
2513 values.end(),
2514 initialNumBuckets,
2515 hashFunction,
2516 EQUAL(),
2517 basicAllocator)
2518{
2519}
2520
2521template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2522# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
2523template <class>
2524# endif
2525inline
2527 std::initializer_list<value_type> values,
2528 size_type initialNumBuckets,
2529 const ALLOCATOR& basicAllocator)
2530: unordered_multimap(values.begin(),
2531 values.end(),
2532 initialNumBuckets,
2533 HASH(),
2534 EQUAL(),
2535 basicAllocator)
2536{
2537}
2538
2539template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2540# ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
2541template <class>
2542# endif
2543inline
2545 std::initializer_list<value_type> values,
2546 const ALLOCATOR& basicAllocator)
2547: unordered_multimap(values.begin(),
2548 values.end(),
2549 0,
2550 HASH(),
2551 EQUAL(),
2552 basicAllocator)
2553{
2554}
2555#endif // defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2556
2557template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2559{
2560 // All memory management is handled by the base 'd_impl' member.
2561}
2562
2563// MANIPULATORS
2564template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2567 const unordered_multimap& rhs)
2568{
2569 // Note that we have delegated responsibility for correct handling of
2570 // allocator propagation to the 'HashTable' implementation.
2571
2572 d_impl = rhs.d_impl;
2573
2574 return *this;
2575}
2576
2577template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2578inline
2581 BloombergLP::bslmf::MovableRef<unordered_multimap> rhs)
2583 AllocatorTraits::is_always_equal::value &&
2584 std::is_nothrow_move_assignable<HASH>::value &&
2585 std::is_nothrow_move_assignable<EQUAL>::value)
2586{
2587 // Note that we have delegated responsibility for correct handling of
2588 // allocator propagation to the 'HashTable' implementation.
2589
2590 unordered_multimap& lvalue = rhs;
2591
2592 d_impl = MoveUtil::move(lvalue.d_impl);
2593
2594 return *this;
2595}
2596
2597#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2598template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2599inline
2600unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>&
2602 std::initializer_list<value_type> values)
2603{
2604 unordered_multimap tmp(values.begin(), values.end(), d_impl.allocator());
2605
2606 d_impl.swap(tmp.d_impl);
2607
2608 return *this;
2609}
2610#endif
2611
2612#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2613template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2614template <class... Args>
2615inline
2618{
2619 return iterator(d_impl.emplace(
2620 BSLS_COMPILERFEATURES_FORWARD(Args, args)...));
2621
2622}
2623
2624template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2625template <class... Args>
2626inline
2629 const_iterator hint,
2630 Args&&... args)
2631{
2632 return iterator(d_impl.emplaceWithHint(hint.node(),
2633 BSLS_COMPILERFEATURES_FORWARD(Args, args)...));
2634}
2635#endif
2636
2637template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2638inline
2645
2646template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2647inline
2654
2655template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2656inline
2659{
2660 BSLS_ASSERT_SAFE(index < this->bucket_count());
2661
2662 return local_iterator(&d_impl.bucketAtIndex(index));
2663}
2664
2665template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2666inline
2669{
2670 BSLS_ASSERT_SAFE(index < this->bucket_count());
2671
2672 return local_iterator(0, &d_impl.bucketAtIndex(index));
2673}
2674
2675template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2676inline
2682
2683template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2684inline
2686 const key_type& key) const
2687{
2688 return find(key) != end();
2689}
2690
2691template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2692inline
2695 const key_type& key)
2696{
2697 return iterator(d_impl.find(key));
2698}
2699
2700template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2701bsl::pair<
2705 const key_type& key)
2706{
2707 HashTableLink *first;
2708 HashTableLink *last;
2709 d_impl.findRange(&first, &last, key);
2710 return bsl::pair<iterator, iterator>(iterator(first), iterator(last));
2711}
2712
2713template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2714inline
2717 const_iterator position)
2718{
2719 BSLS_ASSERT(position != this->end());
2720
2721 return iterator(d_impl.remove(position.node()));
2722}
2723
2724template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2725inline
2732
2733template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2736 const key_type& key)
2737{ // As an alternative implementation, the table could return an extracted
2738 // "slice" list from the underlying table, and now need merely:
2739 // iterate each node, destroying the associated value
2740 // reclaim each node (potentially returning to a node-pool)
2741
2742 typedef ::BloombergLP::bslalg::BidirectionalNode<value_type> BNode;
2743
2744 if (HashTableLink *target = d_impl.find(key)) {
2745 target = d_impl.remove(target);
2746 size_type result = 1;
2747 while (target &&
2748 this->key_eq()(key, ListConfiguration::extractKey(
2749 static_cast<BNode *>(target)->value()))) {
2750 target = d_impl.remove(target);
2751 ++result;
2752 }
2753 return result; // RETURN
2754 }
2755
2756 return 0;
2757}
2758
2759template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2762 const_iterator first,
2763 const_iterator last)
2764{
2765#if defined BDE_BUILD_TARGET_SAFE_2
2766 if (first != last) {
2767 iterator it = this->begin();
2768 const iterator end = this->end();
2769 for (; it != first; ++it) {
2770 BSLS_ASSERT(last != it);
2771 BSLS_ASSERT(end != it);
2772 }
2773 for (; it != last; ++it) {
2774 BSLS_ASSERT(end != it);
2775 }
2776 }
2777#endif
2778
2779 while (first != last) {
2780 first = this->erase(first);
2781 }
2782
2783 return iterator(first.node()); // convert from const_iterator
2784}
2785
2786template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2787inline
2790 const value_type& value)
2791{
2792 return iterator(d_impl.insert(value));
2793}
2794
2795template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2796inline
2799 const_iterator hint,
2800 const value_type& value)
2801{
2802 return iterator(d_impl.insert(value, hint.node()));
2803}
2804
2805template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2806template <class INPUT_ITERATOR>
2808 INPUT_ITERATOR first,
2809 INPUT_ITERATOR last)
2810{
2811 insertFromRange(first, last);
2812}
2813
2814#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2815template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2816inline
2818 std::initializer_list<value_type> values)
2819{
2820 insert(values.begin(), values.end());
2821}
2822#endif
2823
2824template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2825inline
2827 float newLoadFactor)
2828{
2829 d_impl.setMaxLoadFactor(newLoadFactor);
2830}
2831
2832template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2833inline
2835 size_type numBuckets)
2836{
2837 d_impl.rehashForNumBuckets(numBuckets);
2838}
2839
2840template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2841inline
2843 size_type numElements)
2844{
2845 d_impl.reserveForNumElements(numElements);
2846}
2847
2848template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2849inline
2851 unordered_multimap& other)
2853 AllocatorTraits::is_always_equal::value &&
2854 bsl::is_nothrow_swappable<HASH>::value &&
2855 bsl::is_nothrow_swappable<EQUAL>::value)
2856{
2857 d_impl.swap(other.d_impl);
2858}
2859
2860// ACCESSORS
2861template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2862inline
2863ALLOCATOR
2866{
2867 return d_impl.allocator();
2868}
2869
2870template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2877
2878template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2879inline
2886
2887template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2894
2895template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2896inline
2903
2904template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2905inline
2907 const_local_iterator
2909 size_type index) const
2910{
2911 BSLS_ASSERT_SAFE(index < this->bucket_count());
2912
2913 return const_local_iterator(&d_impl.bucketAtIndex(index));
2914}
2915
2916template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2917inline
2918typename
2921 size_type index) const
2922{
2923 BSLS_ASSERT_SAFE(index < this->bucket_count());
2924
2925 return const_local_iterator(0, &d_impl.bucketAtIndex(index));
2926}
2927
2928template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2929inline
2930typename
2933 size_type index) const
2934{
2935 BSLS_ASSERT_SAFE(index < this->bucket_count());
2936
2937 return const_local_iterator(&d_impl.bucketAtIndex(index));
2938}
2939
2940template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2941inline
2943 const_local_iterator
2945 size_type index) const
2946{
2947 BSLS_ASSERT_SAFE(index < this->bucket_count());
2948
2949 return const_local_iterator(0, &d_impl.bucketAtIndex(index));
2950}
2951
2952template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2953inline
2956 const key_type& key) const
2957{
2958 return d_impl.bucketIndexForKey(key);
2959}
2960
2961template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2962inline
2969
2970template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2971inline
2974 size_type index) const
2975{
2976 BSLS_ASSERT_SAFE(index < this->bucket_count());
2977
2978 return d_impl.countElementsInBucket(index);
2979}
2980
2981template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
2984 const key_type& key) const
2985{
2986 typedef ::BloombergLP::bslalg::BidirectionalNode<value_type> BNode;
2987
2988 size_type result = 0;
2989 for (HashTableLink *cursor = d_impl.find(key);
2990 cursor;
2991 ++result, cursor = cursor->nextLink())
2992 {
2993 BNode *cursorNode = static_cast<BNode *>(cursor);
2994 if (!this->key_eq()(key,
2995 ListConfiguration::extractKey(cursorNode->value()))) {
2996
2997 break;
2998 }
2999 }
3000 return result;
3001}
3002
3003template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3004inline
3007 const key_type& key) const
3008{
3009 return const_iterator(d_impl.find(key));
3010}
3011
3012template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3013inline
3016{
3017 return 0 == d_impl.size();
3018}
3019
3020template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3021inline
3028
3029template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3030inline
3034{
3035 return AllocatorTraits::max_size(get_allocator());
3036}
3037
3038template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3039inline
3042{
3043 return d_impl.hasher();
3044}
3045
3046template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3047inline
3050{
3051 return d_impl.comparator();
3052}
3053
3054template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3055bsl::pair<typename unordered_multimap<KEY,
3056 VALUE,
3057 HASH,
3058 EQUAL,
3059 ALLOCATOR>::const_iterator,
3060 typename unordered_multimap<KEY,
3061 VALUE,
3062 HASH,
3063 EQUAL,
3064 ALLOCATOR>::const_iterator>
3066 const key_type& key) const
3067{
3068 HashTableLink *first;
3069 HashTableLink *last;
3070 d_impl.findRange(&first, &last, key);
3072 const_iterator(last));
3073}
3074
3075template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3076inline
3079 const
3081{
3082 return d_impl.maxNumBuckets();
3083}
3084
3085template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3086inline
3088 const
3090{
3091 return d_impl.loadFactor();
3092}
3093
3094template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3095inline
3097 const
3099{
3100 return d_impl.maxLoadFactor();
3101}
3102
3103} // close namespace bsl
3104
3105// FREE OPERATORS
3106template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3107inline
3108bool bsl::operator==(
3111{
3112 return lhs.d_impl == rhs.d_impl;
3113}
3114
3115#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
3116template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3117inline
3118bool bsl::operator!=(
3121{
3122 return !(lhs == rhs);
3123}
3124#endif
3125
3126// FREE FUNCTIONS
3127template <class KEY,
3128 class VALUE,
3129 class HASH,
3130 class EQUAL,
3131 class ALLOCATOR,
3132 class PREDICATE>
3133inline
3135bsl::erase_if(unordered_multimap<KEY, VALUE, HASH, EQUAL, ALLOCATOR>& m,
3136 PREDICATE predicate)
3137{
3138 return BloombergLP::bslstl::AlgorithmUtil::containerEraseIf(m, predicate);
3139}
3140
3141template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3142inline
3146{
3147 a.swap(b);
3148}
3149
3150// ============================================================================
3151// TYPE TRAITS
3152// ============================================================================
3153
3154// Type traits for STL *unordered* *associative* containers:
3155//: o An unordered associative container defines STL iterators.
3156//: o An unordered associative container is bitwise movable if both functors
3157//: and the allocator are bitwise movable.
3158//: o An unordered associative container uses 'bslma' allocators if the
3159//: (template parameter) type 'ALLOCATOR' is convertible from
3160//: 'bslma::Allocator*'.
3161
3162
3163
3164namespace bslalg {
3165
3166template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3167struct HasStlIterators<bsl::unordered_multimap<KEY,
3168 VALUE,
3169 HASH,
3170 EQUAL,
3171 ALLOCATOR> >
3173{};
3174
3175} // close namespace bslalg
3176
3177namespace bslma {
3178
3179template <class KEY, class VALUE, class HASH, class EQUAL, class ALLOCATOR>
3180struct UsesBslmaAllocator<bsl::unordered_multimap<KEY,
3181 VALUE,
3182 HASH,
3183 EQUAL,
3184 ALLOCATOR> >
3185: bsl::is_convertible<Allocator*, ALLOCATOR>::type
3186{};
3187
3188} // close namespace bslma
3189
3190namespace bslmf {
3191
3192template <class KEY, class MAPPED, class HASH, class EQUAL, class ALLOCATOR>
3193struct IsBitwiseMoveable<
3194 bsl::unordered_multimap<KEY, MAPPED, HASH, EQUAL, ALLOCATOR> >
3195 : ::BloombergLP::bslmf::IsBitwiseMoveable<BloombergLP::bslstl::HashTable<
3196 ::BloombergLP::bslstl::
3197 UnorderedMapKeyConfiguration<KEY, bsl::pair<const KEY, MAPPED> >,
3198 HASH,
3199 EQUAL,
3200 ALLOCATOR> >::type
3201{};
3202
3203}
3204
3205
3206#endif // End C++11 code
3207
3208#endif
3209
3210// ----------------------------------------------------------------------------
3211// Copyright 2013 Bloomberg Finance L.P.
3212//
3213// Licensed under the Apache License, Version 2.0 (the "License");
3214// you may not use this file except in compliance with the License.
3215// You may obtain a copy of the License at
3216//
3217// http://www.apache.org/licenses/LICENSE-2.0
3218//
3219// Unless required by applicable law or agreed to in writing, software
3220// distributed under the License is distributed on an "AS IS" BASIS,
3221// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3222// See the License for the specific language governing permissions and
3223// limitations under the License.
3224// ----------------------------- END-OF-FILE ----------------------------------
3225
3226/** @} */
3227/** @} */
3228/** @} */
Definition bslma_bslallocator.h:588
Definition bslstl_pair.h:1280
Definition bslstl_unorderedmultimap.h:740
float max_load_factor() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:3096
friend bool operator==(const unordered_multimap< KEY2, VALUE2, HASH2, EQUAL2, ALLOCATOR2 > &, const unordered_multimap< KEY2, VALUE2, HASH2, EQUAL2, ALLOCATOR2 > &)
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_unorderedmultimap.h:1248
unordered_multimap()
Definition bslstl_unorderedmultimap.h:2348
bool empty() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:3014
const value_type & const_reference
Definition bslstl_unorderedmultimap.h:796
EQUAL key_eq() const
Definition bslstl_unorderedmultimap.h:3049
float load_factor() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:3087
KEY key_type
Definition bslstl_unorderedmultimap.h:788
ALLOCATOR allocator_type
Definition bslstl_unorderedmultimap.h:793
AllocatorTraits::const_pointer const_pointer
Definition bslstl_unorderedmultimap.h:801
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:2649
size_type max_size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:3032
void reserve(size_type numElements)
Definition bslstl_unorderedmultimap.h:2842
HASH hash_function() const
Definition bslstl_unorderedmultimap.h:3041
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, pair< const_iterator, const_iterator > >::type equal_range(const LOOKUP_KEY &key) const
Definition bslstl_unorderedmultimap.h:1708
::BloombergLP::bslstl::HashTableIterator< value_type, difference_type > iterator
Definition bslstl_unorderedmultimap.h:804
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_unorderedmultimap.h:1339
unordered_multimap &operator=(BloombergLP::bslmf::MovableRef< unordered_multimap > rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:2640
BSLSTL_UNORDEREDMULTIMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(RANGE, value_type) unordered_multimap(bsl
Definition bslstl_unorderedmultimap.h:1089
size_type bucket(const key_type &key) const
Definition bslstl_unorderedmultimap.h:2955
value_type & reference
Definition bslstl_unorderedmultimap.h:795
HASH hasher
Definition bslstl_unorderedmultimap.h:791
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:2889
void swap(unordered_multimap &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:1573
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:2898
enable_if< is_convertible< ALT_VALUE_TYPE, value_type >::value, iterator >::type insert(BSLS_COMPILERFEATURES_FORWARD_REF(ALT_VALUE_TYPE) value)
Definition bslstl_unorderedmultimap.h:1379
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, t_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, t_KEY >::value &&!is_convertible< BSLS_COMPILERFEATURES_FORWARD_REF(t_KEY), iterator >::value &&!is_convertible< BSLS_COMPILERFEATURES_FORWARD_REF(t_KEY), const_iterator >::value, size_type >::type erase(BSLS_COMPILERFEATURES_FORWARD_REF(t_KEY) key)
Definition bslstl_unorderedmultimap.h:1284
unordered_multimap & operator=(const unordered_multimap &rhs)
Definition bslstl_unorderedmultimap.h:2566
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_unorderedmultimap.h:1667
::BloombergLP::bslstl::HashTableIterator< const value_type, difference_type > const_iterator
Definition bslstl_unorderedmultimap.h:807
EQUAL key_equal
Definition bslstl_unorderedmultimap.h:792
size_type max_bucket_count() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:3078
size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:2964
enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, size_type >::type bucket(const LOOKUP_KEY &key) const
Definition bslstl_unorderedmultimap.h:1764
iterator insert(const value_type &value)
Definition bslstl_unorderedmultimap.h:2789
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this unordered multimap.
Definition bslstl_unorderedmultimap.h:3023
size_type erase(const key_type &key)
Definition bslstl_unorderedmultimap.h:2735
bool contains(const key_type &key) const
Definition bslstl_unorderedmultimap.h:2685
::BloombergLP::bslstl::HashTableBucketIterator< const value_type, difference_type > const_local_iterator
Definition bslstl_unorderedmultimap.h:813
AllocatorTraits::difference_type difference_type
Definition bslstl_unorderedmultimap.h:799
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition bslstl_unorderedmultimap.h:2628
::BloombergLP::bslstl::HashTableBucketIterator< value_type, difference_type > local_iterator
Definition bslstl_unorderedmultimap.h:810
AllocatorTraits::pointer pointer
Definition bslstl_unorderedmultimap.h:800
bsl::pair< const KEY, VALUE > value_type
Definition bslstl_unorderedmultimap.h:790
AllocatorTraits::size_type size_type
Definition bslstl_unorderedmultimap.h:798
void rehash(size_type numBuckets)
Definition bslstl_unorderedmultimap.h:2834
iterator emplace(Args &&... args)
Definition bslstl_unorderedmultimap.h:2617
size_type bucket_size(size_type index) const
Definition bslstl_unorderedmultimap.h:2973
void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_unorderedmultimap.h:2677
~unordered_multimap()
Destroy this object.
Definition bslstl_unorderedmultimap.h:2558
VALUE mapped_type
Definition bslstl_unorderedmultimap.h:789
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_unorderedmultimap.h:1432
BSLSTL_UNORDEREDMULTIMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(RANGE, value_type) void insert_range(BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
Definition bslstl_unorderedmultimap.h:1464
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
#define BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(...)
Definition bsls_keyword.h:676
#define BSLSTL_UNORDEREDMULTIMAP_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
Definition bslstl_unorderedmultimap.h:703
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
int reserve(TYPE *array, int numElements)
Definition bdlat_valuetypefunctions.h:939
void swap(array< VALUE_TYPE, SIZE > &lhs, array< VALUE_TYPE, SIZE > &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4424
T::iterator begin(T &container)
Definition bslstl_iterator.h:1593
const from_range_t from_range
ALLOCATOR & lhs
Definition bslstl_string.h:3917
T::iterator end(T &container)
Definition bslstl_iterator.h:1621
deque< VALUE_TYPE, ALLOCATOR >::size_type erase_if(deque< VALUE_TYPE, ALLOCATOR > &deq, PREDICATE predicate)
Definition bslstl_deque.h:4433
bool operator!=(const memory_resource &a, const memory_resource &b)
Definition bdlc_flathashmap.h:2218
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bdldfp_decimal.h:5549
Definition bslma_allocatortraits.h:1089
BloombergLP::bslma::AllocatorTraits_ConstPointerType< ALLOCATOR >::type const_pointer
Definition bslma_allocatortraits.h:1183
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR >::type size_type
Definition bslma_allocatortraits.h:1196
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR >::type pointer
Definition bslma_allocatortraits.h:1180
BloombergLP::bslma::AllocatorTraits_DifferenceType< ALLOCATOR >::type difference_type
Definition bslma_allocatortraits.h:1193
Definition bslmf_enableif.h:530
Definition bslstl_equalto.h:316
Definition bslstl_ranges.h:301
Definition bslstl_hash.h:495
Definition bslmf_isconvertible.h:875