22 Containers library [containers]

22.4 Associative containers [associative]

22.4.7 Class template multiset [multiset]

22.4.7.1 Overview [multiset.overview]

A multiset is an associative container that supports equivalent keys (possibly contains multiple copies of the same key value) and provides for fast retrieval of the keys themselves.
The multiset class supports bidirectional iterators.
A multiset meets all of the requirements of a container, of a reversible container ([container.requirements]), of an associative container ([associative.reqmts]), and of an allocator-aware container (Table 76).
multiset also provides most operations described in [associative.reqmts] for duplicate keys.
This means that a multiset supports the a_­eq operations in [associative.reqmts] but not the a_­uniq operations.
For a multiset<Key> both the key_­type and value_­type are Key.
Descriptions are provided here only for operations on multiset that are not described in one of these tables and for operations where there is additional semantic information.
namespace std { template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> class multiset { public: // types using key_type = Key; using key_compare = Compare; using value_type = Key; using value_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using node_type = unspecified; // [multiset.cons], construct/copy/destroy multiset() : multiset(Compare()) { } explicit multiset(const Compare& comp, const Allocator& = Allocator()); template<class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); multiset(const multiset& x); multiset(multiset&& x); explicit multiset(const Allocator&); multiset(const multiset&, const Allocator&); multiset(multiset&&, const Allocator&); multiset(initializer_list<value_type>, const Compare& = Compare(), const Allocator& = Allocator()); template<class InputIterator> multiset(InputIterator first, InputIterator last, const Allocator& a) : multiset(first, last, Compare(), a) { } multiset(initializer_list<value_type> il, const Allocator& a) : multiset(il, Compare(), a) { } ~multiset(); multiset& operator=(const multiset& x); multiset& operator=(multiset&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>); multiset& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity [[nodiscard]] bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& x); iterator insert(value_type&& x); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); template<class InputIterator> void insert(InputIterator first, InputIterator last); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); iterator insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); iterator erase(const_iterator first, const_iterator last); void swap(multiset&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>); void clear() noexcept; template<class C2> void merge(multiset<Key, C2, Allocator>& source); template<class C2> void merge(multiset<Key, C2, Allocator>&& source); template<class C2> void merge(set<Key, C2, Allocator>& source); template<class C2> void merge(set<Key, C2, Allocator>&& source); // observers key_compare key_comp() const; value_compare value_comp() const; // set operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; }; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>, class Allocator = allocator<iter-value-type<InputIterator>>> multiset(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> multiset<iter-value-type<InputIterator>, Compare, Allocator>; template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) -> multiset<Key, Compare, Allocator>; template<class InputIterator, class Allocator> multiset(InputIterator, InputIterator, Allocator) -> multiset<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; template<class Key, class Allocator> multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>; // swap template<class Key, class Compare, class Allocator> void swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y) noexcept(noexcept(x.swap(y))); }

22.4.7.2 Constructors [multiset.cons]

explicit multiset(const Compare& comp, const Allocator& = Allocator());
Effects: Constructs an empty multiset using the specified comparison object and allocator.
Complexity: Constant.
template<class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty multiset using the specified comparison object and allocator, and inserts elements from the range [first, last).
Complexity: Linear in N if the range [first, last) is already sorted using comp and otherwise , where N is last - first.

22.4.7.3 Erasure [multiset.erasure]

template<class Key, class Compare, class Allocator, class Predicate> typename multiset<Key, Compare, Allocator>::size_type erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();