BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_multiset.h
Go to the documentation of this file.
1/// @file bslstl_multiset.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_multiset.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_MULTISET
9#define INCLUDED_BSLSTL_MULTISET
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_multiset bslstl_multiset
15/// @brief Provide an STL-compliant multiset class.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_multiset
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_multiset-purpose"> Purpose</a>
25/// * <a href="#bslstl_multiset-classes"> Classes </a>
26/// * <a href="#bslstl_multiset-canonical-header"> Canonical Header </a>
27/// * <a href="#bslstl_multiset-description"> Description </a>
28/// * <a href="#bslstl_multiset-requirements-on-key"> Requirements on KEY </a>
29/// * <a href="#bslstl_multiset-memory-allocation"> Memory Allocation </a>
30/// * <a href="#bslstl_multiset-bslma-style-allocators"> bslma-Style Allocators </a>
31/// * <a href="#bslstl_multiset-operations"> Operations </a>
32/// * <a href="#bslstl_multiset-usage"> Usage </a>
33/// * <a href="#bslstl_multiset-example-1-creating-a-shopping-cart"> Example 1: Creating a Shopping Cart </a>
34///
35/// # Purpose {#bslstl_multiset-purpose}
36/// Provide an STL-compliant multiset class.
37///
38/// # Classes {#bslstl_multiset-classes}
39///
40/// - bsl::multiset: STL-compatible multiset template
41///
42/// # Canonical Header {#bslstl_multiset-canonical-header}
43/// bsl_set.h
44///
45/// @see bslstl_set, bslstl_multimap
46///
47/// # Description {#bslstl_multiset-description}
48/// This component defines a single class template `bsl::multiset`,
49/// implementing the standard container holding an ordered sequence of possibly
50/// duplicate keys.
51///
52/// An instantiation of `multiset` is an allocator-aware, value-semantic type
53/// whose salient attributes are its size (number of keys) and the ordered
54/// sequence of keys the `multiset` contains. If `multiset` is instantiated
55/// with a key type that is not itself value-semantic, then it will not retain
56/// all of its value-semantic qualities. In particular, if the key type cannot
57/// be tested for equality, then a multiset containing that type cannot be
58/// tested for equality. It is even possible to instantiate `multiset` with a
59/// key type that does not have a copy-constructor, in which case the `multiset`
60/// will not be copyable.
61///
62/// A multiset meets the requirements of an associative container with
63/// bidirectional iterators in the C++ standard [23.2.4]. The `multiset`
64/// implemented here adheres to the C++11 standard when compiled with a C++11
65/// compiler, and makes the best approximation when compiled with a C++03
66/// compiler. In particular, for C++03 we emulate move semantics, but limit
67/// forwarding (in `emplace`) to `const` lvalues, and make no effort to emulate
68/// `noexcept` or initializer-lists.
69///
70/// ## Requirements on KEY {#bslstl_multiset-requirements-on-key}
71///
72///
73/// A `multiset` is a fully "Value-Semantic Type" (see @ref bsldoc_glossary ) only
74/// if the supplied `KEY` template parameter is fully value-semantic. It is
75/// possible to instantiate a `multiset` with a `KEY` parameter argument that
76/// does not provide a full set of value-semantic operations, but then some
77/// methods of the container may not be instantiable. The following
78/// terminology, adopted from the C++11 standard, is used in the function
79/// documentation of `multiset` to describe a function's requirements for the
80/// `KEY` template parameter. These terms are also defined in section
81/// [17.6.3.1] of the C++11 standard. Note that, in the context of a `multiset`
82/// instantiation, the requirements apply specifically to the multiset's entry
83/// type, `value_type`, which is an alias for `KEY`.
84///
85/// Legend
86/// ------
87/// `X` - denotes an allocator-aware container type (e.g., `multiset`)
88/// `T` - `value_type` associated with `X`
89/// `A` - type of the allocator used by `X`
90/// `m` - lvalue of type `A` (allocator)
91/// `p`, - address (`T *`) of uninitialized storage for a `T` within an `X`
92/// `rv` - rvalue of type (non-`const`) `T`
93/// `v` - rvalue or lvalue of type (possibly `const`) `T`
94/// `args` - 0 or more arguments
95///
96/// The following terms are used to more precisely specify the requirements on
97/// template parameter types in function-level documentation.
98///
99/// *default-insertable*: `T` has a default constructor. More precisely, `T`
100/// is `default-insertable` into `X` means that the following expression is
101/// well-formed:
102///
103/// `allocator_traits<A>::construct(m, p)`
104///
105/// *move-insertable*: `T` provides a constructor that takes an rvalue of type
106/// (non-`const`) `T`. More precisely, `T` is `move-insertable` into `X`
107/// means that the following expression is well-formed:
108///
109/// `allocator_traits<A>::construct(m, p, rv)`
110///
111/// *copy-insertable*: `T` provides a constructor that takes an lvalue or
112/// rvalue of type (possibly `const`) `T`. More precisely, `T` is
113/// `copy-insertable` into `X` means that the following expression is
114/// well-formed:
115///
116/// `allocator_traits<A>::construct(m, p, v)`
117///
118/// *move-assignable*: `T` provides an assignment operator that takes an rvalue
119/// of type (non-`const`) `T`.
120///
121/// *copy-assignable*: `T` provides an assignment operator that takes an lvalue
122/// or rvalue of type (possibly `const`) `T`.
123///
124/// *emplace-constructible*: `T` is `emplace-constructible` into `X` from
125/// `args` means that the following expression is well-formed:
126///
127/// `allocator_traits<A>::construct(m, p, args)`
128///
129/// *erasable*: `T` provides a destructor. More precisely, `T` is `erasable`
130/// from `X` means that the following expression is well-formed:
131///
132/// `allocator_traits<A>::destroy(m, p)`
133///
134/// *equality-comparable*: The type provides an equality-comparison operator
135/// that defines an equivalence relationship and is both reflexive and
136/// transitive.
137///
138/// ## Memory Allocation {#bslstl_multiset-memory-allocation}
139///
140///
141/// The type supplied as a multiset's `ALLOCATOR` template parameter determines
142/// how that multiset will allocate memory. The `multiset` template supports
143/// allocators meeting the requirements of the C++11 standard [17.6.3.5]; in
144/// addition, it supports scoped-allocators derived from the `bslma::Allocator`
145/// memory allocation protocol. Clients intending to use `bslma`-style
146/// allocators should use the template's default `ALLOCATOR` type: The default
147/// type for the `ALLOCATOR` template parameter, `bsl::allocator`, provides a
148/// C++11 standard-compatible adapter for a `bslma::Allocator` object.
149///
150/// ### bslma-Style Allocators {#bslstl_multiset-bslma-style-allocators}
151///
152///
153/// If the (template parameter) type `ALLOCATOR` of a `multiset` instantiation
154/// is `bsl::allocator`, then objects of that multiset type will conform to the
155/// standard behavior of a `bslma`-allocator-enabled type. Such a multiset
156/// accepts an optional `bslma::Allocator` argument at construction. If the
157/// address of a `bslma::Allocator` object is explicitly supplied at
158/// construction, it is used to supply memory for the multiset throughout its
159/// lifetime; otherwise, the multiset will use the default allocator installed
160/// at the time of the multiset's construction (see @ref bslma_default ). In
161/// addition to directly allocating memory from the indicated
162/// `bslma::Allocator`, a multiset supplies that allocator's address to the
163/// constructors of contained objects of the (template parameter) type `KEY`
164/// having the `bslma::UsesBslmaAllocator` trait.
165///
166/// ## Operations {#bslstl_multiset-operations}
167///
168///
169/// This section describes the run-time complexity of operations on instances
170/// of `multiset`:
171/// @code
172/// Legend
173/// ------
174/// 'K' - (template parameter) type 'KEY' of the multiset
175/// 'a', 'b' - two distinct objects of type 'multiset<K>'
176/// 'rv' - modifiable rvalue of type 'multiset<K>'
177/// 'n', 'm' - number of elements in 'a' and 'b' respectively
178/// 'c' - comparator providing an ordering for objects of type 'K'
179/// 'al' - STL-style memory allocator
180/// 'i1', 'i2' - two iterators defining a sequence of 'value_type' objects
181/// 'rg' - range of objects convertible to 'value_type`
182/// 'li' - object of type 'initializer_list<K>'
183/// 'k' - object of type 'K'
184/// 'rk' - modifiable rvalue of type 'K'
185/// 'p1', 'p2' - two 'const_iterator's belonging to 'a'
186/// distance(i1,i2) - number of elements in the range '[i1 .. i2)'
187/// distance(p1,p2) - number of elements in the range '[p1 .. p2)'
188///
189/// +----------------------------------------------------+--------------------+
190/// | Operation | Complexity |
191/// +====================================================+====================+
192/// | multiset<K> a; (default construction)| O[1] |
193/// | multiset<K> a(al); | |
194/// | multiset<K> a(c, al); | |
195/// +----------------------------------------------------+--------------------+
196/// | multiset<K> a(b); (copy construction) | O[n] |
197/// | multiset<K> a(b, al); | |
198/// +----------------------------------------------------+--------------------+
199/// | multiset<K> a(rv); (move construction) | O[1] if 'a' and |
200/// | multiset<K> a(rv, al); | 'rv' use the same |
201/// | | allocator, |
202/// | | O[n] otherwise |
203/// +----------------------------------------------------+--------------------+
204/// | multiset<K> a(i1, i2, al); (range construction) | O[N] if [i1, i2) |
205/// | multiset<K> a(i1, i2, c, al); | is sorted with |
206/// | | 'a.value_comp()', |
207/// | | O[N * log(N)] |
208/// | | otherwise, where N |
209/// | | is distance(i1,i2) |
210/// +----------------------------------------------------+--------------------+
211/// | multiset<K> a(from_range, rg); | O[N] if 'rg' is |
212/// | multiset<K> a(from_range, rg, al); | sorted with |
213/// | multiset<K> a(from_range, rg, c, al); | 'a.value_comp()', |
214/// | | O[N * log(N)] |
215/// | | otherwise, where N |
216/// | | is ranges:: |
217/// | | distance(rg) |
218/// +----------------------------------------------------+--------------------+
219/// | multiset<K> a(li); | O[N] if 'li' is |
220/// | multiset<K> a(li, al); | sorted with |
221/// | multiset<K> a(li, c); | 'a.value_comp()', |
222/// | multiset<K> a(li, c, al); | O[N * log(N)] |
223/// | | otherwise, where |
224/// | | N = 'li.size()' |
225/// +----------------------------------------------------+--------------------+
226/// | a.~multiset<K>(); (destruction) | O[n] |
227/// +----------------------------------------------------+--------------------+
228/// | a = b; (copy assignment) | O[n] |
229/// +----------------------------------------------------+--------------------+
230/// | a = rv; (move assignment) | O[1] if 'a' and |
231/// | | 'rv' use the same |
232/// | | allocator, |
233/// | | O[n] otherwise |
234/// +----------------------------------------------------+--------------------+
235/// | a = li; | O[N] if 'li' is |
236/// | | sorted with |
237/// | | 'a.value_comp()', |
238/// | | O[N * log(N)] |
239/// | | otherwise, where |
240/// | | N = 'li.size()' |
241/// +----------------------------------------------------+--------------------+
242/// | a.begin(), a.end(), a.cbegin(), a.cend(), | O[1] |
243/// | a.rbegin(), a.rend(), a.crbegin(), a.crend() | |
244/// +----------------------------------------------------+--------------------+
245/// | a == b, a != b | O[n] |
246/// +----------------------------------------------------+--------------------+
247/// | a < b, a <= b, a > b, a >= b | O[n] |
248/// +----------------------------------------------------+--------------------+
249/// | a.swap(b), swap(a, b) | O[1] if 'a' and |
250/// | | 'b' use the same |
251/// | | allocator, |
252/// | | O[n + m] otherwise |
253/// +----------------------------------------------------+--------------------+
254/// | a.size() | O[1] |
255/// +----------------------------------------------------+--------------------+
256/// | a.max_size() | O[1] |
257/// +----------------------------------------------------+--------------------+
258/// | a.empty() | O[1] |
259/// +----------------------------------------------------+--------------------+
260/// | get_allocator() | O[1] |
261/// +----------------------------------------------------+--------------------+
262/// | a.insert(k) | O[log(n)] |
263/// | a.insert(rk) | |
264/// | a.emplace(Args&&...) | |
265/// +----------------------------------------------------+--------------------+
266/// | a.insert(p1, k) | amortized constant |
267/// | a.insert(p1, rk) | if the value is |
268/// | a.emplace_hint(p1, Args&&...) | inserted right |
269/// | | before p1, |
270/// | | O[log(n)] |
271/// | | otherwise |
272/// +----------------------------------------------------+--------------------+
273/// | a.insert(i1, i2) | O[N * log(n + N)] |
274/// | | where N is |
275/// | | distance(i1,i2) |
276/// +----------------------------------------------------+--------------------+
277/// | a.insert_range(rg) | O[log(N) * |
278/// | | ranges:: |
279/// | | distance(rg)] |
280/// | | |
281/// | | where N is n + |
282/// | | ranges:: |
283/// | | distance(rg)|
284/// +----------------------------------------------------+--------------------+
285/// | a.insert(li) | O[N * log(n + N)] |
286/// | | where N = |
287/// | | 'li.size()'|
288/// +----------------------------------------------------+--------------------+
289/// | a.erase(p1) | amortized constant |
290/// +----------------------------------------------------+--------------------+
291/// | a.erase(k) | O[log(n) + |
292/// | | a.count(k)] |
293/// +----------------------------------------------------+--------------------+
294/// | a.erase(p1, p2) | O[log(n) + |
295/// | | distance(p1, p2)] |
296/// +----------------------------------------------------+--------------------+
297/// | a.clear() | O[n] |
298/// +----------------------------------------------------+--------------------+
299/// | a.key_comp() | O[1] |
300/// +----------------------------------------------------+--------------------+
301/// | a.value_comp() | O[1] |
302/// +----------------------------------------------------+--------------------+
303/// | a.contains(k) | O[log(n)] |
304/// +----------------------------------------------------+--------------------+
305/// | a.find(k) | O[log(n)] |
306/// +----------------------------------------------------+--------------------+
307/// | a.count(k) | O[log(n) + |
308/// | | a.count(k)] |
309/// +----------------------------------------------------+--------------------+
310/// | a.lower_bound(k) | O[log(n)] |
311/// +----------------------------------------------------+--------------------+
312/// | a.upper_bound(k) | O[log(n)] |
313/// +----------------------------------------------------+--------------------+
314/// | a.equal_range(k) | O[log(n)] |
315/// +----------------------------------------------------+--------------------+
316/// @endcode
317///
318/// ## Usage {#bslstl_multiset-usage}
319///
320///
321/// In this section we show intended use of this component.
322///
323/// ### Example 1: Creating a Shopping Cart {#bslstl_multiset-example-1-creating-a-shopping-cart}
324///
325///
326/// In this example, we will utilize `bsl::multiset` to define a class
327/// `ShoppingCart`, that characterizes a simple online shopping cart with the
328/// ability to add, remove, and view items in the shopping cart.
329///
330/// Note that this example uses a type `string` that is based on the standard
331/// type `string` (see @ref bslstl_string ). For the sake of brevity, the
332/// implementation of `string` is not explored here.
333///
334/// First, we define a comparison functor for `string` objects:
335/// @code
336/// struct StringComparator {
337/// // This 'struct' defines an ordering on 'string' values, allowing
338/// // them to be included in sorted containers such as 'bsl::multiset'.
339///
340/// bool operator()(const string& lhs, const string& rhs) const
341/// // Return 'true' if the value of the specified 'lhs' is less than
342/// // (ordered before) the value of the specified 'rhs', and 'false'
343/// // otherwise.
344/// {
345/// int cmp = std::strcmp(lhs.c_str(), rhs.c_str());
346/// return cmp < 0;
347/// }
348/// };
349/// @endcode
350/// Then, we define the public interface for `ShoppingCart`:
351/// @code
352/// class ShoppingCart {
353/// // This class provides an ordered collection of (possibly duplicate)
354/// // items in a shopping cart. For simplicity of the usage example, each
355/// // item in the shopping cart is represented by a 'string'.
356/// @endcode
357/// Here, we create a type alias, `StringSet`, for a `bsl::multiset` that will
358/// serve as the data member for a `ShoppingCart`. A `StringSet` has keys of
359/// type `string`, and uses the default `ALLOCATOR` template parameter to be
360/// compatible with `bslma` style allocators:
361/// @code
362/// // PRIVATE TYPES
363/// typedef bsl::multiset<string, StringComparator> StringSet;
364/// // This 'typedef' is an alias for a multiset of 'string' objects,
365/// // each representing an item in a shopping cart;
366///
367/// // DATA
368/// StringSet d_items; // multiset of items in the shopping cart
369///
370/// // FRIENDS
371/// friend bool operator==(const ShoppingCart& lhs,
372/// const ShoppingCart& rhs);
373///
374/// public:
375/// // PUBLIC TYPES
376/// typedef StringSet::const_iterator ConstIterator;
377/// // This 'typedef' provides an alias for the type of an iterator
378/// // providing non-modifiable access to the items in a
379/// // 'ShoppingCart'.
380///
381/// // CREATORS
382/// ShoppingCart(bslma::Allocator *basicAllocator = 0);
383/// // Create an empty 'Shopping' object. Optionally specify a
384/// // 'basicAllocator' used to supply memory. If 'basicAllocator' is
385/// // 0, the currently installed default allocator is used.
386///
387/// ShoppingCart(const ShoppingCart& original,
388/// bslma::Allocator *basicAllocator = 0);
389/// // Create a 'ShoppingCart' object having the same value as the
390/// // specified 'original' object. Optionally specify a
391/// // 'basicAllocator' used to supply memory. If 'basicAllocator' is
392/// // 0, the currently installed default allocator is used.
393///
394/// //! ~ShoppingCart() = default;
395/// // Destroy this object.
396///
397/// // MANIPULATORS
398/// ShoppingCart& operator=(const ShoppingCart& rhs);
399/// // Assign to this object the value of the specified 'rhs' object,
400/// // and return a reference providing modifiable access to this
401/// // object.
402///
403/// void addItem(const string& name);
404/// // Add an item with the specified 'name' to this shopping cart.
405/// // The behavior is undefined unless 'name' is a non-empty strings.
406///
407/// size_t removeItems(const string& name);
408/// // Remove from this shopping cart all items having the specified
409/// // 'name', if they exist, and return the number of removed items;
410/// // otherwise, return 0 with no other effects. The behavior is
411/// // undefined unless 'name' is a non-empty strings.
412///
413/// // ACCESSORS
414/// size_t count(const string& name) const;
415/// // Return the number of items in the shopping cart with the
416/// // specified 'name'. The behavior is undefined unless 'name' is a
417/// // non-empty strings.
418///
419/// ConstIterator begin() const;
420/// // Return an iterator providing non-modifiable access to the first
421/// // item in the ordered sequence of item held in this shopping cart,
422/// // or the past-the-end iterator if this shopping cart is empty.
423///
424/// ConstIterator end() const;
425/// // Return an iterator providing non-modifiable access to the
426/// // past-the-end item in the ordered sequence of items maintained by
427/// // this shopping cart.
428///
429/// size_t numItems() const;
430/// // Return the number of items contained in this shopping cart.
431/// };
432/// @endcode
433/// Then, we declare the free operators for `ShoppingCart`:
434/// @code
435/// inline
436/// bool operator==(const ShoppingCart& lhs, const ShoppingCart& rhs);
437/// // Return 'true' if the specified 'lhs' and 'rhs' objects have the same
438/// // value, and 'false' otherwise. Two 'ShoppingCart' objects have the
439/// // same value if they have the same number of items, and each
440/// // corresponding item, in their respective ordered sequence of items,
441/// // is the same.
442///
443/// inline
444/// bool operator!=(const ShoppingCart& lhs, const ShoppingCart& rhs);
445/// // Return 'true' if the specified 'lhs' and 'rhs' objects do not have
446/// // the same value, and 'false' otherwise. Two 'ShoppingCart' objects
447/// // do not have the same value if they either differ in their number of
448/// // contained items, or if any of the corresponding items, in their
449/// // respective ordered sequences of items, is not the same.
450/// @endcode
451/// Now, we define the implementations methods of the `ShoppingCart` class:
452/// @code
453/// // CREATORS
454/// inline
455/// ShoppingCart::ShoppingCart(bslma::Allocator *basicAllocator)
456/// : d_items(basicAllocator)
457/// {
458/// }
459/// @endcode
460/// Notice that, on construction, we pass the contained `bsl::multiset` object
461/// the allocator supplied to `ShoppingCart` at construction'.
462/// @code
463/// inline
464/// ShoppingCart::ShoppingCart(const ShoppingCart& original,
465/// bslma::Allocator *basicAllocator)
466/// : d_items(original.d_items, basicAllocator)
467/// {
468/// }
469///
470/// // MANIPULATORS
471/// inline
472/// ShoppingCart& ShoppingCart::operator=(const ShoppingCart& rhs)
473/// {
474/// d_items = rhs.d_items;
475/// return *this;
476/// }
477///
478/// inline
479/// void ShoppingCart::addItem(const string& name)
480/// {
481/// BSLS_ASSERT(!name.empty());
482///
483/// d_items.insert(name);
484/// }
485///
486/// inline
487/// size_t ShoppingCart::removeItems(const string& name)
488/// {
489/// BSLS_ASSERT(!name.empty());
490///
491/// return d_items.erase(name);
492/// }
493///
494/// // ACCESSORS
495/// size_t ShoppingCart::count(const string& name) const
496/// {
497/// BSLS_ASSERT(!name.empty());
498///
499/// return d_items.count(name);
500/// }
501///
502/// ShoppingCart::ConstIterator ShoppingCart::begin() const
503/// {
504/// return d_items.begin();
505/// }
506///
507/// ShoppingCart::ConstIterator ShoppingCart::end() const
508/// {
509/// return d_items.end();
510/// }
511///
512/// size_t ShoppingCart::numItems() const
513/// {
514/// return d_items.size();
515/// }
516/// @endcode
517/// Finally, we implement the free operators for `ShoppingCart`:
518/// @code
519/// inline
520/// bool operator==(const ShoppingCart& lhs, const ShoppingCart& rhs)
521/// {
522/// return lhs.d_items == rhs.d_items;
523/// }
524///
525/// inline
526/// bool operator!=(const ShoppingCart& lhs, const ShoppingCart& rhs)
527/// {
528/// return !(lhs == rhs);
529/// }
530/// @endcode
531/// @}
532/** @} */
533/** @} */
534
535/** @addtogroup bsl
536 * @{
537 */
538/** @addtogroup bslstl
539 * @{
540 */
541/** @addtogroup bslstl_multiset
542 * @{
543 */
544
545#include <bslscm_version.h>
546
547#include <bslstl_algorithm.h>
548#include <bslstl_iterator.h>
549#include <bslstl_iteratorutil.h>
550#include <bslstl_pair.h>
551#include <bslstl_ranges.h>
552#include <bslstl_setcomparator.h>
553#include <bslstl_stdexceptutil.h>
554#include <bslstl_treeiterator.h>
555#include <bslstl_treenode.h>
556#include <bslstl_treenodepool.h>
557
558#include <bslalg_rangecompare.h>
559#include <bslalg_rbtreeanchor.h>
560#include <bslalg_rbtreenode.h>
561#include <bslalg_rbtreeutil.h>
562#include <bslalg_swaputil.h>
565
566#include <bslma_isstdallocator.h>
567#include <bslma_bslallocator.h>
569
571#include <bslmf_isconvertible.h>
574#include <bslmf_movableref.h>
575#include <bslmf_typeidentity.h>
576#include <bslmf_util.h> // 'forward(V)'
577
578#include <bsls_assert.h>
580#include <bsls_keyword.h>
581#include <bsls_libraryfeatures.h>
582#include <bsls_performancehint.h>
583#include <bsls_platform.h>
584#include <bsls_types.h>
585#include <bsls_util.h> // 'forward<T>(V)'
586
587#include <functional>
588
589#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
590# include <initializer_list>
591#endif
592
593#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
594#include <bsls_nativestd.h>
595#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
596
597#ifdef BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER
598#include <type_traits> // 'std::is_nothrow_move_assignable'
599#endif
600
601#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
602 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
603# define BSLSTL_MULTISET_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T) \
604 requires ::BloombergLP::bslmf::ContainerCompatibleRange<R, T>
605#else
606# define BSLSTL_MULTISET_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
607#endif
608
609#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
610// clang-format off
611// Include version that can be compiled with C++03
612// Generated on Mon Jan 13 08:31:39 2025
613// Command line: sim_cpp11_features.pl bslstl_multiset.h
614
615# define COMPILING_BSLSTL_MULTISET_H
616# include <bslstl_multiset_cpp03.h>
617# undef COMPILING_BSLSTL_MULTISET_H
618
619// clang-format on
620#else
621
622namespace bsl {
623
624 // ==============
625 // class multiset
626 // ==============
627
628/// This class template implements a value-semantic container type holding
629/// an ordered sequence of possibly duplicate keys (of the template
630/// parameter type, `KEY`).
631///
632/// This class:
633/// * supports a complete set of *value-semantic* operations
634/// - except for BDEX serialization
635/// * is *exception-neutral* (agnostic except for the `at` method)
636/// * is *alias-safe*
637/// * is `const` *thread-safe*
638/// For terminology see @ref bsldoc_glossary .
639///
640/// See @ref bslstl_multiset
641template <class KEY,
642 class COMPARATOR = std::less<KEY>,
643 class ALLOCATOR = bsl::allocator<KEY> >
644class multiset {
645
646 // PRIVATE TYPES
647
648 /// This typedef is an alias for the type of key objects maintained by
649 /// this multiset.
650 typedef const KEY ValueType;
651
652 /// This typedef is an alias for the comparator used internally by this
653 /// multiset.
654 typedef BloombergLP::bslstl::SetComparator<KEY, COMPARATOR> Comparator;
655
656 /// This typedef is an alias for the type of nodes held by the tree (of
657 /// nodes) used to implement this multiset.
658 typedef BloombergLP::bslstl::TreeNode<KEY> Node;
659
660 /// This typedef is an alias for the factory type used to create and
661 /// destroy `Node` objects.
662 typedef BloombergLP::bslstl::TreeNodePool<KEY, ALLOCATOR> NodeFactory;
663
664 /// This typedef is an alias for the allocator traits type associated
665 /// with this container.
667
668 /// This typedef is a convenient alias for the utility associated with
669 /// movable references.
670 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
671
672 /// This class is a wrapper around the comparator and allocator data
673 /// members. It takes advantage of the empty-base optimization (EBO) so
674 /// that if the comparator is stateless, it takes up no space.
675 ///
676 /// TBD: This class should eventually be replaced by the use of a
677 /// general EBO-enabled component that provides a `pair`-like interface
678 /// or a `tuple`.
679 ///
680 /// See @ref bslstl_multiset
681 class DataWrapper : public Comparator {
682
683 // DATA
684 NodeFactory d_pool; // pool of 'Node' objects
685
686 private:
687 // NOT IMPLEMENTED
688 DataWrapper(const DataWrapper&);
689 DataWrapper& operator=(const DataWrapper&);
690
691 public:
692 // CREATORS
693
694 /// Create a data wrapper using a copy of the specified `comparator`
695 /// to order keys and a copy of the specified `basicAllocator` to
696 /// supply memory.
697 explicit DataWrapper(const COMPARATOR& comparator,
698 const ALLOCATOR& basicAllocator);
699
700 /// Create a data wrapper initialized to the contents of the `pool`
701 /// associated with the specified `original` data wrapper. The
702 /// comparator and allocator associated with `original` are
703 /// propagated to the new data wrapper. `original` is left in a
704 /// valid but unspecified state.
705 DataWrapper(BloombergLP::bslmf::MovableRef<DataWrapper> original);
706
707 // MANIPULATORS
708
709 /// Return a reference providing modifiable access to the node
710 /// factory associated with this data wrapper.
711 NodeFactory& nodeFactory();
712
713 // ACCESSORS
714
715 /// Return a reference providing non-modifiable access to the node
716 /// factory associated with this data wrapper.
717 const NodeFactory& nodeFactory() const;
718 };
719
720 // DATA
721 DataWrapper d_compAndAlloc;
722 // comparator and pool of 'Node'
723 // objects
724
725 BloombergLP::bslalg::RbTreeAnchor d_tree; // balanced tree of 'Node'
726 // objects
727
728 public:
729 // PUBLIC TYPES
730 typedef KEY key_type;
731 typedef KEY value_type;
732 typedef COMPARATOR key_compare;
733 typedef COMPARATOR value_compare;
734 typedef ALLOCATOR allocator_type;
737
742
743 typedef BloombergLP::bslstl::TreeIterator<const value_type,
744 Node,
746 typedef BloombergLP::bslstl::TreeIterator<const value_type,
747 Node,
749 typedef bsl::reverse_iterator<iterator> reverse_iterator;
750 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
751
752 private:
753 // PRIVATE MANIPULATORS
754
755 /// Return a reference providing modifiable access to the comparator for
756 /// this multiset.
757 Comparator& comparator();
758
759 /// Return a reference providing modifiable access to the node-allocator
760 /// for this multiset.
761 NodeFactory& nodeFactory();
762
763 /// Efficiently exchange the value, comparator, and allocator of this
764 /// object with the value, comparator, and allocator of the specified
765 /// `other` object. This method provides the no-throw exception-safety
766 /// guarantee, *unless* swapping the (user-supplied) comparator or
767 /// allocator objects can throw.
768 void quickSwapExchangeAllocators(multiset& other);
769
770 /// Efficiently exchange the value and comparator of this object with
771 /// the value and comparator of the specified `other` object. This
772 /// method provides the no-throw exception-safety guarantee, *unless*
773 /// swapping the (user-supplied) comparator objects can throw.
774 ///
775 /// \pre The behavior is undefined unless this object was created with the same
776 /// allocator as `other`.
777 void quickSwapRetainAllocators(multiset& other);
778
779 /// Insert the values between the specified `first` and `last` into an
780 /// initially empty set. If sorted, directly place each value in its
781 /// proper position. If an out of order value is detected, revert to
782 /// normal insertion.
783 template <class INPUT_ITERATOR, class SENTINEL>
784 void constructFromRange(INPUT_ITERATOR first, SENTINEL last);
785
786#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
787 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
788
789 /// Insert the values between the specified `first` and `last` into an
790 /// initially empty set. The specified 'numElements` is used to improve
791 /// performance. If sorted, directly place each value in its proper
792 /// position. If an out of order value is detected, revert to normal insertion.
793 ///
794 /// \pre The behavior is undefined if the iterators support
795 /// the calculation of distance and `numElements` is not the distance
796 /// from `first` to `last`.
797 template <class INPUT_ITERATOR, class SENTINEL>
798 void constructFromRange(INPUT_ITERATOR first,
799 SENTINEL last,
800 size_t numElements);
801#endif
802
803 // Insert the values between `first` and `last` into this map.
804 template <class INPUT_ITERATOR, class SENTINEL>
805 void insertFromRange(INPUT_ITERATOR first,
806 SENTINEL last);
807
808#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
809 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
810
811 /// Insert the values between the specified `first` and `last` into this
812 /// map. The specified `numElements` is used to improve performance.
813 ///
814 /// \pre The behavior is undefined if the iterators support the calculation
815 /// of distance and `numElements` is not the distance from `first` to
816 /// `last`.
817 template <class INPUT_ITERATOR, class SENTINEL>
818 void insertFromRange(INPUT_ITERATOR first,
819 SENTINEL last,
820 size_t numElements);
821#endif
822
823 // PRIVATE ACCESSORS
824
825 /// Return a reference providing non-modifiable access to the comparator
826 /// for this multiset.
827 const Comparator& comparator() const;
828
829 /// Return a reference providing non-modifiable access to the
830 /// node-allocator for this multiset.
831 const NodeFactory& nodeFactory() const;
832
833 public:
834 // CREATORS
835
836 /// Create an empty multiset. Optionally specify a `comparator` used to
837 /// order keys contained in this object. If `comparator` is not
838 /// supplied, a default-constructed object of the (template parameter)
839 /// type `COMPARATOR` is used. Optionally specify the `basicAllocator`
840 /// used to supply memory. If `basicAllocator` is not supplied, a
841 /// default-constructed object of the (template parameter) type
842 /// `ALLOCATOR` is used. If the type `ALLOCATOR` is `bsl::allocator`
843 /// (the default), then `basicAllocator`, if supplied, shall be
844 /// convertible to `bslma::Allocator *`. If the type `ALLOCATOR` is
845 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
846 /// installed default allocator is used.
847 multiset();
848 explicit multiset(const COMPARATOR& comparator,
849 const ALLOCATOR& basicAllocator = ALLOCATOR())
850 : d_compAndAlloc(comparator, basicAllocator)
851 , d_tree()
852 {
853 // The implementation is placed here in the class definition to work
854 // around an AIX compiler bug, where the constructor can fail to
855 // compile because it is unable to find the definition of the default
856 // argument. This occurs when a templatized class wraps around the
857 // container and the comparator is defined after the new class.
858 }
859
860 /// Create an empty multiset that uses the specified `basicAllocator` to
861 /// supply memory. Use a default-constructed object of the (template
862 /// parameter) type `COMPARATOR` to order the keys contained in this multiset.
863 ///
864 /// \note Note that a `bslma::Allocator *` can be supplied for
865 /// `basicAllocator` if the (template parameter) `ALLOCATOR` is
866 /// `bsl::allocator` (the default).
867 explicit multiset(const ALLOCATOR& basicAllocator);
868
869 /// Create a multiset having the same value as the specified `original`
870 /// object. Use a copy of `original.key_comp()` to order the keys
871 /// contained in this multiset. Use the allocator returned by
872 /// 'bsl::allocator_traits<ALLOCATOR>::
873 /// select_on_container_copy_construction(original.get_allocator())' to
874 /// allocate memory. This method requires that the (template parameter)
875 /// type `KEY` be `copy-insertable` into this multiset (see
876 /// {Requirements on `KEY`}).
877 multiset(const multiset& original);
878
879 /// Create a multiset having the same value as that of the specified
880 /// `original` object by moving (in constant time) the contents of
881 /// `original` to the new multiset. Use a copy of `original.key_comp()`
882 /// to order the keys contained in this multiset. The allocator
883 /// associated with `original` is propagated for use in the
884 /// newly-created multiset. `original` is left in a valid but
885 /// unspecified state.
886 multiset(BloombergLP::bslmf::MovableRef<multiset> original); // IMPLICIT
887
888 /// Create a multiset having the same value as the specified `original`
889 /// object that uses the specified `basicAllocator` to supply memory.
890 /// Use a copy of `original.key_comp()` to order the keys contained in
891 /// this multiset. This method requires that the (template parameter)
892 /// type `KEY` be `copy-insertable` into this multiset (see {Requirements on `KEY`}).
893 ///
894 /// \note Note that a `bslma::Allocator *` can be
895 /// supplied for `basicAllocator` if the (template parameter) type
896 /// `ALLOCATOR` is `bsl::allocator` (the default).
897 multiset(const multiset& original,
898 const typename type_identity<ALLOCATOR>::type& basicAllocator);
899
900 /// Create a multiset having the same value as the specified `original`
901 /// object that uses the specified `basicAllocator` to supply memory.
902 /// The contents of `original` are moved (in constant time) to the new
903 /// multiset if `basicAllocator == original.get_allocator()`, and are
904 /// move-inserted (in linear time) using `basicAllocator` otherwise.
905 /// `original` is left in a valid but unspecified state. Use a copy of
906 /// `original.key_comp()` to order the keys contained in this multiset.
907 /// This method requires that the (template parameter) type `KEY` be
908 /// `move-insertable` into this multiset (see {Requirements on `KEY`}).
909 ///
910 /// \note Note that a `bslma::Allocator *` can be supplied for
911 /// `basicAllocator` if the (template parameter) type `ALLOCATOR` is
912 /// `bsl::allocator` (the default).
913 multiset(BloombergLP::bslmf::MovableRef<multiset> original,
914 const typename type_identity<ALLOCATOR>::type& basicAllocator);
915
916 /// Create a multiset, and insert each `value_type` object in the
917 /// sequence starting at the specified `first` element, and ending
918 /// immediately before the specified `last` element. Optionally specify
919 /// a `comparator` used to order keys contained in this object. If
920 /// `comparator` is not supplied, a default-constructed object of the
921 /// (template parameter) type `COMPARATOR` is used. Optionally specify
922 /// a `basicAllocator` used to supply memory. If `basicAllocator` is
923 /// not supplied, a default-constructed object of the (template
924 /// parameter) type `ALLOCATOR` is used. If the type `ALLOCATOR` is
925 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
926 /// installed default allocator is used. If the sequence `first` to
927 /// `last` is ordered according to `comparator`, then this operation has
928 /// `O[N]` complexity, where `N` is the number of elements between
929 /// `first` and `last`, otherwise this operation has `O[N * log(N)]`
930 /// complexity. The (template parameter) type `INPUT_ITERATOR` shall
931 /// meet the requirements of an input iterator defined in the C++11
932 /// standard [24.2.3] providing access to values of a type convertible
933 /// to `value_type`, and `value_type` must be `emplace-constructible`
934 /// from `*i` into this multiset, where `i` is a dereferenceable
935 /// iterator in the range `[first .. last)` (see {Requirements on `KEY`}).
936 ///
937 /// \pre The behavior is undefined unless `first` and `last` refer
938 /// to a sequence of valid values where `first` is at a position at or before `last`.
939 ///
940 /// \note Note that a `bslma::Allocator *` can be supplied for
941 /// `basicAllocator` if the type `ALLOCATOR` is `bsl::allocator` (the
942 /// default).
943 template <class INPUT_ITERATOR>
944 multiset(INPUT_ITERATOR first,
945 INPUT_ITERATOR last,
946 const COMPARATOR& comparator = COMPARATOR(),
947 const ALLOCATOR& basicAllocator = ALLOCATOR());
948 template <class INPUT_ITERATOR>
949 multiset(INPUT_ITERATOR first,
950 INPUT_ITERATOR last,
951 const ALLOCATOR& basicAllocator);
952
953 /// Create a multiset having the (`value_type`) values obtained from the
954 /// specified `range`. Ignore those those objects having a key equivalent
955 /// to that which appears earlier in the sequence. Optionally specify a
956 /// `comparator` used to order key-value pairs contained in this object.
957 /// If `comparator` is not supplied, a default-constructed object of the
958 /// (template parameter) type `COMPARATOR` is used. Optionally specify a
959 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
960 /// supplied, a default-constructed object of the (template parameter) type
961 /// `ALLOCATOR` is used. If the type `ALLOCATOR` is `bsl::allocator`
962 /// (the default), then `basicAllocator`, if supplied, shall be
963 /// convertible to `bslma::Allocator *`. If the type `ALLOCATOR` is
964 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
965 /// installed default allocator is used. If values obtained from `range
966 /// are ordered according to `comparator`, then this operation has `O[N]`
967 /// complexity, where `N` is the number of values in the `range`;
968 /// otherwise, this operation has `O[N * log(N)]` complexity.
969 ///
970 /// \note Note that `RANGE` must meet the requirements of an input range and the values
971 /// from `range` must have a type matching or convertible to `value_type`.
972 template <class RANGE>
977 const COMPARATOR& comparator = COMPARATOR(),
978 const ALLOCATOR& basicAllocator = ALLOCATOR())
979 : d_compAndAlloc(comparator, basicAllocator)
980 , d_tree()
981 {
982 // Defined inline to avoid Windows errors.
983
984#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
985 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
986 if constexpr (ranges::sized_range<RANGE>) {
987 constructFromRange(bsl::ranges::begin(range),
988 bsl::ranges::end (range),
989 bsl::ranges::size (range));
990 } else // ...
991#endif
992 {
993 constructFromRange(bsl::ranges::begin(range),
994 bsl::ranges::end (range));
995 }
996 }
997
998 template <class RANGE>
1002 const ALLOCATOR& basicAllocator)
1003 : d_compAndAlloc(COMPARATOR(), basicAllocator)
1004 , d_tree()
1005 {
1006 // Defined inline to avoid Windows errors.
1007
1009 range,
1010 COMPARATOR(),
1011 nodeFactory().allocator());
1012 quickSwapRetainAllocators(other);
1013 }
1014
1015#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1016 /// Create a multiset and insert each `value_type` object in the
1017 /// specified `values` initializer list. Optionally specify a
1018 /// `comparator` used to order keys contained in this object. If
1019 /// `comparator` is not supplied, a default-constructed object of the
1020 /// (template parameter) type `COMPARATOR` is used. Optionally specify
1021 /// a `basicAllocator` used to supply memory. If `basicAllocator` is
1022 /// not supplied, a default-constructed object of the (template
1023 /// parameter) type `ALLOCATOR` is used. If the type `ALLOCATOR` is
1024 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
1025 /// installed default allocator is used. If `values` is ordered
1026 /// according to `comparator`, then this operation has `O[N]`
1027 /// complexity, where `N` is the number of elements in `values`;
1028 /// otherwise this operation has `O[N * log(N)]` complexity. This
1029 /// method requires that the (template parameter) type `KEY` be
1030 /// `copy-insertable` into this multiset (see {Requirements on `KEY`}).
1031 ///
1032 /// \note Note that a `bslma::Allocator *` can be supplied for
1033 /// `basicAllocator` if the type `ALLOCATOR` is `bsl::allocator` (the
1034 /// default).
1035 multiset(std::initializer_list<KEY> values,
1036 const COMPARATOR& comparator = COMPARATOR(),
1037 const ALLOCATOR& basicAllocator = ALLOCATOR());
1038 multiset(std::initializer_list<KEY> values,
1039 const ALLOCATOR& basicAllocator);
1040#endif
1041
1042 /// Destroy this object.
1043 ~multiset();
1044
1045 // MANIPULATORS
1046
1047 /// Assign to this object the value and comparator of the specified
1048 /// `rhs` object, propagate to this object the allocator of `rhs` if the
1049 /// `ALLOCATOR` type has trait @ref propagate_on_container_copy_assignment ,
1050 /// and return a reference providing modifiable access to this object.
1051 /// If an exception is thrown, `*this` is left in a valid but
1052 /// unspecified state. This method requires that the (template
1053 /// parameter) type `KEY` be `copy-assignable` and `copy-insertable`
1054 /// into this multiset (see {Requirements on `KEY`}).
1055 multiset& operator=(const multiset& rhs);
1056
1057 multiset& operator=(BloombergLP::bslmf::MovableRef<multiset> rhs)
1059 AllocatorTraits::is_always_equal::value
1060 && std::is_nothrow_move_assignable<COMPARATOR>::value);
1061 // Assign to this object the value and comparator of the specified
1062 // 'rhs' object, propagate to this object the allocator of 'rhs' if the
1063 // 'ALLOCATOR' type has trait @ref propagate_on_container_move_assignment ,
1064 // and return a reference providing modifiable access to this object.
1065 // The contents of 'rhs' are moved (in constant time) to this multiset
1066 // if 'get_allocator() == rhs.get_allocator()' (after accounting for
1067 // the aforementioned trait); otherwise, all elements in this multiset
1068 // are either destroyed or move-assigned to and each additional element
1069 // in 'rhs' is move-inserted into this multiset. 'rhs' is left in a
1070 // valid but unspecified state, and if an exception is thrown, '*this'
1071 // is left in a valid but unspecified state. This method requires that
1072 // the (template parameter) type 'KEY' be 'move-assignable' and
1073 // 'move-insertable' into this multiset (see {Requirements on 'KEY'}).
1074
1075#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1076 /// Assign to this object the value resulting from first clearing this
1077 /// multiset and then inserting each `value_type` object in the
1078 /// specified `values` initializer list and return a reference providing
1079 /// modifiable access to this object. This method requires that the
1080 /// (template parameter) type `KEY` be `copy-insertable` into this
1081 /// multiset (see {Requirements on `KEY`}).
1082 multiset& operator=(std::initializer_list<KEY> values);
1083#endif
1084
1085 /// Return an iterator providing modifiable access to the first
1086 /// `value_type` object in the ordered sequence of `value_type` objects
1087 /// maintained by this multiset, or the `end` iterator if this multiset
1088 /// is empty.
1090
1091 /// Return an iterator providing modifiable access to the past-the-end
1092 /// element in the ordered sequence of `value_type` objects maintained
1093 /// by this multiset.
1095
1096 /// Return a reverse iterator providing modifiable access to the last
1097 /// `value_type` object in the ordered sequence of `value_type` objects
1098 /// maintained by this multiset, or `rend` if this multiset is empty.
1100
1101 /// Return a reverse iterator providing modifiable access to the
1102 /// prior-to-the-beginning element in the ordered sequence of
1103 /// `value_type` objects maintained by this multiset.
1105
1106 /// Insert the specified `value` into this multiset. If a range
1107 /// containing elements equivalent to `value` already exists, insert the
1108 /// `value` at the end of that range. Return an iterator referring to
1109 /// the newly inserted `value_type` object. This method requires that
1110 /// the (template parameter) type `KEY` be `copy-insertable` into this
1111 /// multiset (see {Requirements on `KEY`}).
1112 iterator insert(const value_type& value);
1113
1114 /// Insert the specified `value` into this multiset. If a range
1115 /// containing elements equivalent to `value` already exists in this
1116 /// multiset, insert `value` at the end of that range. `value` is left
1117 /// in a valid but unspecified state. Return an iterator referring to
1118 /// the newly inserted `value_type` object in this multiset that is
1119 /// equivalent to `value`. This method requires that the (template
1120 /// parameter) type `KEY` be `move-insertable` into this multiset (see
1121 /// {Requirements on `KEY`}).
1122 iterator insert(BloombergLP::bslmf::MovableRef<value_type> value);
1123
1124 /// Insert the specified `value` into this multiset (in amortized
1125 /// constant time if the specified `hint` is a valid immediate successor
1126 /// to `value`). Return an iterator referring to the newly inserted
1127 /// `value_type` object in this multiset that is equivalent to `value`.
1128 /// If `hint` is not a valid immediate successor to `value`, this
1129 /// operation has `O[log(N)]` complexity, where `N` is the size of this
1130 /// multiset. This method requires that the (template parameter) type
1131 /// `KEY` be `copy-insertable` into this multiset (see {Requirements on `KEY`}).
1132 ///
1133 /// \pre The behavior is undefined unless `hint` is an iterator in
1134 /// the range `[begin() .. end()]` (both endpoints included).
1135 iterator insert(const_iterator hint, const value_type& value);
1136
1137 /// Insert the specified `value` into this multiset (in amortized
1138 /// constant time if the specified `hint` is a valid immediate successor
1139 /// to `value`). `value` is left in a valid but unspecified state.
1140 /// Return an iterator referring to the newly inserted `value_type`
1141 /// object in this multiset that is equivalent to `value`. If `hint` is
1142 /// not a valid immediate successor to `value`, this operation has
1143 /// `O[log(N)]` complexity, where `N` is the size of this multiset.
1144 /// This method requires that the (template parameter) type `KEY` be
1145 /// `move-insertable` into this multiset (see {Requirements on `KEY`}).
1146 ///
1147 /// \pre The behavior is undefined unless `hint` is an iterator in the range
1148 /// `[begin() .. end()]` (both endpoints included).
1150 BloombergLP::bslmf::MovableRef<value_type> value);
1151
1152 /// Insert into this multiset the value of each `value_type` object in
1153 /// the range starting at the specified `first` iterator and ending
1154 /// immediately before the specified `last` iterator. The (template
1155 /// parameter) type `INPUT_ITERATOR` shall meet the requirements of an
1156 /// input iterator defined in the C++11 standard [24.2.3] providing
1157 /// access to values of a type convertible to `value_type`, and
1158 /// `value_type` must be `emplace-constructible` from `*i` into this
1159 /// multiset, where `i` is a dereferenceable iterator in the range
1160 /// `[first .. last)` (see {Requirements on `KEY`}).
1161 ///
1162 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid
1163 /// values where `first` is at a position at or before `last`.
1164 template <class INPUT_ITERATOR>
1165 void insert(INPUT_ITERATOR first, INPUT_ITERATOR last);
1166
1167#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1168 /// Insert into this multiset the value of each `value_type` object in
1169 /// the specified `values` initializer list. This method requires that
1170 /// the (template parameter) type `KEY` be `copy-insertable` into this
1171 /// multiset (see {Requirements on `KEY`}).
1172 void insert(std::initializer_list<KEY> values);
1173#endif
1174
1175 /// Insert into this multiset the value of each `value_type` object in the
1176 /// specified `range` if the key equivalent of that object is not
1177 /// already contained in this map. The (template parameter) type `RANGE`
1178 /// must meet the requirements the C++20 standard [ranges] providing access
1179 /// to values of a type convertible to `value_type`, and `value_type` must
1180 /// be `emplace-constructible` from `*i` into this map, where `i` is a
1181 /// dereferenceable iterator obtained from `range` (see {Requirements on `KEY`}).
1182 ///
1183 /// \pre The behavior is undefined if `range` overlaps this multiset.
1184 template <class RANGE>
1187 {
1188 // Defined inline to avoid Windows errors.
1189
1190#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1191 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1192 if constexpr (ranges::sized_range<RANGE>) {
1193 insertFromRange(bsl::ranges::begin(range),
1194 bsl::ranges::end (range),
1195 bsl::ranges::size (range));
1196 } else // ...
1197#endif
1198 {
1199 insertFromRange(bsl::ranges::begin(range),
1200 bsl::ranges::end (range));
1201 }
1202 }
1203
1204#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1205 /// Insert into this multiset a newly-created `value_type` object,
1206 /// constructed by forwarding `get_allocator()` (if required) and the
1207 /// specified (variable number of) `args` to the corresponding
1208 /// constructor of `value_type`. Return an iterator referring to the
1209 /// newly created and inserted object in this multiset. This method
1210 /// requires that the (template parameter) type `KEY` be
1211 /// `emplace-constructible` from `args` (see {Requirements on `KEY`}).
1212 template <class... Args>
1213 iterator emplace(Args&&... args);
1214
1215 /// Insert into this multiset a newly-created `value_type` object,
1216 /// constructed by forwarding `get_allocator()` (if required) and the
1217 /// specified (variable number of) `args` to the corresponding
1218 /// constructor of `value_type` (in amortized constant time if the
1219 /// specified `hint` is a valid immediate successor to the `value_type`
1220 /// object constructed from `args`). Return an iterator referring to
1221 /// the newly created and inserted object in this multiset. If `hint`
1222 /// is not a valid immediate successor to the `value_type` object
1223 /// implied by `args`, this operation has `O[log(N)]` complexity where
1224 /// `N` is the size of this multiset. This method requires that the
1225 /// (template parameter) type `KEY` be `emplace-constructible` from
1226 /// `args` (see {Requirements on `KEY`}).
1227 ///
1228 /// \pre The behavior is undefined unless `hint` is an iterator in the range `[begin() .. end()]` (both
1229 /// endpoints included).
1230 template <class... Args>
1231 iterator emplace_hint(const_iterator hint, Args&&... args);
1232
1233#endif
1234
1235 /// Remove from this multiset the `value_type` object at the specified
1236 /// `position`, and return an iterator referring to the element
1237 /// immediately following the removed element, or to the past-the-end
1238 /// position if the removed element was the last element in the sequence
1239 /// of elements maintained by this multiset. This method invalidates
1240 /// only iterators and references to the removed element and previously
1241 /// saved values of the `end()` iterator.
1242 ///
1243 /// \pre The behavior is undefined unless `position` refers to a `value_type` object in this multiset.
1244 iterator erase(const_iterator position);
1245
1246 /// Remove from this multiset all `value_type` objects equivalent to the
1247 /// specified `key`, if they exist, and return the number of erased
1248 /// objects; otherwise, if there are no `value_type` objects equivalent
1249 /// to `key`, return 0 with no other effect. This method invalidates
1250 /// only iterators and references to the removed element and previously
1251 /// saved values of the `end()` iterator.
1252 size_type erase(const key_type& key);
1253 template <class t_KEY>
1254 typename enable_if<
1255 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1256 t_KEY>::value &&
1258 iterator>::value &&
1260 const_iterator>::value,
1262 {
1263 // Implemented inline due to Sun CC compilation error.
1264 size_type count = 0;
1265 iterator it = this->lower_bound(key);
1266 while (it != end() && !key_comp()(key, *it)) {
1267 // !(*it > key)
1268 it = erase(it);
1269 count++;
1270 }
1271 return count;
1272 }
1273
1274 /// Remove from this multiset the `value_type` objects starting at the
1275 /// specified `first` position up to, but not including the specified
1276 /// `last` position, and return `last`. This method invalidates only
1277 /// iterators and references to the removed element and previously saved values of the `end()` iterator.
1278 ///
1279 /// \pre The behavior is undefined unless
1280 /// `first` and `last` either refer to elements in this multiset or are
1281 /// the `end` iterator, and the `first` position is at or before the
1282 /// `last` position in the ordered sequence provided by this container.
1284
1286 AllocatorTraits::is_always_equal::value
1287 && bsl::is_nothrow_swappable<COMPARATOR>::value);
1288 // Exchange the value and comparator of this object with those of the
1289 // specified 'other' object; also exchange the allocator of this object
1290 // with that of 'other' if the (template parameter) type 'ALLOCATOR'
1291 // has the @ref propagate_on_container_swap trait, and do not modify
1292 // either allocator otherwise. This method provides the no-throw
1293 // exception-safety guarantee if and only if the (template parameter)
1294 // type 'COMPARATOR' provides a no-throw swap operation, and provides
1295 // the basic exception-safety guarantee otherwise; if an exception is
1296 // thrown, both objects are left in valid but unspecified states. This
1297 // operation has 'O[1]' complexity if either this object was created
1298 // with the same allocator as 'other' or 'ALLOCATOR' has the
1299 // @ref propagate_on_container_swap trait; otherwise, it has 'O[n + m]'
1300 // complexity, where 'n' and 'm' are the number of elements in this
1301 // object and 'other', respectively. Note that this method's support
1302 // for swapping objects created with different allocators when
1303 // 'ALLOCATOR' does not have the @ref propagate_on_container_swap trait is
1304 // a departure from the C++ Standard.
1305
1306 /// Remove all entries from this multiset.
1307 /// \note Note that the multiset is
1308 /// empty after this call, but allocated memory may be retained for
1309 /// future use.
1311
1312 // Turn off complaints about necessarily class-defined methods.
1313 // BDE_VERIFY pragma: push
1314 // BDE_VERIFY pragma: -CD01
1315
1316 /// Return an iterator providing modifiable access to the first
1317 /// `value_type` object in this multiset equivalent to the specified
1318 /// `key`, if such an object exists, and the past-the-end (`end`)
1319 /// iterator otherwise.
1320 ///
1321 /// Note: implemented inline due to Sun CC compilation error.
1322 iterator find(const key_type& key)
1323 {
1324 return iterator(BloombergLP::bslalg::RbTreeUtil::find(
1325 d_tree, this->comparator(), key));
1326 }
1327
1328 /// Return an iterator providing modifiable access to the first
1329 /// `value_type` object in this multiset equivalent to the specified
1330 /// `key`, if such an object exists, and the past-the-end (`end`)
1331 /// iterator otherwise.
1332 ///
1333 /// Note: implemented inline due to Sun CC compilation error.
1334 template <class LOOKUP_KEY>
1335 typename bsl::enable_if<
1336 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1337 LOOKUP_KEY>::value,
1338 iterator>::type
1339 find(const LOOKUP_KEY& key)
1340 {
1341 return iterator(BloombergLP::bslalg::RbTreeUtil::find(
1342 d_tree, this->comparator(), key));
1343 }
1344
1345 /// Return an iterator providing modifiable access to the first (i.e.,
1346 /// ordered least) `value_type` object in this multiset greater-than or
1347 /// equal-to the specified `key`, and the past-the-end iterator if this
1348 /// multiset does not contain a `value_type` object greater-than or equal-to `key`.
1349 ///
1350 /// \note Note that this function returns the *first*
1351 /// position before which a `value_type` object equivalent to `key`
1352 /// could be inserted into the ordered sequence maintained by this
1353 /// multiset, while preserving its ordering.
1354 ///
1355 /// Note: implemented inline due to Sun CC compilation error.
1357 {
1358 return iterator(BloombergLP::bslalg::RbTreeUtil::lowerBound(
1359 d_tree, this->comparator(), key));
1360 }
1361
1362 /// Return an iterator providing modifiable access to the first (i.e.,
1363 /// ordered least) `value_type` object in this multiset greater-than or
1364 /// equal-to the specified `key`, and the past-the-end iterator if this
1365 /// multiset does not contain a `value_type` object greater-than or equal-to `key`.
1366 ///
1367 /// \note Note that this function returns the *first*
1368 /// position before which a `value_type` object equivalent to `key`
1369 /// could be inserted into the ordered sequence maintained by this
1370 /// multiset, while preserving its ordering.
1371 ///
1372 /// Note: implemented inline due to Sun CC compilation error.
1373 template <class LOOKUP_KEY>
1374 typename bsl::enable_if<
1375 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1376 LOOKUP_KEY>::value,
1377 iterator>::type
1378 lower_bound(const LOOKUP_KEY& key)
1379 {
1380 return iterator(BloombergLP::bslalg::RbTreeUtil::lowerBound(
1381 d_tree, this->comparator(), key));
1382 }
1383
1384 /// Return an iterator providing modifiable access to the first (i.e.,
1385 /// ordered least) `value_type` object in this multiset greater than the
1386 /// specified `key`, and the past-the-end iterator if this multiset does
1387 /// not contain a `value_type` object greater-than `key`.
1388 ///
1389 /// \note Note that this function returns the *last* position before which a
1390 /// `value_type` object equivalent to `key` could be inserted into the
1391 /// ordered sequence maintained by this multiset, while preserving its
1392 /// ordering.
1393 ///
1394 /// Note: implemented inline due to Sun CC compilation error.
1396 {
1397 return iterator(BloombergLP::bslalg::RbTreeUtil::upperBound(
1398 d_tree, this->comparator(), key));
1399 }
1400
1401 /// Return an iterator providing modifiable access to the first (i.e.,
1402 /// ordered least) `value_type` object in this multiset greater than the
1403 /// specified `key`, and the past-the-end iterator if this multiset does
1404 /// not contain a `value_type` object greater-than `key`.
1405 ///
1406 /// \note Note that this function returns the *last* position before which a
1407 /// `value_type` object equivalent to `key` could be inserted into the
1408 /// ordered sequence maintained by this multiset, while preserving its
1409 /// ordering.
1410 ///
1411 /// Note: implemented inline due to Sun CC compilation error.
1412 template <class LOOKUP_KEY>
1413 typename bsl::enable_if<
1414 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1415 LOOKUP_KEY>::value,
1416 iterator>::type
1417 upper_bound(const LOOKUP_KEY& key)
1418 {
1419 return iterator(BloombergLP::bslalg::RbTreeUtil::upperBound(
1420 d_tree, this->comparator(), key));
1421 }
1422
1423 /// Return a pair of iterators providing modifiable access to the
1424 /// sequence of `value_type` objects in this multiset equivalent to the
1425 /// specified `key`, where the first iterator is positioned at the start
1426 /// of the sequence and the second is positioned one past the end of the
1427 /// sequence. The first returned iterator will be `lower_bound(key)`,
1428 /// the second returned iterator will be `upper_bound(key)`, and, if
1429 /// this multiset contains no `value_type` objects with an equivalent
1430 /// key, then the two returned iterators will have the same value.
1431 ///
1432 /// Note: implemented inline due to Sun CC compilation error.
1434 {
1435 iterator startIt = lower_bound(key);
1436 iterator endIt = startIt;
1437
1438 if (endIt != end() && !comparator()(key, *endIt.node())) {
1439 endIt = upper_bound(key);
1440 }
1441 return pair<iterator, iterator>(startIt, endIt);
1442 }
1443
1444 /// Return a pair of iterators providing modifiable access to the
1445 /// sequence of `value_type` objects in this multiset equivalent to the
1446 /// specified `key`, where the first iterator is positioned at the start
1447 /// of the sequence and the second is positioned one past the end of the
1448 /// sequence. The first returned iterator will be `lower_bound(key)`,
1449 /// the second returned iterator will be `upper_bound(key)`, and, if
1450 /// this multiset contains no `value_type` objects with an equivalent
1451 /// key, then the two returned iterators will have the same value.
1452 ///
1453 /// Note: implemented inline due to Sun CC compilation error.
1454 template <class LOOKUP_KEY>
1455 typename bsl::enable_if<
1456 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1457 LOOKUP_KEY>::value,
1459 equal_range(const LOOKUP_KEY& key)
1460 {
1461 iterator startIt = lower_bound(key);
1462 iterator endIt = startIt;
1463 if (endIt != end() && !comparator()(key, *endIt.node())) {
1464 endIt = upper_bound(key);
1465 }
1466 return pair<iterator, iterator>(startIt, endIt);
1467 }
1468
1469 // BDE_VERIFY pragma: pop
1470
1471 // ACCESSORS
1472
1473 /// Return (a copy of) the allocator used for memory allocation by this
1474 /// multiset.
1476
1477 /// Return an iterator providing non-modifiable access to the first
1478 /// `value_type` object in the ordered sequence of `value_type` objects
1479 /// maintained by this multiset, or the `end` iterator if this multiset
1480 /// is empty.
1482
1483 /// Return an iterator providing non-modifiable access to the
1484 /// past-the-end element in the ordered sequence of `value_type` objects
1485 /// maintained by this multiset.
1487
1488 /// Return a reverse iterator providing non-modifiable access to the
1489 /// last `value_type` object in the ordered sequence of `value_type`
1490 /// objects maintained by this multiset, or `rend` if this multiset is
1491 /// empty.
1493
1494 /// Return a reverse iterator providing non-modifiable access to the
1495 /// prior-to-the-beginning element in the ordered sequence of
1496 /// `value_type` objects maintained by this multiset.
1498
1499 /// Return an iterator providing non-modifiable access to the first
1500 /// `value_type` object in the ordered sequence of `value_type` objects
1501 /// maintained by this multiset, or the `end` iterator if this multiset
1502 /// is empty.
1504
1505 /// Return an iterator providing non-modifiable access to the
1506 /// past-the-end element in the ordered sequence of `value_type` objects
1507 /// maintained by this multiset.
1509
1510 /// Return a reverse iterator providing non-modifiable access to the
1511 /// last `value_type` object in the ordered sequence of `value_type`
1512 /// objects maintained by this multiset, or `rend` if this multiset is
1513 /// empty.
1515
1516 /// Return a reverse iterator providing non-modifiable access to the
1517 /// prior-to-the-beginning element in the ordered sequence of
1518 /// `value_type` objects maintained by this multiset.
1520
1521 /// Return `true` if this map contains an element whose key is
1522 /// equivalent to the specified `key`.
1523 bool contains(const key_type &key) const;
1524
1525 /// Return `true` if this map contains an element whose key is
1526 /// equivalent to the specified `key`.
1527 ///
1528 /// Note: implemented inline due to Sun CC compilation error
1529 template <class LOOKUP_KEY>
1530 typename bsl::enable_if<
1531 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1532 LOOKUP_KEY>::value,
1533 bool>::type
1534 contains(const LOOKUP_KEY& key) const
1535 {
1536 return find(key) != end();
1537 }
1538
1539 /// Return `true` if this multiset contains no elements, and `false`
1540 /// otherwise.
1541 bool empty() const BSLS_KEYWORD_NOEXCEPT;
1542
1543 /// Return the number of elements in this multiset.
1545
1546 /// Return a theoretical upper bound on the largest number of elements that this multiset could possibly hold.
1547 ///
1548 /// \note Note that there is no
1549 /// guarantee that the multiset can successfully grow to the returned
1550 /// size, or even close to that size without running out of resources.
1552
1553 /// Return the key-comparison functor (or function pointer) used by this
1554 /// multiset; if a comparator was supplied at construction, return its
1555 /// value, otherwise return a default constructed @ref key_compare object.
1556 ///
1557 /// \note Note that this comparator compares objects of type `KEY`, which is
1558 /// the type of the `value_type` objects contained in this multiset.
1559 key_compare key_comp() const;
1560
1561 /// Return a functor for comparing two `value_type` objects using `key_comp()`.
1562 ///
1563 /// \note Note that since `value_type` is an alias to `KEY` for
1564 /// `multiset`, this method returns the same functor as `key_comp()`.
1565 value_compare value_comp() const;
1566
1567 // Turn off complaints about necessarily class-defined methods.
1568 // BDE_VERIFY pragma: push
1569 // BDE_VERIFY pragma: -CD01
1570
1571 /// Return an iterator providing non-modifiable access to the first
1572 /// `value_type` object that is equivalent to the specified `key` in
1573 /// ordered sequence maintained by this multiset, if such an object
1574 /// exists, and the past-the-end (`end`) iterator otherwise.
1575 ///
1576 /// Note: implemented inline due to Sun CC compilation error.
1577 const_iterator find(const key_type& key) const
1578 {
1579 return const_iterator(BloombergLP::bslalg::RbTreeUtil::find(
1580 d_tree, this->comparator(), key));
1581 }
1582
1583 /// Return an iterator providing non-modifiable access to the first
1584 /// `value_type` object that is equivalent to the specified `key` in
1585 /// ordered sequence maintained by this multiset, if such an object
1586 /// exists, and the past-the-end (`end`) iterator otherwise.
1587 ///
1588 /// Note: implemented inline due to Sun CC compilation error.
1589 template <class LOOKUP_KEY>
1590 typename bsl::enable_if<
1591 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1592 LOOKUP_KEY>::value,
1593 const_iterator>::type
1594 find(const LOOKUP_KEY& key) const
1595 {
1596 return const_iterator(BloombergLP::bslalg::RbTreeUtil::find(
1597 d_tree, this->comparator(), key));
1598 }
1599
1600 /// Return the number of `value_type` objects within this multiset that
1601 /// are equivalent to the specified `key`.
1602 ///
1603 /// Note: implemented inline due to Sun CC compilation error.
1604 size_type count(const key_type& key) const
1605 {
1606 int count = 0;
1607 const_iterator it = lower_bound(key);
1608
1609 while (it != end() && !comparator()(key, *it.node())) {
1610 ++it;
1611 ++count;
1612 }
1613 return count;
1614 }
1615
1616 /// Return the number of `value_type` objects within this multiset that
1617 /// are equivalent to the specified `key`.
1618 ///
1619 /// Note: implemented inline due to Sun CC compilation error.
1620 template <class LOOKUP_KEY>
1621 typename bsl::enable_if<
1622 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1623 LOOKUP_KEY>::value,
1624 size_type>::type
1625 count(const LOOKUP_KEY& key) const
1626 {
1627 int count = 0;
1628 const_iterator it = lower_bound(key);
1629
1630 while (it != end() && !comparator()(key, *it.node())) {
1631 ++it;
1632 ++count;
1633 }
1634 return count;
1635 }
1636
1637 /// Return an iterator providing non-modifiable access to the first
1638 /// (i.e., ordered least) `value_type` object in this multiset
1639 /// greater-than or equal-to the specified `key`, and the past-the-end
1640 /// iterator if this multiset does not contain a `value_type` greater-than or equal-to `key`.
1641 ///
1642 /// \note Note that this function returns the
1643 /// *first* position before which a `value_type` object equivalent to
1644 /// `key` could be inserted into the ordered sequence maintained by this
1645 /// multiset, while preserving its ordering.
1646 ///
1647 /// Note: implemented inline due to Sun CC compilation error.
1649 {
1650 return iterator(BloombergLP::bslalg::RbTreeUtil::lowerBound(
1651 d_tree, this->comparator(), key));
1652 }
1653
1654 /// Return an iterator providing non-modifiable access to the first
1655 /// (i.e., ordered least) `value_type` object in this multiset
1656 /// greater-than or equal-to the specified `key`, and the past-the-end
1657 /// iterator if this multiset does not contain a `value_type` greater-than or equal-to `key`.
1658 ///
1659 /// \note Note that this function returns the
1660 /// *first* position before which a `value_type` object equivalent to
1661 /// `key` could be inserted into the ordered sequence maintained by this
1662 /// multiset, while preserving its ordering.
1663 ///
1664 /// Note: implemented inline due to Sun CC compilation error.
1665 template <class LOOKUP_KEY>
1666 typename bsl::enable_if<
1667 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1668 LOOKUP_KEY>::value,
1669 const_iterator>::type
1670 lower_bound(const LOOKUP_KEY& key) const
1671 {
1672 return const_iterator(BloombergLP::bslalg::RbTreeUtil::lowerBound(
1673 d_tree, this->comparator(), key));
1674 }
1675
1676 /// Return an iterator providing non-modifiable access to the first
1677 /// (i.e., ordered least) `value_type` object in this multiset greater
1678 /// than the specified `key`, and the past-the-end iterator if this
1679 /// multiset does not contain a `value_type` object greater-than `key`.
1680 ///
1681 /// \note Note that this function returns the *last* position before which a
1682 /// `value_type` object equivalent to `key` could be inserted into the
1683 /// ordered sequence maintained by this multiset, while preserving its
1684 /// ordering.
1685 ///
1686 /// Note: implemented inline due to Sun CC compilation error.
1688 {
1689 return const_iterator(BloombergLP::bslalg::RbTreeUtil::upperBound(
1690 d_tree, this->comparator(), key));
1691 }
1692
1693 /// Return an iterator providing non-modifiable access to the first
1694 /// (i.e., ordered least) `value_type` object in this multiset greater
1695 /// than the specified `key`, and the past-the-end iterator if this
1696 /// multiset does not contain a `value_type` object greater-than `key`.
1697 ///
1698 /// \note Note that this function returns the *last* position before which a
1699 /// `value_type` object equivalent to `key` could be inserted into the
1700 /// ordered sequence maintained by this multiset, while preserving its
1701 /// ordering.
1702 ///
1703 /// Note: implemented inline due to Sun CC compilation error.
1704 template <class LOOKUP_KEY>
1705 typename bsl::enable_if<
1706 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1707 LOOKUP_KEY>::value,
1708 const_iterator>::type
1709 upper_bound(const LOOKUP_KEY& key) const
1710 {
1711 return const_iterator(BloombergLP::bslalg::RbTreeUtil::upperBound(
1712 d_tree, this->comparator(), key));
1713 }
1714
1715 /// Return a pair of iterators providing non-modifiable access to the
1716 /// sequence of `value_type` objects in this multiset that are
1717 /// equivalent to the specified `key`, where the first iterator is
1718 /// positioned at the start of the sequence, and the second is
1719 /// positioned one past the end of the sequence. The first returned
1720 /// iterator will be `lower_bound(key)`; the second returned iterator
1721 /// will be `upper_bound(key)`; and, if this multiset contains no
1722 /// `value_type` objects equivalent to `key`, then the two returned
1723 /// iterators will have the same value.
1724 ///
1725 /// Note: implemented inline due to Sun CC compilation error.
1727 {
1728 const_iterator startIt = lower_bound(key);
1729 const_iterator endIt = startIt;
1730
1731 if (endIt != end() && !comparator()(key, *endIt.node())) {
1732 endIt = upper_bound(key);
1733 }
1734 return pair<const_iterator, const_iterator>(startIt, endIt);
1735 }
1736
1737 /// Return a pair of iterators providing non-modifiable access to the
1738 /// sequence of `value_type` objects in this multiset that are
1739 /// equivalent to the specified `key`, where the first iterator is
1740 /// positioned at the start of the sequence, and the second is
1741 /// positioned one past the end of the sequence. The first returned
1742 /// iterator will be `lower_bound(key)`; the second returned iterator
1743 /// will be `upper_bound(key)`; and, if this multiset contains no
1744 /// `value_type` objects equivalent to `key`, then the two returned
1745 /// iterators will have the same value.
1746 ///
1747 /// Note: implemented inline due to Sun CC compilation error.
1748 template <class LOOKUP_KEY>
1749 typename bsl::enable_if<
1750 BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,
1751 LOOKUP_KEY>::value,
1753 equal_range(const LOOKUP_KEY& key) const
1754 {
1755 const_iterator startIt = lower_bound(key);
1756 const_iterator endIt = startIt;
1757 if (endIt != end() && !comparator()(key, *endIt.node())) {
1758 endIt = upper_bound(key);
1759 }
1760 return pair<const_iterator, const_iterator>(startIt, endIt);
1761 }
1762
1763 // BDE_VERIFY pragma: pop
1764};
1765
1766#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1767// CLASS TEMPLATE DEDUCTION GUIDES
1768
1769/// Deduce the template parameter `KEY` from the `value_type` of the
1770/// iterators supplied to the constructor of `multiset`. Deduce the
1771/// template parameters `COMPARATOR` and `ALLOCATOR` from the other
1772/// parameters passed to the constructor. This guide does not participate
1773/// unless the supplied (or defaulted) `ALLOCATOR` meets the requirements of
1774/// a standard allocator.
1775template <
1776 class INPUT_ITERATOR,
1777 class KEY =
1778 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR>,
1779 class COMPARATOR = std::less<KEY>,
1780 class ALLOCATOR = bsl::allocator<KEY>,
1781 class = bsl::enable_if_t<!bsl::IsStdAllocator_v<COMPARATOR>>,
1782 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1783 >
1784multiset(INPUT_ITERATOR,
1785 INPUT_ITERATOR,
1786 COMPARATOR = COMPARATOR(),
1787 ALLOCATOR = ALLOCATOR())
1788-> multiset<KEY, COMPARATOR, ALLOCATOR>;
1789
1790/// Deduce the template parameter `KEY` from the `value_type` of the
1791/// iterators supplied to the constructor of `multiset`. Deduce the
1792/// template parameter `COMPARATOR` from the other parameter passed to the
1793/// constructor. This deduction guide does not participate unless the
1794/// specified `ALLOC` is convertible to `bsl::allocator<KEY>`.
1795template <
1796 class INPUT_ITERATOR,
1797 class COMPARATOR,
1798 class ALLOC,
1799 class KEY =
1800 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR>,
1801 class DEFAULT_ALLOCATOR = bsl::allocator<KEY>,
1802 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1803 >
1804multiset(INPUT_ITERATOR, INPUT_ITERATOR, COMPARATOR, ALLOC *)
1805-> multiset<KEY, COMPARATOR>;
1806
1807/// Deduce the template parameter `KEY` from the `value_type` of the
1808/// iterators supplied to the constructor of `multiset`. Deduce the
1809/// template parameter `ALLOCATOR` from the other parameter passed to the
1810/// constructor. This deduction guide does not participate unless the
1811/// supplied allocator meets the requirements of a standard allocator.
1812template <
1813 class INPUT_ITERATOR,
1814 class ALLOCATOR,
1815 class KEY =
1816 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR>,
1817 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1818 >
1819multiset(INPUT_ITERATOR, INPUT_ITERATOR, ALLOCATOR)
1820-> multiset<KEY, std::less<KEY>, ALLOCATOR>;
1821
1822/// Deduce the template parameter `KEY` from the `value_type` of the
1823/// iterators supplied to the constructor of `multiset`. This deduction
1824/// guide does not participate unless the specified `ALLOC` is convertible
1825/// to `bsl::allocator<KEY>`.
1826template <
1827 class INPUT_ITERATOR,
1828 class ALLOC,
1829 class KEY =
1830 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR>,
1831 class DEFAULT_ALLOCATOR = bsl::allocator<KEY>,
1832 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1833 >
1834multiset(INPUT_ITERATOR, INPUT_ITERATOR, ALLOC *)
1835-> multiset<KEY>;
1836
1837/// Deduce the template parameter `KEY` from the `value_type` of the
1838/// initializer_list supplied to the constructor of `multiset`. Deduce the
1839/// template parameters `COMPARATOR` and `ALLOCATOR` from the other
1840/// parameters passed to the constructor.
1841template <
1842 class KEY,
1843 class COMPARATOR = std::less<KEY>,
1844 class ALLOCATOR = bsl::allocator<KEY>,
1845 class = bsl::enable_if_t<!bsl::IsStdAllocator_v<COMPARATOR>>,
1846 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1847 >
1848multiset(std::initializer_list<KEY>,
1849 COMPARATOR = COMPARATOR(),
1850 ALLOCATOR = ALLOCATOR())
1851-> multiset<KEY, COMPARATOR, ALLOCATOR>;
1852
1853/// Deduce the template parameter `KEY` from the `value_type` of the
1854/// initializer_list supplied to the constructor of `multiset`. Deduce the
1855/// template parameter `COMPARATOR` from the other parameter passed to the
1856/// constructor. This deduction guide does not participate unless the
1857/// specified `ALLOC` is convertible to `bsl::allocator<KEY>`.
1858template <
1859 class KEY,
1860 class COMPARATOR,
1861 class ALLOC,
1862 class DEFAULT_ALLOCATOR = bsl::allocator<KEY>,
1863 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1864 >
1865multiset(std::initializer_list<KEY>, COMPARATOR, ALLOC *)
1866-> multiset<KEY, COMPARATOR>;
1867
1868/// Deduce the template parameter `KEY` from the `value_type` of the
1869/// initializer_list supplied to the constructor of `multiset`. Deduce the
1870/// template parameter `ALLOCATOR` from the other parameter passed to the
1871/// constructor.
1872template <
1873 class KEY,
1874 class ALLOCATOR,
1875 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
1876 >
1877multiset(std::initializer_list<KEY>, ALLOCATOR)
1878-> multiset<KEY, std::less<KEY>, ALLOCATOR>;
1879
1880/// Deduce the template parameter `KEY` from the `value_type` of the
1881/// initializer_list supplied to the constructor of `multiset`. This
1882/// deduction guide does not participate unless the specified `ALLOC` is
1883/// convertible to `bsl::allocator<KEY>`.
1884template <
1885 class KEY,
1886 class ALLOC,
1887 class DEFAULT_ALLOCATOR = bsl::allocator<KEY>,
1888 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1889 >
1890multiset(std::initializer_list<KEY>, ALLOC *)
1891-> multiset<KEY>;
1892
1893#endif
1894
1895// FREE OPERATORS
1896
1897/// Return `true` if the specified `lhs` and `rhs` objects have the same
1898/// value, and `false` otherwise. Two `multiset` objects `lhs` and `rhs`
1899/// have the same value if they have the same number of keys, and each
1900/// element in the ordered sequence of keys of `lhs` has the same value as
1901/// the corresponding element in the ordered sequence of keys of `rhs`.
1902/// This method requires that the (template parameter) type `KEY` be
1903/// `equality-comparable` (see {Requirements on `KEY`}).
1904template <class KEY, class COMPARATOR, class ALLOCATOR>
1905bool operator==(const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
1906 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs);
1907
1908#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
1909template <class KEY, class COMPARATOR, class ALLOCATOR>
1910bool operator!=(const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
1911 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs);
1912 // Return 'true' if the specified 'lhs' and 'rhs' objects do not have the
1913 // same value, and 'false' otherwise. Two 'multiset' objects 'lhs' and
1914 // 'rhs' do not have the same value if they do not have the same number of
1915 // keys, or some element in the ordered sequence of keys of 'lhs' does not
1916 // have the same value as the corresponding element in the ordered sequence
1917 // of keys of 'rhs'. This method requires that the (template parameter)
1918 // type 'KEY' be 'equality-comparable' (see {Requirements on 'KEY'}).
1919#endif
1920
1921#ifdef BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
1922
1923/// Perform a lexicographic three-way comparison of the specified `lhs` and
1924/// the specified `rhs` multisets by using the comparison operators of `KEY`
1925/// on each element; return the result of that comparison.
1926template <class KEY, class COMPARATOR, class ALLOCATOR>
1927BloombergLP::bslalg::SynthThreeWayUtil::Result<KEY>
1928operator<=>(const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
1929 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs);
1930
1931#else
1932
1933template <class KEY, class COMPARATOR, class ALLOCATOR>
1934bool operator< (const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
1935 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs);
1936 // Return 'true' if the value of the specified 'lhs' multiset is
1937 // lexicographically less than that of the specified 'rhs' multiset, and
1938 // 'false' otherwise. Given iterators 'i' and 'j' over the respective
1939 // sequences '[lhs.begin() .. lhs.end())' and '[rhs.begin() .. rhs.end())',
1940 // the value of multiset 'lhs' is lexicographically less than that of
1941 // multiset 'rhs' if 'true == *i < *j' for the first pair of corresponding
1942 // iterator positions where '*i < *j' and '*j < *i' are not both 'false'.
1943 // If no such corresponding iterator position exists, the value of 'lhs' is
1944 // lexicographically less than that of 'rhs' if 'lhs.size() < rhs.size()'.
1945 // This method requires that 'operator<', inducing a total order, be
1946 // defined for 'value_type'.
1947
1948template <class KEY, class COMPARATOR, class ALLOCATOR>
1949bool operator> (const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
1950 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs);
1951 // Return 'true' if the value of the specified 'lhs' multiset is
1952 // lexicographically greater than that of the specified 'rhs' multiset, and
1953 // 'false' otherwise. The value of multiset 'lhs' is lexicographically
1954 // greater than that of multiset 'rhs' if 'rhs' is lexicographically less
1955 // than 'lhs' (see 'operator<'). This method requires that 'operator<',
1956 // inducing a total order, be defined for 'value_type'. Note that this
1957 // operator returns 'rhs < lhs'.
1958
1959template <class KEY, class COMPARATOR, class ALLOCATOR>
1960bool operator<=(const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
1961 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs);
1962 // Return 'true' if the value of the specified 'lhs' multiset is
1963 // lexicographically less than or equal to that of the specified 'rhs'
1964 // multiset, and 'false' otherwise. The value of multiset 'lhs' is
1965 // lexicographically less than or equal to that of multiset 'rhs' if 'rhs'
1966 // is not lexicographically less than 'lhs' (see 'operator<'). This method
1967 // requires that 'operator<', inducing a total order, be defined for
1968 // 'value_type'. Note that this operator returns '!(rhs < lhs)'.
1969
1970template <class KEY, class COMPARATOR, class ALLOCATOR>
1971bool operator>=(const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
1972 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs);
1973 // Return 'true' if the value of the specified 'lhs' multiset is
1974 // lexicographically greater than or equal to that of the specified 'rhs'
1975 // multiset, and 'false' otherwise. The value of multiset 'lhs' is
1976 // lexicographically greater than or equal to that of multiset 'rhs' if
1977 // 'lhs' is not lexicographically less than 'rhs' (see 'operator<'). This
1978 // method requires that 'operator<', inducing a total order, be defined for
1979 // 'value_type'. Note that this operator returns '!(lhs < rhs)'.
1980
1981#endif // BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
1982
1983// FREE FUNCTIONS
1984
1985/// Erase all the elements in the specified multiset `ms` that satisfy the
1986/// specified predicate `predicate`. Return the number of elements erased.
1987template <class KEY, class COMPARATOR, class ALLOCATOR, class PREDICATE>
1988typename multiset<KEY, COMPARATOR, ALLOCATOR>::size_type
1989erase_if(multiset<KEY, COMPARATOR, ALLOCATOR>& ms, PREDICATE predicate);
1990
1991template <class KEY, class COMPARATOR, class ALLOCATOR>
1992void swap(multiset<KEY, COMPARATOR, ALLOCATOR>& a,
1993 multiset<KEY, COMPARATOR, ALLOCATOR>& b)
1995 BSLS_KEYWORD_NOEXCEPT_OPERATOR(a.swap(b)));
1996 // Exchange the value and comparator of the specified 'a' object with those
1997 // of the specified 'b' object; also exchange the allocator of 'a' with
1998 // that of 'b' if the (template parameter) type 'ALLOCATOR' has the
1999 // @ref propagate_on_container_swap trait, and do not modify either allocator
2000 // otherwise. This function provides the no-throw exception-safety
2001 // guarantee if and only if the (template parameter) type 'COMPARATOR'
2002 // provides a no-throw swap operation, and provides the basic
2003 // exception-safety guarantee otherwise; if an exception is thrown, both
2004 // objects are left in valid but unspecified states. This operation has
2005 // 'O[1]' complexity if either 'a' was created with the same allocator as
2006 // 'b' or 'ALLOCATOR' has the @ref propagate_on_container_swap trait;
2007 // otherwise, it has 'O[n + m]' complexity, where 'n' and 'm' are the
2008 // number of elements in 'a' and 'b', respectively. Note that this
2009 // function's support for swapping objects created with different
2010 // allocators when 'ALLOCATOR' does not have the
2011 // @ref propagate_on_container_swap trait is a departure from the C++
2012 // Standard.
2013
2014// ============================================================================
2015// TEMPLATE AND INLINE FUNCTION DEFINITIONS
2016// ============================================================================
2017
2018 // -----------------
2019 // class DataWrapper
2020 // -----------------
2021
2022// CREATORS
2023template <class KEY, class COMPARATOR, class ALLOCATOR>
2024inline
2025multiset<KEY, COMPARATOR, ALLOCATOR>::DataWrapper::DataWrapper(
2026 const COMPARATOR& comparator,
2027 const ALLOCATOR& basicAllocator)
2028: ::bsl::multiset<KEY, COMPARATOR, ALLOCATOR>::Comparator(comparator)
2029, d_pool(basicAllocator)
2030{
2031}
2032
2033template <class KEY, class COMPARATOR, class ALLOCATOR>
2034inline
2035multiset<KEY, COMPARATOR, ALLOCATOR>::DataWrapper::DataWrapper(
2036 BloombergLP::bslmf::MovableRef<DataWrapper> original)
2037: ::bsl::multiset<KEY, COMPARATOR, ALLOCATOR>::Comparator(
2038 MoveUtil::access(original).keyComparator())
2039, d_pool(MoveUtil::move(MoveUtil::access(original).d_pool))
2040{
2041}
2042
2043// MANIPULATORS
2044template <class KEY, class COMPARATOR, class ALLOCATOR>
2045inline
2046typename multiset<KEY, COMPARATOR, ALLOCATOR>::NodeFactory&
2047multiset<KEY, COMPARATOR, ALLOCATOR>::DataWrapper::nodeFactory()
2048{
2049 return d_pool;
2050}
2051
2052// ACCESSORS
2053template <class KEY, class COMPARATOR, class ALLOCATOR>
2054inline
2055const typename multiset<KEY, COMPARATOR, ALLOCATOR>::NodeFactory&
2056multiset<KEY, COMPARATOR, ALLOCATOR>::DataWrapper::nodeFactory() const
2057{
2058 return d_pool;
2059}
2060 // --------------
2061 // class multiset
2062 // --------------
2063
2064// PRIVATE MANIPULATORS
2065template <class KEY, class COMPARATOR, class ALLOCATOR>
2066inline
2067typename multiset<KEY, COMPARATOR, ALLOCATOR>::Comparator&
2068multiset<KEY, COMPARATOR, ALLOCATOR>::comparator()
2069{
2070 return d_compAndAlloc;
2071}
2072
2073template <class KEY, class COMPARATOR, class ALLOCATOR>
2074inline
2075typename multiset<KEY, COMPARATOR, ALLOCATOR>::NodeFactory&
2076multiset<KEY, COMPARATOR, ALLOCATOR>::nodeFactory()
2077{
2078 return d_compAndAlloc.nodeFactory();
2079}
2080
2081template <class KEY, class COMPARATOR, class ALLOCATOR>
2082inline
2083void multiset<KEY, COMPARATOR, ALLOCATOR>::quickSwapExchangeAllocators(
2084 multiset& other)
2085{
2086 BloombergLP::bslalg::RbTreeUtil::swap(&d_tree, &other.d_tree);
2087 nodeFactory().swapExchangeAllocators(other.nodeFactory());
2088
2089 // 'DataWrapper' contains a 'NodeFactory' object and inherits from
2090 // 'Comparator'. If the empty-base-class optimization has been applied to
2091 // 'Comparator', then we must not call 'swap' on it because
2092 // 'sizeof(Comparator) > 0' and, therefore, we will incorrectly swap bytes
2093 // of the 'NodeFactory' members!
2094
2095 if (sizeof(NodeFactory) != sizeof(DataWrapper)) {
2096 comparator().swap(other.comparator());
2097 }
2098}
2099
2100template <class KEY, class COMPARATOR, class ALLOCATOR>
2101inline
2102void multiset<KEY, COMPARATOR, ALLOCATOR>::quickSwapRetainAllocators(
2103 multiset& other)
2104{
2105 BloombergLP::bslalg::RbTreeUtil::swap(&d_tree, &other.d_tree);
2106 nodeFactory().swapRetainAllocators(other.nodeFactory());
2107
2108 // See 'quickSwapExchangeAllocators' (above).
2109
2110 if (sizeof(NodeFactory) != sizeof(DataWrapper)) {
2111 comparator().swap(other.comparator());
2112 }
2113}
2114
2115template <class KEY, class COMPARATOR, class ALLOCATOR>
2116template <class INPUT_ITERATOR, class SENTINEL>
2117inline
2118void
2119multiset<KEY, COMPARATOR, ALLOCATOR>::constructFromRange(INPUT_ITERATOR first,
2120 SENTINEL last)
2121{
2122 if (first == last) {
2123 return; // RETURN
2124 }
2125
2127 BloombergLP::bslstl::IteratorUtil::
2128 canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()) {
2129 const size_type numElements = static_cast<size_type>(
2130 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last));
2131 nodeFactory().reserveNodes(numElements);
2132 }
2133
2134 BloombergLP::bslalg::RbTreeUtilTreeProctor<NodeFactory> proctor(
2135 &d_tree,
2136 &nodeFactory());
2137
2138 // The following loop guarantees amortized linear time to insert an ordered
2139 // sequence of values (as required by the standard). If the values are
2140 // in sorted order, we are guaranteed the next node can be inserted as the
2141 // right child of the previous node, and can call 'insertAt' without
2142 // 'findUniqueInsertLocation'.
2143
2144 insert(*first);
2145 BloombergLP::bslalg::RbTreeNode *prevNode = d_tree.rootNode();
2146
2147 while (++first != last) {
2148
2149 const value_type& value = *first;
2150 if (this->comparator()(value, *prevNode)) {
2151 // The values are not in order, so insert them normally.
2152 insert(value);
2153 insertFromRange(++first, last);
2154 break;
2155 }
2156
2157 if (this->comparator()(*prevNode, value)) {
2158 BloombergLP::bslalg::RbTreeNode *node =
2159 nodeFactory().emplaceIntoNewNode(value);
2160 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2161 prevNode,
2162 false,
2163 node);
2164 prevNode = node;
2165 }
2166 }
2167
2168 proctor.release();
2169}
2170
2171#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
2172 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
2173
2174template <class KEY, class COMPARATOR, class ALLOCATOR>
2175template <class INPUT_ITERATOR, class SENTINEL>
2176inline
2177void multiset<KEY, COMPARATOR, ALLOCATOR>::constructFromRange(
2178 INPUT_ITERATOR first,
2179 SENTINEL last,
2180 size_t numElements)
2181
2182{
2184 !BloombergLP::bslstl::IteratorUtil
2185 ::canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()
2186 || numElements == static_cast<size_type>(
2187 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last))));
2188
2189 if (first == last) {
2190 return; // RETURN
2191 }
2192
2193 if (0 < numElements) {
2194 nodeFactory().reserveNodes(numElements);
2195 }
2196
2197 BloombergLP::bslalg::RbTreeUtilTreeProctor<NodeFactory> proctor(
2198 &d_tree,
2199 &nodeFactory());
2200
2201 // The following loop guarantees amortized linear time to insert an ordered
2202 // sequence of values (as required by the standard). If the values are
2203 // in sorted order, we are guaranteed the next node can be inserted as the
2204 // right child of the previous node, and can call 'insertAt' without
2205 // 'findUniqueInsertLocation'.
2206
2207 insert(*first); --numElements;
2208 BloombergLP::bslalg::RbTreeNode *prevNode = d_tree.rootNode();
2209
2210 while (++first != last) {
2211
2212 const value_type& value = *first;
2213 if (this->comparator()(value, *prevNode)) {
2214 // The values are not in order, so insert them normally.
2215 insert(value); --numElements;
2216 insertFromRange(++first, last, numElements);
2217 break;
2218 }
2219
2220 if (this->comparator()(*prevNode, value)) {
2221 BloombergLP::bslalg::RbTreeNode *node =
2222 nodeFactory().emplaceIntoNewNode(value);
2223 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2224 prevNode,
2225 false,
2226 node);
2227 --numElements;
2228 prevNode = node;
2229 }
2230 }
2231
2232 proctor.release();
2233}
2234
2235#endif
2236
2237template <class KEY, class COMPARATOR, class ALLOCATOR>
2238template <class INPUT_ITERATOR, class SENTINEL>
2239inline
2240void
2241multiset<KEY, COMPARATOR, ALLOCATOR>::insertFromRange(INPUT_ITERATOR first,
2242 SENTINEL last)
2243{
2244 ///Implementation Notes
2245 ///--------------------
2246 // First, consume currently held free nodes. Free nodes may be available
2247 // from previous insertions that where skipped due to collisions with
2248 // keys already in the map or from nodes reserved in `constructFromRange`.
2249 //
2250 // If those nodes are insufficient *and* one can calculate the remaining
2251 // number of elements, then reserve exactly that many free nodes. There is
2252 // no more than one call to 'reserveNodes' per invocation of this method,
2253 // hence the use of 'BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY'.
2254 //
2255 // When reserving nodes, we assume the elements remaining to be inserted
2256 // have unique keys that do not duplicate any keys already in the container
2257 // If there are any duplicates, this container will have free nodes on
2258 // return from this method.
2259
2260 while (first != last) {
2261
2262 if (BloombergLP::bslstl::IteratorUtil
2263 ::canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()
2265 !nodeFactory().hasFreeNodes())) {
2266 nodeFactory().reserveNodes(
2267 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last));
2268 }
2269
2270 insert(*first);
2271 ++first;
2272 }
2273}
2274
2275#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
2276 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
2277
2278template <class KEY, class COMPARATOR, class ALLOCATOR>
2279template <class INPUT_ITERATOR, class SENTINEL>
2280inline
2281void multiset<KEY, COMPARATOR, ALLOCATOR>::insertFromRange(
2282 INPUT_ITERATOR first,
2283 SENTINEL last,
2284 size_t numElements)
2285{
2287 !BloombergLP::bslstl::IteratorUtil
2288 ::canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()
2289 || numElements == static_cast<size_type>(
2290 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last))));
2291
2292 while (first != last) {
2293
2295 !nodeFactory().hasFreeNodes())) {
2296 nodeFactory().reserveNodes(numElements);
2297 }
2298
2299 insert(*first);
2300 --numElements;
2301 ++first;
2302 }
2303}
2304
2305#endif
2306
2307// PRIVATE ACCESSORS
2308template <class KEY, class COMPARATOR, class ALLOCATOR>
2309inline
2310const typename multiset<KEY, COMPARATOR, ALLOCATOR>::Comparator&
2311multiset<KEY, COMPARATOR, ALLOCATOR>::comparator() const
2312{
2313 return d_compAndAlloc;
2314}
2315
2316template <class KEY, class COMPARATOR, class ALLOCATOR>
2317inline
2318const typename multiset<KEY, COMPARATOR, ALLOCATOR>::NodeFactory&
2319multiset<KEY, COMPARATOR, ALLOCATOR>::nodeFactory() const
2320{
2321 return d_compAndAlloc.nodeFactory();
2322}
2323
2324// CREATORS
2325template <class KEY, class COMPARATOR, class ALLOCATOR>
2326inline
2328: d_compAndAlloc(COMPARATOR(), ALLOCATOR())
2329, d_tree()
2330{
2331}
2332
2333template <class KEY, class COMPARATOR, class ALLOCATOR>
2334inline
2336: d_compAndAlloc(COMPARATOR(), basicAllocator)
2337, d_tree()
2338{
2339}
2340
2341template <class KEY, class COMPARATOR, class ALLOCATOR>
2342inline
2344: d_compAndAlloc(original.comparator().keyComparator(),
2345 AllocatorTraits::select_on_container_copy_construction(
2346 original.nodeFactory().allocator()))
2347, d_tree()
2348{
2349 if (0 < original.size()) {
2350 nodeFactory().reserveNodes(original.size());
2351 BloombergLP::bslalg::RbTreeUtil::copyTree(&d_tree,
2352 original.d_tree,
2353 &nodeFactory());
2354 }
2355}
2356
2357template <class KEY, class COMPARATOR, class ALLOCATOR>
2358inline
2360 BloombergLP::bslmf::MovableRef<multiset> original)
2361: d_compAndAlloc(MoveUtil::move(MoveUtil::access(original).d_compAndAlloc))
2362, d_tree()
2363{
2364 multiset& lvalue = original;
2365 BloombergLP::bslalg::RbTreeUtil::swap(&d_tree, &lvalue.d_tree);
2366}
2367
2368template <class KEY, class COMPARATOR, class ALLOCATOR>
2369inline
2371 const typename type_identity<ALLOCATOR>::type& basicAllocator)
2372: d_compAndAlloc(original.comparator().keyComparator(), basicAllocator)
2373, d_tree()
2374{
2375 if (0 < original.size()) {
2376 nodeFactory().reserveNodes(original.size());
2377 BloombergLP::bslalg::RbTreeUtil::copyTree(&d_tree,
2378 original.d_tree,
2379 &nodeFactory());
2380 }
2381}
2382
2383template <class KEY, class COMPARATOR, class ALLOCATOR>
2384inline
2386 BloombergLP::bslmf::MovableRef<multiset> original,
2387 const typename type_identity<ALLOCATOR>::type& basicAllocator)
2388: d_compAndAlloc(MoveUtil::access(original).comparator().keyComparator(),
2389 basicAllocator)
2390, d_tree()
2391{
2392 multiset& lvalue = original;
2393
2395 nodeFactory().allocator() == lvalue.nodeFactory().allocator())) {
2396 d_compAndAlloc.nodeFactory().adopt(
2397 MoveUtil::move(lvalue.d_compAndAlloc.nodeFactory()));
2398 BloombergLP::bslalg::RbTreeUtil::swap(&d_tree, &lvalue.d_tree);
2399 }
2400 else {
2401 if (0 < lvalue.size()) {
2402 nodeFactory().reserveNodes(lvalue.size());
2403 BloombergLP::bslalg::RbTreeUtil::moveTree(&d_tree,
2404 &lvalue.d_tree,
2405 &nodeFactory(),
2406 &lvalue.nodeFactory());
2407 }
2408 }
2409}
2410
2411template <class KEY, class COMPARATOR, class ALLOCATOR>
2412template <class INPUT_ITERATOR>
2413inline
2415 INPUT_ITERATOR first,
2416 INPUT_ITERATOR last,
2417 const COMPARATOR& comparator,
2418 const ALLOCATOR& basicAllocator)
2419: d_compAndAlloc(comparator, basicAllocator)
2420, d_tree()
2421{
2422 if (first != last) {
2423
2424 const size_type numElements = static_cast<size_type>(
2425 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last));
2426
2427 if (0 < numElements) {
2428 nodeFactory().reserveNodes(numElements);
2429 }
2430
2431 BloombergLP::bslalg::RbTreeUtilTreeProctor<NodeFactory> proctor(
2432 &d_tree,
2433 &nodeFactory());
2434
2435 // The following loop guarantees amortized linear time to insert an
2436 // ordered sequence of values (as required by the standard). If the
2437 // values are in sorted order, we are guaranteed the next node can be
2438 // inserted as the right child of the previous node, and can call
2439 // 'insertAt' without 'findUniqueInsertLocation'.
2440
2441 insert(*first);
2442 BloombergLP::bslalg::RbTreeNode *prevNode = d_tree.rootNode();
2443 while (++first != last) {
2444 // The values are not in order, so insert them normally.
2445
2446 const value_type& value = *first;
2447 if (this->comparator()(value, *prevNode)) {
2448 insert(value);
2449 insert(++first, last);
2450 break;
2451 }
2452 BloombergLP::bslalg::RbTreeNode *node =
2453 nodeFactory().emplaceIntoNewNode(value);
2454 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2455 prevNode,
2456 false,
2457 node);
2458 prevNode = node;
2459 }
2460
2461 proctor.release();
2462 }
2463}
2464
2465template <class KEY, class COMPARATOR, class ALLOCATOR>
2466template <class INPUT_ITERATOR>
2467inline
2469 INPUT_ITERATOR first,
2470 INPUT_ITERATOR last,
2471 const ALLOCATOR& basicAllocator)
2472: d_compAndAlloc(COMPARATOR(), basicAllocator)
2473, d_tree()
2474{
2475 if (first != last) {
2476
2477 const size_type numElements = static_cast<size_type>(
2478 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last));
2479
2480 if (0 < numElements) {
2481 nodeFactory().reserveNodes(numElements);
2482 }
2483
2484 BloombergLP::bslalg::RbTreeUtilTreeProctor<NodeFactory> proctor(
2485 &d_tree,
2486 &nodeFactory());
2487
2488 // The following loop guarantees amortized linear time to insert an
2489 // ordered sequence of values (as required by the standard). If the
2490 // values are in sorted order, we are guaranteed the next node can be
2491 // inserted as the right child of the previous node, and can call
2492 // 'insertAt' without 'findUniqueInsertLocation'.
2493
2494 insert(*first);
2495 BloombergLP::bslalg::RbTreeNode *prevNode = d_tree.rootNode();
2496 while (++first != last) {
2497 // The values are not in order, so insert them normally.
2498
2499 const value_type& value = *first;
2500 if (this->comparator()(value, *prevNode)) {
2501 insert(value);
2502 insert(++first, last);
2503 break;
2504 }
2505 BloombergLP::bslalg::RbTreeNode *node =
2506 nodeFactory().emplaceIntoNewNode(value);
2507 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2508 prevNode,
2509 false,
2510 node);
2511 prevNode = node;
2512 }
2513
2514 proctor.release();
2515 }
2516}
2517
2518#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2519template <class KEY, class COMPARATOR, class ALLOCATOR>
2520inline
2522 std::initializer_list<KEY> values,
2523 const COMPARATOR& comparator,
2524 const ALLOCATOR& basicAllocator)
2525: multiset(values.begin(), values.end(), comparator, basicAllocator)
2526{
2527}
2528
2529template <class KEY, class COMPARATOR, class ALLOCATOR>
2530inline
2532 std::initializer_list<KEY> values,
2533 const ALLOCATOR& basicAllocator)
2534: multiset(values.begin(), values.end(), COMPARATOR(), basicAllocator)
2535{
2536}
2537#endif
2538
2539template <class KEY, class COMPARATOR, class ALLOCATOR>
2540inline
2545
2546// MANIPULATORS
2547template <class KEY, class COMPARATOR, class ALLOCATOR>
2548inline
2551{
2553 if (AllocatorTraits::propagate_on_container_copy_assignment::value) {
2554 multiset other(rhs, rhs.nodeFactory().allocator());
2555 quickSwapExchangeAllocators(other);
2556 }
2557 else {
2558 multiset other(rhs, nodeFactory().allocator());
2559 quickSwapRetainAllocators(other);
2560 }
2561 }
2562 return *this;
2563}
2564
2565template <class KEY, class COMPARATOR, class ALLOCATOR>
2566inline
2569 BloombergLP::bslmf::MovableRef<multiset> rhs)
2571 AllocatorTraits::is_always_equal::value
2572 && std::is_nothrow_move_assignable<COMPARATOR>::value)
2573{
2574 multiset& lvalue = rhs;
2575
2576 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &lvalue)) {
2577 if (nodeFactory().allocator() == lvalue.nodeFactory().allocator()) {
2578 multiset other(MoveUtil::move(lvalue));
2579 quickSwapRetainAllocators(other);
2580 }
2581 else if (
2582 AllocatorTraits::propagate_on_container_move_assignment::value) {
2583 multiset other(MoveUtil::move(lvalue));
2584 quickSwapExchangeAllocators(other);
2585 }
2586 else {
2587 multiset other(MoveUtil::move(lvalue), nodeFactory().allocator());
2588 quickSwapRetainAllocators(other);
2589 }
2590 }
2591 return *this;
2592}
2593
2594#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2595template <class KEY, class COMPARATOR, class ALLOCATOR>
2596inline
2597multiset<KEY, COMPARATOR, ALLOCATOR>&
2599 std::initializer_list<KEY> values)
2600{
2601 clear();
2602 insert(values.begin(), values.end());
2603 return *this;
2604}
2605#endif
2606
2607template <class KEY, class COMPARATOR, class ALLOCATOR>
2608inline
2614
2615template <class KEY, class COMPARATOR, class ALLOCATOR>
2616inline
2622
2623template <class KEY, class COMPARATOR, class ALLOCATOR>
2624inline
2630
2631template <class KEY, class COMPARATOR, class ALLOCATOR>
2632inline
2638
2639template <class KEY, class COMPARATOR, class ALLOCATOR>
2640inline
2643{
2644 bool leftChild;
2645
2646 BloombergLP::bslalg::RbTreeNode *insertLocation =
2647 BloombergLP::bslalg::RbTreeUtil::findInsertLocation(&leftChild,
2648 &d_tree,
2649 this->comparator(),
2650 value);
2651
2652 BloombergLP::bslalg::RbTreeNode *node =
2653 nodeFactory().emplaceIntoNewNode(value);
2654
2655 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2656 insertLocation,
2657 leftChild,
2658 node);
2659 return iterator(node);
2660}
2661
2662template <class KEY, class COMPARATOR, class ALLOCATOR>
2663inline
2666 BloombergLP::bslmf::MovableRef<value_type> value)
2667{
2668 value_type& lvalue = value;
2669 bool leftChild;
2670
2671 BloombergLP::bslalg::RbTreeNode *insertLocation =
2672 BloombergLP::bslalg::RbTreeUtil::findInsertLocation(&leftChild,
2673 &d_tree,
2674 this->comparator(),
2675 lvalue);
2676
2677 BloombergLP::bslalg::RbTreeNode *node =
2678 nodeFactory().emplaceIntoNewNode(MoveUtil::move(lvalue));
2679
2680 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2681 insertLocation,
2682 leftChild,
2683 node);
2684 return iterator(node);
2685}
2686
2687template <class KEY, class COMPARATOR, class ALLOCATOR>
2688inline
2691 const value_type& value)
2692{
2693 bool leftChild;
2694
2695 BloombergLP::bslalg::RbTreeNode *hintNode =
2696 const_cast<BloombergLP::bslalg::RbTreeNode *>(hint.node());
2697
2698 BloombergLP::bslalg::RbTreeNode *insertLocation =
2699 BloombergLP::bslalg::RbTreeUtil::findInsertLocation(&leftChild,
2700 &d_tree,
2701 this->comparator(),
2702 value,
2703 hintNode);
2704
2705 BloombergLP::bslalg::RbTreeNode *node =
2706 nodeFactory().emplaceIntoNewNode(value);
2707
2708 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2709 insertLocation,
2710 leftChild,
2711 node);
2712 return iterator(node);
2713}
2714
2715template <class KEY, class COMPARATOR, class ALLOCATOR>
2716inline
2719 const_iterator hint,
2720 BloombergLP::bslmf::MovableRef<value_type> value)
2721{
2722 value_type& lvalue = value;
2723 bool leftChild;
2724
2725 BloombergLP::bslalg::RbTreeNode *hintNode =
2726 const_cast<BloombergLP::bslalg::RbTreeNode *>(hint.node());
2727
2728 BloombergLP::bslalg::RbTreeNode *insertLocation =
2729 BloombergLP::bslalg::RbTreeUtil::findInsertLocation(&leftChild,
2730 &d_tree,
2731 this->comparator(),
2732 lvalue,
2733 hintNode);
2734
2735 BloombergLP::bslalg::RbTreeNode *node =
2736 nodeFactory().emplaceIntoNewNode(MoveUtil::move(lvalue));
2737
2738 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2739 insertLocation,
2740 leftChild,
2741 node);
2742 return iterator(node);
2743}
2744
2745template <class KEY, class COMPARATOR, class ALLOCATOR>
2746template <class INPUT_ITERATOR>
2747inline
2749 INPUT_ITERATOR last)
2750{
2751 ///Implementation Notes
2752 ///--------------------
2753 // First, consume currently held free nodes. If those nodes are
2754 // insufficient *and* one can calculate the remaining number of elements,
2755 // then reserve exactly that many free nodes. There is no more than one
2756 // call to 'reserveNodes' per invocation of this method, hence the use of
2757 // 'BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY'.
2758
2759 while (first != last) {
2760 if (BloombergLP::bslstl::IteratorUtil::
2761 canCalculateInsertDistance<INPUT_ITERATOR,INPUT_ITERATOR>()
2763 !nodeFactory().hasFreeNodes())) {
2764 const size_type numElements = static_cast<size_type>(
2765 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last));
2766
2767 nodeFactory().reserveNodes(numElements);
2768 }
2769 insert(*first);
2770 ++first;
2771 }
2772}
2773
2774#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2775template <class KEY, class COMPARATOR, class ALLOCATOR>
2776inline
2778 std::initializer_list<KEY> values)
2779{
2780 insert(values.begin(), values.end());
2781}
2782#endif
2783
2784#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2785template <class KEY, class COMPARATOR, class ALLOCATOR>
2786template <class... Args>
2787inline
2790{
2791 bool leftChild;
2792
2793 BloombergLP::bslalg::RbTreeNode *node = nodeFactory().emplaceIntoNewNode(
2794 BSLS_COMPILERFEATURES_FORWARD(Args,args)...);
2795
2796 BloombergLP::bslalg::RbTreeNode *insertLocation =
2797 BloombergLP::bslalg::RbTreeUtil::findInsertLocation(&leftChild,
2798 &d_tree,
2799 this->comparator(),
2800 static_cast<const Node *>(node)->value());
2801
2802 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2803 insertLocation,
2804 leftChild,
2805 node);
2806 return iterator(node);
2807}
2808
2809template <class KEY, class COMPARATOR, class ALLOCATOR>
2810template <class... Args>
2811inline
2814 Args&&... args)
2815{
2816 bool leftChild;
2817
2818 BloombergLP::bslalg::RbTreeNode *node = nodeFactory().emplaceIntoNewNode(
2819 BSLS_COMPILERFEATURES_FORWARD(Args,args)...);
2820
2821 BloombergLP::bslalg::RbTreeNode *hintNode =
2822 const_cast<BloombergLP::bslalg::RbTreeNode *>(hint.node());
2823
2824 BloombergLP::bslalg::RbTreeNode *insertLocation =
2825 BloombergLP::bslalg::RbTreeUtil::findInsertLocation(&leftChild,
2826 &d_tree,
2827 this->comparator(),
2828 static_cast<const Node *>(node)->value(),
2829 hintNode);
2830
2831 BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree,
2832 insertLocation,
2833 leftChild,
2834 node);
2835 return iterator(node);
2836}
2837#endif
2838
2839template <class KEY, class COMPARATOR, class ALLOCATOR>
2840inline
2843{
2844 BSLS_ASSERT_SAFE(position != end());
2845
2846 BloombergLP::bslalg::RbTreeNode *node =
2847 const_cast<BloombergLP::bslalg::RbTreeNode *>(position.node());
2848 BloombergLP::bslalg::RbTreeNode *result =
2849 BloombergLP::bslalg::RbTreeUtil::next(node);
2850 BloombergLP::bslalg::RbTreeUtil::remove(&d_tree, node);
2851 nodeFactory().deleteNode(node);
2852 return iterator(result);
2853}
2854
2855template <class KEY, class COMPARATOR, class ALLOCATOR>
2856inline
2859{
2860 size_type count = 0;
2861 const_iterator first = find(key);
2862 if (first != end()) {
2863 const_iterator last = upper_bound(key);
2864 while (first != last) {
2865 first = erase(first);
2866 ++count;
2867 }
2868 }
2869 return count;
2870}
2871
2872template <class KEY, class COMPARATOR, class ALLOCATOR>
2873inline
2876 const_iterator last)
2877{
2878 while (first != last) {
2879 first = erase(first);
2880 }
2881 return iterator(last.node());
2882}
2883
2884template <class KEY, class COMPARATOR, class ALLOCATOR>
2885inline
2888 AllocatorTraits::is_always_equal::value
2889 && bsl::is_nothrow_swappable<COMPARATOR>::value)
2890{
2891 if (AllocatorTraits::propagate_on_container_swap::value) {
2892 quickSwapExchangeAllocators(other);
2893 }
2894 else {
2895 // C++11 behavior for member 'swap': undefined for unequal allocators.
2896 // BSLS_ASSERT(allocator() == other.allocator());
2897
2899 nodeFactory().allocator() == other.nodeFactory().allocator())) {
2900 quickSwapRetainAllocators(other);
2901 }
2902 else {
2904
2905 multiset toOtherCopy(MoveUtil::move(*this),
2906 other.nodeFactory().allocator());
2907 multiset toThisCopy(MoveUtil::move(other),
2908 nodeFactory().allocator());
2909
2910 other.quickSwapRetainAllocators(toOtherCopy);
2911 this->quickSwapRetainAllocators(toThisCopy);
2912 }
2913 }
2914}
2915
2916template <class KEY, class COMPARATOR, class ALLOCATOR>
2917inline
2919{
2920 BSLS_ASSERT_SAFE(d_tree.firstNode());
2921
2922 if (d_tree.rootNode()) {
2923 BSLS_ASSERT_SAFE(0 < d_tree.numNodes());
2924 BSLS_ASSERT_SAFE(d_tree.firstNode() != d_tree.sentinel());
2925
2926 BloombergLP::bslalg::RbTreeUtil::deleteTree(&d_tree, &nodeFactory());
2927 }
2928#if defined(BSLS_ASSERT_SAFE_IS_USED)
2929 else {
2930 BSLS_ASSERT_SAFE(0 == d_tree.numNodes());
2931 BSLS_ASSERT_SAFE(d_tree.firstNode() == d_tree.sentinel());
2932 }
2933#endif
2934}
2935
2936// ACCESSORS
2937template <class KEY, class COMPARATOR, class ALLOCATOR>
2938inline
2942{
2943 return nodeFactory().allocator();
2944}
2945
2946template <class KEY, class COMPARATOR, class ALLOCATOR>
2947inline
2953
2954template <class KEY, class COMPARATOR, class ALLOCATOR>
2955inline
2961
2962template <class KEY, class COMPARATOR, class ALLOCATOR>
2963inline
2969
2970template <class KEY, class COMPARATOR, class ALLOCATOR>
2971inline
2977
2978template <class KEY, class COMPARATOR, class ALLOCATOR>
2979inline
2982{
2983 return const_iterator(d_tree.firstNode());
2984}
2985
2986template <class KEY, class COMPARATOR, class ALLOCATOR>
2987inline
2990{
2991 return const_iterator(d_tree.sentinel());
2992}
2993
2994template <class KEY, class COMPARATOR, class ALLOCATOR>
2995inline
3001
3002template <class KEY, class COMPARATOR, class ALLOCATOR>
3003inline
3009
3010template <class KEY, class COMPARATOR, class ALLOCATOR>
3011inline
3013{
3014 return find(key) != end();
3015}
3016
3017// capacity:
3018template <class KEY, class COMPARATOR, class ALLOCATOR>
3019inline
3021{
3022 return 0 == d_tree.numNodes();
3023}
3024
3025template <class KEY, class COMPARATOR, class ALLOCATOR>
3026inline
3029{
3030 return d_tree.numNodes();
3031}
3032
3033template <class KEY, class COMPARATOR, class ALLOCATOR>
3034inline
3037{
3038 return AllocatorTraits::max_size(get_allocator());
3039}
3040
3041template <class KEY, class COMPARATOR, class ALLOCATOR>
3042inline
3045{
3046 return comparator().keyComparator();
3047}
3048
3049template <class KEY, class COMPARATOR, class ALLOCATOR>
3050inline
3053{
3054 return value_compare(key_comp());
3055}
3056
3057} // close namespace bsl
3058
3059// FREE OPERATORS
3060template <class KEY, class COMPARATOR, class ALLOCATOR>
3061inline
3062bool bsl::operator==(const bsl::multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
3064{
3065 return BloombergLP::bslalg::RangeCompare::equal(lhs.begin(),
3066 lhs.end(),
3067 lhs.size(),
3068 rhs.begin(),
3069 rhs.end(),
3070 rhs.size());
3071}
3072
3073#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
3074template <class KEY, class COMPARATOR, class ALLOCATOR>
3075inline
3078{
3079 return !(lhs == rhs);
3080}
3081#endif
3082
3083#ifdef BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
3084
3085template <class KEY, class COMPARATOR, class ALLOCATOR>
3086inline
3087BloombergLP::bslalg::SynthThreeWayUtil::Result<KEY>
3088bsl::operator<=>(const multiset<KEY, COMPARATOR, ALLOCATOR>& lhs,
3089 const multiset<KEY, COMPARATOR, ALLOCATOR>& rhs)
3090{
3091 return bsl::lexicographical_compare_three_way(
3092 lhs.begin(),
3093 lhs.end(),
3094 rhs.begin(),
3095 rhs.end(),
3096 BloombergLP::bslalg::SynthThreeWayUtil::compare);
3097}
3098
3099#else
3100
3101template <class KEY, class COMPARATOR, class ALLOCATOR>
3102inline
3105{
3106 return 0 > BloombergLP::bslalg::RangeCompare::lexicographical(lhs.begin(),
3107 lhs.end(),
3108 lhs.size(),
3109 rhs.begin(),
3110 rhs.end(),
3111 rhs.size());
3112}
3113
3114template <class KEY, class COMPARATOR, class ALLOCATOR>
3115inline
3118{
3119 return rhs < lhs;
3120}
3121
3122template <class KEY, class COMPARATOR, class ALLOCATOR>
3123inline
3126{
3127 return !(rhs < lhs);
3128}
3129
3130template <class KEY, class COMPARATOR, class ALLOCATOR>
3131inline
3134{
3135 return !(lhs < rhs);
3136}
3137
3138#endif // BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
3139
3140// FREE FUNCTIONS
3141template <class KEY, class COMPARATOR, class ALLOCATOR, class PREDICATE>
3142inline
3144bsl::erase_if(multiset<KEY, COMPARATOR, ALLOCATOR>& ms, PREDICATE predicate)
3145{
3146 return BloombergLP::bslstl::AlgorithmUtil::containerEraseIf(ms, predicate);
3147}
3148
3149template <class KEY, class COMPARATOR, class ALLOCATOR>
3150inline
3155{
3156 a.swap(b);
3157}
3158
3159// ============================================================================
3160// TYPE TRAITS
3161// ============================================================================
3162
3163// Type traits for STL *ordered* containers:
3164//: o An ordered container defines STL iterators.
3165//: o An ordered container uses 'bslma' allocators if the (template parameter)
3166//: type 'ALLOCATOR' is convertible from 'bslma::Allocator *'.
3167
3168
3169
3170namespace bslalg {
3171
3172template <class KEY, class COMPARATOR, class ALLOCATOR>
3173struct HasStlIterators<bsl::multiset<KEY, COMPARATOR, ALLOCATOR> >
3175{};
3176
3177} // close namespace bslalg
3178
3179namespace bslma {
3180
3181template <class KEY, class COMPARATOR, class ALLOCATOR>
3182struct UsesBslmaAllocator<bsl::multiset<KEY, COMPARATOR, ALLOCATOR> >
3183 : bsl::is_convertible<Allocator*, ALLOCATOR>
3184{};
3185
3186} // close namespace bslma
3187
3188
3189
3190#endif // End C++11 code
3191
3192#endif
3193
3194// ----------------------------------------------------------------------------
3195// Copyright 2019 Bloomberg Finance L.P.
3196//
3197// Licensed under the Apache License, Version 2.0 (the "License");
3198// you may not use this file except in compliance with the License.
3199// You may obtain a copy of the License at
3200//
3201// http://www.apache.org/licenses/LICENSE-2.0
3202//
3203// Unless required by applicable law or agreed to in writing, software
3204// distributed under the License is distributed on an "AS IS" BASIS,
3205// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3206// See the License for the specific language governing permissions and
3207// limitations under the License.
3208// ----------------------------- END-OF-FILE ----------------------------------
3209
3210/** @} */
3211/** @} */
3212/** @} */
Definition bslma_bslallocator.h:588
Definition bslstl_multiset.h:644
multiset(const COMPARATOR &comparator, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_multiset.h:848
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2997
multiset &operator=(BloombergLP::bslmf::MovableRef< multiset > rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2610
bool empty() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:3020
void swap(multiset &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:1310
size_type max_size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:3036
BloombergLP::bslstl::TreeIterator< const value_type, Node, difference_type > const_iterator
Definition bslstl_multiset.h:748
value_type & reference
Definition bslstl_multiset.h:735
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bslstl_multiset.h:750
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:3005
COMPARATOR key_compare
Definition bslstl_multiset.h:732
BloombergLP::bslstl::TreeIterator< const value_type, Node, difference_type > iterator
Definition bslstl_multiset.h:745
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2989
COMPARATOR value_compare
Definition bslstl_multiset.h:733
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, pair< iterator, iterator > >::type equal_range(const LOOKUP_KEY &key)
Definition bslstl_multiset.h:1459
iterator erase(const_iterator position)
Definition bslstl_multiset.h:2842
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2618
iterator find(const key_type &key)
Definition bslstl_multiset.h:1322
key_compare key_comp() const
Definition bslstl_multiset.h:3044
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this multiset.
Definition bslstl_multiset.h:3028
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, size_type >::type count(const LOOKUP_KEY &key) const
Definition bslstl_multiset.h:1625
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2940
multiset()
Definition bslstl_multiset.h:2327
iterator insert(const value_type &value)
Definition bslstl_multiset.h:2642
iterator lower_bound(const key_type &key)
Definition bslstl_multiset.h:1356
KEY value_type
Definition bslstl_multiset.h:731
void insert_range(BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
Definition bslstl_multiset.h:1186
~multiset()
Destroy this object.
Definition bslstl_multiset.h:2541
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2981
bool contains(const key_type &key) const
Definition bslstl_multiset.h:3012
pair< iterator, iterator > equal_range(const key_type &key)
Definition bslstl_multiset.h:1433
const_iterator upper_bound(const key_type &key) const
Definition bslstl_multiset.h:1687
iterator emplace(Args &&... args)
Definition bslstl_multiset.h:2789
value_compare value_comp() const
Definition bslstl_multiset.h:3052
multiset & operator=(const multiset &rhs)
Definition bslstl_multiset.h:2550
KEY key_type
Definition bslstl_multiset.h:730
reverse_iterator rend() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2634
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, iterator >::type find(const LOOKUP_KEY &key)
Definition bslstl_multiset.h:1339
iterator upper_bound(const key_type &key)
Definition bslstl_multiset.h:1395
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, pair< const_iterator, const_iterator > >::type equal_range(const LOOKUP_KEY &key) const
Definition bslstl_multiset.h:1753
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition bslstl_multiset.h:2813
enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, 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_multiset.h:1261
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, iterator >::type upper_bound(const LOOKUP_KEY &key)
Definition bslstl_multiset.h:1417
AllocatorTraits::const_pointer const_pointer
Definition bslstl_multiset.h:741
AllocatorTraits::difference_type difference_type
Definition bslstl_multiset.h:739
size_type count(const key_type &key) const
Definition bslstl_multiset.h:1604
const_iterator lower_bound(const key_type &key) const
Definition bslstl_multiset.h:1648
AllocatorTraits::pointer pointer
Definition bslstl_multiset.h:740
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, iterator >::type lower_bound(const LOOKUP_KEY &key)
Definition bslstl_multiset.h:1378
ALLOCATOR allocator_type
Definition bslstl_multiset.h:734
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, const_iterator >::type upper_bound(const LOOKUP_KEY &key) const
Definition bslstl_multiset.h:1709
reverse_iterator rbegin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_multiset.h:2626
bsl::reverse_iterator< iterator > reverse_iterator
Definition bslstl_multiset.h:749
const value_type & const_reference
Definition bslstl_multiset.h:736
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, const_iterator >::type lower_bound(const LOOKUP_KEY &key) const
Definition bslstl_multiset.h:1670
pair< const_iterator, const_iterator > equal_range(const key_type &key) const
Definition bslstl_multiset.h:1726
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< COMPARATOR, LOOKUP_KEY >::value, const_iterator >::type find(const LOOKUP_KEY &key) const
Definition bslstl_multiset.h:1594
AllocatorTraits::size_type size_type
Definition bslstl_multiset.h:738
Definition bslstl_pair.h:1280
#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 BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
#define BSLSTL_MULTISET_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
Definition bslstl_multiset.h:606
Definition bdlat_valuetypefunctions.h:939
void swap(array< VALUE_TYPE, SIZE > &lhs, array< VALUE_TYPE, SIZE > &rhs)
T::const_iterator cend(const T &container)
Definition bslstl_iterator.h:1709
bool operator<(const array< VALUE_TYPE, SIZE > &lhs, const array< VALUE_TYPE, SIZE > &rhs)
T::const_reverse_iterator crbegin(const T &container)
Definition bslstl_iterator.h:1695
bool operator>(const array< VALUE_TYPE, SIZE > &lhs, const array< VALUE_TYPE, SIZE > &rhs)
bool operator>=(const array< VALUE_TYPE, SIZE > &lhs, const array< VALUE_TYPE, SIZE > &rhs)
bool operator<=(const array< VALUE_TYPE, SIZE > &lhs, const 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
T::const_iterator cbegin(const T &container)
Definition bslstl_iterator.h:1651
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)
T::const_reverse_iterator crend(const T &container)
Definition bslstl_iterator.h:1752
Definition bdlc_flathashmap.h:2218
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
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_ranges.h:301
Definition bslmf_isconvertible.h:875
Definition bslalg_hasstliterators.h:99
Definition bslma_usesbslmaallocator.h:344