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