206 KiB
[container.adaptors]
23 Containers library [containers]
23.6 Container adaptors [container.adaptors]
23.6.1 General [container.adaptors.general]
The headers,,<flat_map>, and <flat_set> define the container adaptorsqueue and priority_queue,stack,flat_map and flat_multimap, and flat_set and flat_multiset, respectively.
Each container adaptor takes one or more template parameters named Container, KeyContainer, or MappedContainer that denote the types of containers that the container adaptor adapts.
Each container adaptor has at least one constructor that takes a reference argument to one or more such template parameters.
For each constructor reference argument to a container C, the constructor copies the container into the container adaptor.
If C takes an allocator, then a compatible allocator may be passed in to the adaptor's constructor.
Otherwise, normal copy or move construction is used for the container argument.
For the container adaptors that take a single container template parameter Container, the first template parameter T of the container adaptor shall denote the same type as Container::value_type.
For container adaptors, no swap function throws an exception unless that exception is thrown by the swap of the adaptor'sContainer,KeyContainer,MappedContainer, orCompare object (if any).
A constructor template of a container adaptor shall not participate in overload resolution if it has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
For container adaptors that have them, the insert, emplace, and erase members affect the validity of iterators, references, and pointers to the adaptor's container(s) in the same way that the containers' respectiveinsert, emplace, and erase members do.
[Example 1:
A call to flat_map<Key, T>::insert can invalidate all iterators to the flat_map.
â end example]
A deduction guide for a container adaptor shall not participate in overload resolution if any of the following are true:
-
It has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
-
It has a Compare template parameter and a type that qualifies as an allocator is deduced for that parameter.
-
It has a Container, KeyContainer, or MappedContainer template parameter and a type that qualifies as an allocator is deduced for that parameter.
-
It has no Container, KeyContainer, or MappedContainer template parameter, and it has an Allocator template parameter, and a type that does not qualify as an allocator is deduced for that parameter.
-
It has both Container and Allocator template parameters, and uses_allocator_v<Container, Allocator> is false.
-
It has both KeyContainer and Allocator template parameters, anduses_allocator_v<KeyContainer, Allocator> is false.
-
It has both KeyContainer and Compare template parameters, andis_invocable_v<const Compare&, const typename KeyContainer::value_type&, const typename KeyContainer::value_type&> is not a valid expression or is false.
-
It has both MappedContainer and Allocator template parameters, anduses_allocator_v<MappedContainer, Allocator> is false.
The exposition-only alias template iter-value-type defined in [sequences.general] and the exposition-only alias templates iter-key-type, iter-mapped-type,range-key-type, and range-mapped-type defined in [associative.general] may appear in deduction guides for container adaptors.
The following exposition-only alias template may appear in deduction guides for container adaptors:template<class Allocator, class T>using alloc-rebind = // exposition onlytypename allocator_traits::template rebind_alloc;
23.6.2 Header synopsis [queue.syn]
#include // see [compare.syn]#include <initializer_list> // see [initializer.list.syn]namespace std {// [queue], class template queuetemplate<class T, class Container = deque> class queue; template<class T, class Container>constexpr bool operator==(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container>constexpr bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container>constexpr bool operator< (const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container>constexpr bool operator> (const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container>constexpr bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container>constexpr bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, three_way_comparable Container>constexpr compare_three_way_result_toperator<=>(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container>constexpr void swap(queue<T, Container>& x, queue<T, Container>& y)noexcept(noexcept(x.swap(y))); template<class T, class Container, class Alloc>struct uses_allocator<queue<T, Container>, Alloc>; // [container.adaptors.format], formatter specialization for queuetemplate<class charT, class T, formattable Container>struct formatter<queue<T, Container>, charT>; // [priority.queue], class template priority_queuetemplate<class T, class Container = vector, class Compare = less>class priority_queue; template<class T, class Container, class Compare>constexpr void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y))); template<class T, class Container, class Compare, class Alloc>struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>; // [container.adaptors.format], formatter specialization for priority_queuetemplate<class charT, class T, formattable Container, class Compare>struct formatter<priority_queue<T, Container, Compare>, charT>;}
23.6.3 Class template queue [queue]
23.6.3.1 Definition [queue.defn]
Any sequence container supporting operationsfront(),back(),push_back() andpop_front() can be used to instantiatequeue.
In particular, and can be used.
namespace std {template<class T, class Container = deque>class queue {public:using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; protected: Container c; public:constexpr queue() : queue(Container()) {}constexpr explicit queue(const Container&); constexpr explicit queue(Container&&); template constexpr queue(InputIterator first, InputIterator last); template<container-compatible-range R> constexpr queue(from_range_t, R&& rg); template constexpr explicit queue(const Alloc&); template constexpr queue(const Container&, const Alloc&); template constexpr queue(Container&&, const Alloc&); template constexpr queue(const queue&, const Alloc&); template constexpr queue(queue&&, const Alloc&); template<class InputIterator, class Alloc>constexpr queue(InputIterator first, InputIterator last, const Alloc&); template<container-compatible-range R, class Alloc>constexpr queue(from_range_t, R&& rg, const Alloc&); constexpr bool empty() const { return c.empty(); }constexpr size_type size() const { return c.size(); }constexpr reference front() { return c.front(); }constexpr const_reference front() const { return c.front(); }constexpr reference back() { return c.back(); }constexpr const_reference back() const { return c.back(); }constexpr void push(const value_type& x) { c.push_back(x); }constexpr void push(value_type&& x) { c.push_back(std::move(x)); }template<container-compatible-range R> constexpr void push_range(R&& rg); template<class... Args>constexpr decltype(auto) emplace(Args&&... args){ return c.emplace_back(std::forward(args)...); }constexpr void pop() { c.pop_front(); }constexpr void swap(queue& q) noexcept(is_nothrow_swappable_v){ using std::swap; swap(c, q.c); }}; template queue(Container) -> queue<typename Container::value_type, Container>; template queue(InputIterator, InputIterator) -> queue<iter-value-type>; template<ranges::input_range R> queue(from_range_t, R&&) -> queue<ranges::range_value_t>; template<class Container, class Allocator> queue(Container, Allocator) -> queue<typename Container::value_type, Container>; template<class InputIterator, class Allocator> queue(InputIterator, InputIterator, Allocator)-> queue<iter-value-type, deque<iter-value-type, Allocator>>; template<ranges::input_range R, class Allocator> queue(from_range_t, R&&, Allocator)-> queue<ranges::range_value_t, deque<ranges::range_value_t, Allocator>>; template<class T, class Container, class Alloc>struct uses_allocator<queue<T, Container>, Alloc>: uses_allocator<Container, Alloc>::type { };}
23.6.3.2 Constructors [queue.cons]
constexpr explicit queue(const Container& cont);
Effects: Initializes c with cont.
constexpr explicit queue(Container&& cont);
Effects: Initializes c with std::move(cont).
template<class InputIterator> constexpr queue(InputIterator first, InputIterator last);
Effects: Initializes c withfirst as the first argument and last as the second argument.
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R> constexpr queue(from_range_t, R&& rg);
Effects: Initializes c with ranges::to(std::forward(rg)).
23.6.3.3 Constructors with allocators [queue.cons.alloc]
If uses_allocator_v<container_type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> constexpr explicit queue(const Alloc& a);
Effects: Initializes c with a.
template<class Alloc> constexpr queue(const container_type& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument.
template<class Alloc> constexpr queue(container_type&& cont, const Alloc& a);
Effects: Initializes c with std::move(cont) as the first argument and a as the second argument.
template<class Alloc> constexpr queue(const queue& q, const Alloc& a);
Effects: Initializes c with q.c as the first argument and a as the second argument.
template<class Alloc> constexpr queue(queue&& q, const Alloc& a);
Effects: Initializes c with std::move(q.c) as the first argument and a as the second argument.
template<class InputIterator, class Alloc> constexpr queue(InputIterator first, InputIterator last, const Alloc& alloc);
Effects: Initializes c withfirst as the first argument,last as the second argument, andalloc as the third argument.
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R, class Alloc> constexpr queue(from_range_t, R&& rg, const Alloc& a);
Effects: Initializes c withranges::to(std::forward(rg), a).
23.6.3.4 Modifiers [queue.mod]
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R> constexpr void push_range(R&& rg);
Effects: Equivalent to c.append_range(std::forward(rg)) if that is a valid expression, otherwise ranges::copy(rg, back_inserter(c)).
23.6.3.5 Operators [queue.ops]
template<class T, class Container> constexpr bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c == y.c.
template<class T, class Container> constexpr bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c != y.c.
template<class T, class Container> constexpr bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c < y.c.
template<class T, class Container> constexpr bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c > y.c.
template<class T, class Container> constexpr bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c <= y.c.
template<class T, class Container> constexpr bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c >= y.c.
template<class T, [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_way_comparable [cmp.concept]") Container> constexpr compare_three_way_result_t<Container> operator<=>(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c <=> y.c.
23.6.3.6 Specialized algorithms [queue.special]
template<class T, class Container> constexpr void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_swappable_v is true.
Effects: As if by x.swap(y).
23.6.4 Class template priority_queue [priority.queue]
23.6.4.1 Overview [priqueue.overview]
Any sequence container with random access iterator and supporting operationsfront(),push_back() andpop_back() can be used to instantiatepriority_queue.
In particular, and can be used.
Instantiatingpriority_queue also involves supplying a function or function object for making priority comparisons; the library assumes that the function or function object defines a strict weak ordering.
namespace std {template<class T, class Container = vector, class Compare = less>class priority_queue {public:using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; using value_compare = Compare; protected: Container c; Compare comp; public:constexpr priority_queue() : priority_queue(Compare()) {}constexpr explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {}constexpr priority_queue(const Compare& x, const Container&); constexpr priority_queue(const Compare& x, Container&&); templateconstexpr priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); templateconstexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container&); templateconstexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&&); template<container-compatible-range R>constexpr priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); template constexpr explicit priority_queue(const Alloc&); template constexpr priority_queue(const Compare&, const Alloc&); templateconstexpr priority_queue(const Compare&, const Container&, const Alloc&); template constexpr priority_queue(const Compare&, Container&&, const Alloc&); template constexpr priority_queue(const priority_queue&, const Alloc&); template constexpr priority_queue(priority_queue&&, const Alloc&); template<class InputIterator, class Alloc>constexpr priority_queue(InputIterator, InputIterator, const Alloc&); template<class InputIterator, class Alloc>constexpr priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&); template<class InputIterator, class Alloc>constexpr priority_queue(InputIterator, InputIterator, const Compare&, const Container&, const Alloc&); template<class InputIterator, class Alloc>constexpr priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&); template<container-compatible-range R, class Alloc>constexpr priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); template<container-compatible-range R, class Alloc>constexpr priority_queue(from_range_t, R&& rg, const Alloc&); constexpr bool empty() const { return c.empty(); }constexpr size_type size() const { return c.size(); }constexpr const_reference top() const { return c.front(); }constexpr void push(const value_type& x); constexpr void push(value_type&& x); template<container-compatible-range R>constexpr void push_range(R&& rg); template<class... Args> constexpr void emplace(Args&&... args); constexpr void pop(); constexpr void swap(priority_queue& q)noexcept(is_nothrow_swappable_v && is_nothrow_swappable_v){ using std::swap; swap(c, q.c); swap(comp, q.comp); }}; template<class Compare, class Container> priority_queue(Compare, Container)-> priority_queue<typename Container::value_type, Container, Compare>; template<class InputIterator, class Compare = less<iter-value-type>, class Container = vector<iter-value-type>> priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container())-> priority_queue<iter-value-type, Container, Compare>; template<ranges::input_range R, class Compare = less<ranges::range_value_t>> priority_queue(from_range_t, R&&, Compare = Compare())-> priority_queue<ranges::range_value_t, vector<ranges::range_value_t>, Compare>; template<class Compare, class Container, class Allocator> priority_queue(Compare, Container, Allocator)-> priority_queue<typename Container::value_type, Container, Compare>; template<class InputIterator, class Allocator> priority_queue(InputIterator, InputIterator, Allocator)-> priority_queue<iter-value-type, vector<iter-value-type, Allocator>, less<iter-value-type>>; template<class InputIterator, class Compare, class Allocator> priority_queue(InputIterator, InputIterator, Compare, Allocator)-> priority_queue<iter-value-type, vector<iter-value-type, Allocator>, Compare>; template<class InputIterator, class Compare, class Container, class Allocator> priority_queue(InputIterator, InputIterator, Compare, Container, Allocator)-> priority_queue<typename Container::value_type, Container, Compare>; template<ranges::input_range R, class Compare, class Allocator> priority_queue(from_range_t, R&&, Compare, Allocator)-> priority_queue<ranges::range_value_t, vector<ranges::range_value_t, Allocator>, Compare>; template<ranges::input_range R, class Allocator> priority_queue(from_range_t, R&&, Allocator)-> priority_queue<ranges::range_value_t, vector<ranges::range_value_t, Allocator>>; // no equality is providedtemplate<class T, class Container, class Compare, class Alloc>struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>: uses_allocator<Container, Alloc>::type { };}
23.6.4.2 Constructors [priqueue.cons]
constexpr priority_queue(const Compare& x, const Container& y); constexpr priority_queue(const Compare& x, Container&& y);
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializescomp withx andc withy (copy constructing or move constructing as appropriate); callsmake_heap(c.begin(), c.end(), comp).
template<class InputIterator> constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare());
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes c withfirst as the first argument andlast as the second argument, and initializes comp with x; then calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator> constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container& y); template<class InputIterator> constexpr priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&& y);
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializescomp withx andc withy (copy constructing or move constructing as appropriate); callsc.insert(c.end(), first, last); and finally callsmake_heap(c.begin(), c.end(), comp).
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R> constexpr priority_queue(from_range_t, R&& rg, const Compare& x = Compare());
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes comp with x andc with ranges::to(std::forward(rg)) and finally calls make_heap(c.begin(), c.end(), comp).
23.6.4.3 Constructors with allocators [priqueue.cons.alloc]
If uses_allocator_v<container_type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> constexpr explicit priority_queue(const Alloc& a);
Effects: Initializes c with a and value-initializes comp.
template<class Alloc> constexpr priority_queue(const Compare& compare, const Alloc& a);
Effects: Initializes c with a and initializes comp with compare.
template<class Alloc> constexpr priority_queue(const Compare& compare, const Container& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument, and initializes comp with compare; calls make_heap(c.begin(), c.end(), comp).
template<class Alloc> constexpr priority_queue(const Compare& compare, Container&& cont, const Alloc& a);
Effects: Initializes c with std::move(cont) as the first argument and a as the second argument, and initializes comp with compare; calls make_heap(c.begin(), c.end(), comp).
template<class Alloc> constexpr priority_queue(const priority_queue& q, const Alloc& a);
Effects: Initializes c with q.c as the first argument and a as the second argument, and initializes comp with q.comp.
template<class Alloc> constexpr priority_queue(priority_queue&& q, const Alloc& a);
Effects: Initializes c with std::move(q.c) as the first argument and a as the second argument, and initializes comp with std::move(q.comp).
template<class InputIterator, class Alloc> constexpr priority_queue(InputIterator first, InputIterator last, const Alloc& a);
Effects: Initializes c withfirst as the first argument,last as the second argument, anda as the third argument, and value-initializes comp; calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> constexpr priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Alloc& a);
Effects: Initializes c withfirst as the first argument,last as the second argument, anda as the third argument, and initializes comp with compare; calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> constexpr priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Container& cont, const Alloc& a);
Effects: Initializes c withcont as the first argument and a as the second argument, and initializes comp with compare; calls c.insert(c.end(), first, last); and finally calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> constexpr priority_queue(InputIterator first, InputIterator last, const Compare& compare, Container&& cont, const Alloc& a);
Effects: Initializes c withstd::move(cont) as the first argument anda as the second argument, and initializes comp with compare; calls c.insert(c.end(), first, last); and finally calls make_heap(c.begin(), c.end(), comp).
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R, class Alloc> constexpr priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a);
Effects: Initializes comp with compare andc with ranges::to(std::forward(rg), a); calls make_heap(c.begin(), c.end(), comp).
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R, class Alloc> constexpr priority_queue(from_range_t, R&& rg, const Alloc& a);
Effects: Initializesc with ranges::to(std::forward(rg), a) and value-initializes comp; calls make_heap(c.begin(), c.end(), comp).
23.6.4.4 Members [priqueue.members]
constexpr void push(const value_type& x);
Effects: As if by:c.push_back(x); push_heap(c.begin(), c.end(), comp);
constexpr void push(value_type&& x);
Effects: As if by:c.push_back(std::move(x)); push_heap(c.begin(), c.end(), comp);
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R> constexpr void push_range(R&& rg);
Effects: Inserts all elements of rg in c viac.append_range(std::forward(rg)) if that is a valid expression, orranges::copy(rg, back_inserter(c)) otherwise.
Then restores the heap property as if bymake_heap(c.begin(), c.end(), comp).
Postconditions: is_heap(c.begin(), c.end(), comp) is true.
template<class... Args> constexpr void emplace(Args&&... args);
Effects: As if by:c.emplace_back(std::forward(args)...); push_heap(c.begin(), c.end(), comp);
constexpr void pop();
Effects: As if by:pop_heap(c.begin(), c.end(), comp); c.pop_back();
23.6.4.5 Specialized algorithms [priqueue.special]
template<class T, class Container, class Compare> constexpr void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_swappable_v is true andis_swappable_v is true.
Effects: As if by x.swap(y).
23.6.5 Header synopsis [stack.syn]
#include // see [compare.syn]#include <initializer_list> // see [initializer.list.syn]namespace std {// [stack], class template stacktemplate<class T, class Container = deque> class stack; template<class T, class Container>constexpr bool operator==(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container>constexpr bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container>constexpr bool operator< (const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container>constexpr bool operator> (const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container>constexpr bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container>constexpr bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, three_way_comparable Container>constexpr compare_three_way_result_toperator<=>(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container>constexpr void swap(stack<T, Container>& x, stack<T, Container>& y)noexcept(noexcept(x.swap(y))); template<class T, class Container, class Alloc>struct uses_allocator<stack<T, Container>, Alloc>; // [container.adaptors.format], formatter specialization for stacktemplate<class charT, class T, formattable Container>struct formatter<stack<T, Container>, charT>;}
23.6.6 Class template stack [stack]
23.6.6.1 General [stack.general]
Any sequence container supporting operationsback(),push_back() andpop_back() can be used to instantiatestack.
In particular,, and can be used.
23.6.6.2 Definition [stack.defn]
namespace std {template<class T, class Container = deque>class stack {public:using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; protected: Container c; public:constexpr stack() : stack(Container()) {}constexpr explicit stack(const Container&); constexpr explicit stack(Container&&); template constexpr stack(InputIterator first, InputIterator last); template<container-compatible-range R>constexpr stack(from_range_t, R&& rg); template constexpr explicit stack(const Alloc&); template constexpr stack(const Container&, const Alloc&); template constexpr stack(Container&&, const Alloc&); template constexpr stack(const stack&, const Alloc&); template constexpr stack(stack&&, const Alloc&); template<class InputIterator, class Alloc>constexpr stack(InputIterator first, InputIterator last, const Alloc&); template<container-compatible-range R, class Alloc>constexpr stack(from_range_t, R&& rg, const Alloc&); constexpr bool empty() const { return c.empty(); }constexpr size_type size() const { return c.size(); }constexpr reference top() { return c.back(); }constexpr const_reference top() const { return c.back(); }constexpr void push(const value_type& x) { c.push_back(x); }constexpr void push(value_type&& x) { c.push_back(std::move(x)); }template<container-compatible-range R>constexpr void push_range(R&& rg); template<class... Args>constexpr decltype(auto) emplace(Args&&... args){ return c.emplace_back(std::forward(args)...); }constexpr void pop() { c.pop_back(); }constexpr void swap(stack& s) noexcept(is_nothrow_swappable_v){ using std::swap; swap(c, s.c); }}; template stack(Container) -> stack<typename Container::value_type, Container>; template stack(InputIterator, InputIterator) -> stack<iter-value-type>; template<ranges::input_range R> stack(from_range_t, R&&) -> stack<ranges::range_value_t>; template<class Container, class Allocator> stack(Container, Allocator) -> stack<typename Container::value_type, Container>; template<class InputIterator, class Allocator> stack(InputIterator, InputIterator, Allocator)-> stack<iter-value-type, deque<iter-value-type, Allocator>>; template<ranges::input_range R, class Allocator> stack(from_range_t, R&&, Allocator)-> stack<ranges::range_value_t, deque<ranges::range_value_t, Allocator>>; template<class T, class Container, class Alloc>struct uses_allocator<stack<T, Container>, Alloc>: uses_allocator<Container, Alloc>::type { };}
23.6.6.3 Constructors [stack.cons]
constexpr explicit stack(const Container& cont);
Effects: Initializes c with cont.
constexpr explicit stack(Container&& cont);
Effects: Initializes c with std::move(cont).
template<class InputIterator> constexpr stack(InputIterator first, InputIterator last);
Effects: Initializes c withfirst as the first argument and last as the second argument.
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R> constexpr stack(from_range_t, R&& rg);
Effects: Initializes c with ranges::to(std::forward(rg)).
23.6.6.4 Constructors with allocators [stack.cons.alloc]
If uses_allocator_v<container_type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> constexpr explicit stack(const Alloc& a);
Effects: Initializes c with a.
template<class Alloc> constexpr stack(const container_type& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument.
template<class Alloc> constexpr stack(container_type&& cont, const Alloc& a);
Effects: Initializes c with std::move(cont) as the first argument and a as the second argument.
template<class Alloc> constexpr stack(const stack& s, const Alloc& a);
Effects: Initializes c with s.c as the first argument and a as the second argument.
template<class Alloc> constexpr stack(stack&& s, const Alloc& a);
Effects: Initializes c with std::move(s.c) as the first argument and a as the second argument.
template<class InputIterator, class Alloc> constexpr stack(InputIterator first, InputIterator last, const Alloc& alloc);
Effects: Initializes c withfirst as the first argument,last as the second argument, andalloc as the third argument.
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R, class Alloc> constexpr stack(from_range_t, R&& rg, const Alloc& a);
Effects: Initializesc with ranges::to(std::forward(rg), a).
23.6.6.5 Modifiers [stack.mod]
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<T> R> constexpr void push_range(R&& rg);
Effects: Equivalent to c.append_range(std::forward(rg)) if that is a valid expression, otherwise ranges::copy(rg, back_inserter(c)).
23.6.6.6 Operators [stack.ops]
template<class T, class Container> constexpr bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c == y.c.
template<class T, class Container> constexpr bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c != y.c.
template<class T, class Container> constexpr bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c < y.c.
template<class T, class Container> constexpr bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c > y.c.
template<class T, class Container> constexpr bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c <= y.c.
template<class T, class Container> constexpr bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c >= y.c.
template<class T, [three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_way_comparable [cmp.concept]") Container> constexpr compare_three_way_result_t<Container> operator<=>(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c <=> y.c.
23.6.6.7 Specialized algorithms [stack.special]
template<class T, class Container> constexpr void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_swappable_v is true.
Effects: As if by x.swap(y).
23.6.7 Header <flat_map> synopsis [flat.map.syn]
#include // see [compare.syn]#include <initializer_list> // see [initializer.list.syn]namespace std {// [flat.map], class template flat_maptemplate<class Key, class T, class Compare = less, class KeyContainer = vector, class MappedContainer = vector>class flat_map; struct sorted_unique_t { explicit sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique{}; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator>struct uses_allocator<flat_map<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>; // [flat.map.erasure], erasure for flat_maptemplate<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate>constexpr typename flat_map<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_map<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred); // [flat.multimap], class template flat_multimaptemplate<class Key, class T, class Compare = less, class KeyContainer = vector, class MappedContainer = vector>class flat_multimap; struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; inline constexpr sorted_equivalent_t sorted_equivalent{}; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator>struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>; // [flat.multimap.erasure], erasure for flat_multimaptemplate<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate>constexpr typename flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);}
23.6.8 Class template flat_map [flat.map]
23.6.8.1 Overview [flat.map.overview]
A flat_map is a container adaptor that provides an associative container interface that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of values of another type T based on the keys.
flat_map supports iterators that meet the Cpp17InputIterator requirements and model therandom_access_iterator concept ([iterator.concept.random.access]).
A flat_map meets all of the requirements of a container ([container.reqmts]) and of a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_map meets the requirements of an associative container ([associative.reqmts]), except that:
it does not meet the requirements related to node handles ([container.node]),
it does not meet the requirements related to iterator invalidation, and
the time complexity of the operations that insert or erase a single element from the map is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_map does not meet the additional requirements of an allocator-aware container ([container.alloc.reqmts]).
â end note]
A flat_map also provides most operations described in [associative.reqmts] for unique keys.
This means that a flat_map supports the a_uniq operations in [associative.reqmts] but not the a_eq operations.
For a flat_map<Key, T> the key_type is Key and the value_type is pair<Key, T>.
Descriptions are provided here only for operations on flat_map that are not described in one of those sets of requirements or for operations where there is additional semantic information.
A flat_map maintains the following invariants:
it contains the same number of keys and values;
the keys are sorted with respect to the comparison object; and
the value at offset off within the value container is the value associated with the key at offset off within the key container.
If any member function in [flat.map.defn] exits via an exception the invariants are restored.
[Note 2:
This can result in the flat_map being emptied.
â end note]
Any type C that meets the sequence container requirements ([sequence.reqmts]) can be used to instantiate flat_map, as long asC::iterator meets the Cpp17RandomAccessIterator requirements and invocations of member functions C::size and C::max_size do not exit via an exception.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector is not a sequence container.
â end note]
The program is ill-formed ifKey is not the same type as KeyContainer::value_type orT is not the same type as MappedContainer::value_type.
The effect of calling a constructor that takes both key_container_type and mapped_container_type arguments with containers of different sizes is undefined.
The effect of calling a constructor or member function that takes a sorted_unique_t argument with a container, containers, or range that is not sorted with respect to key_comp(), or that contains equal elements, is undefined.
The types iterator and const_iterator meet the constexpr iterator requirements ([iterator.requirements.general]).
23.6.8.2 Definition [flat.map.defn]
namespace std {template<class Key, class T, class Compare = less, class KeyContainer = vector, class MappedContainer = vector>class flat_map {public:// typesusing key_type = Key; using mapped_type = T; using value_type = pair<key_type, mapped_type>; using key_compare = Compare; using reference = pair<const key_type&, mapped_type&>; using const_reference = pair<const key_type&, const mapped_type&>; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements]using const_iterator = implementation-defined; // see [container.requirements]using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; class value_compare {private: key_compare comp; // exposition onlyconstexpr value_compare(key_compare c) : comp(c) { } // exposition onlypublic:constexpr bool operator()(const_reference x, const_reference y) const {return comp(x.first, y.first); }}; struct containers { key_container_type keys; mapped_container_type values; }; // [flat.map.cons], constructorsconstexpr flat_map() : flat_map(key_compare()) { }constexpr explicit flat_map(const key_compare& comp): c(), compare(comp) { }constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); constexpr flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); templateconstexpr flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(), compare(comp) { insert(first, last); }templateconstexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(), compare(comp) { insert(sorted_unique, first, last); }template<container-compatible-range<value_type> R>constexpr flat_map(from_range_t, R&& rg): flat_map(from_range, std::forward(rg), key_compare()) { }template<container-compatible-range<value_type> R>constexpr flat_map(from_range_t, R&& rg, const key_compare& comp): flat_map(comp) { insert_range(std::forward(rg)); }constexpr flat_map(initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_map(il.begin(), il.end(), comp) { }constexpr flat_map(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_map(sorted_unique, il.begin(), il.end(), comp) { }// [flat.map.cons.alloc], constructors with allocatorstemplateconstexpr explicit flat_map(const Alloc& a); templateconstexpr flat_map(const key_compare& comp, const Alloc& a); templateconstexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); templateconstexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_map(sorted_unique_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); templateconstexpr flat_map(sorted_unique_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_map(const flat_map&, const Alloc& a); templateconstexpr flat_map(flat_map&&, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_map(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_map(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); templateconstexpr flat_map(initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_map(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); templateconstexpr flat_map(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_map(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a); constexpr flat_map& operator=(initializer_list<value_type>); // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // [flat.map.capacity], capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // [flat.map.access], element accessconstexpr mapped_type& operator[](const key_type& x); constexpr mapped_type& operator[](key_type&& x); template constexpr mapped_type& operator[](K&& x); constexpr mapped_type& at(const key_type& x); constexpr const mapped_type& at(const key_type& x) const; template constexpr mapped_type& at(const K& x); template constexpr const mapped_type& at(const K& x) const; // [flat.map.modifiers], modifierstemplate<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args); template<class... Args>constexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr pair<iterator, bool> insert(const value_type& x){ return emplace(x); }constexpr pair<iterator, bool> insert(value_type&& x){ return emplace(std::move(x)); }constexpr iterator insert(const_iterator position, const value_type& x){ return emplace_hint(position, x); }constexpr iterator insert(const_iterator position, value_type&& x){ return emplace_hint(position, std::move(x)); }template constexpr pair<iterator, bool> insert(P&& x); templateconstexpr iterator insert(const_iterator position, P&&); templateconstexpr void insert(InputIterator first, InputIterator last); templateconstexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list<value_type> il){ insert(il.begin(), il.end()); }constexpr void insert(sorted_unique_t, initializer_list<value_type> il){ insert(sorted_unique, il.begin(), il.end()); }constexpr containers extract() &&; constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); template<class... Args>constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args>constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class K, class... Args>constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class... Args>constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args>constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); template<class K, class... Args>constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args); templateconstexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); templateconstexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class K, class M>constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj); templateconstexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); templateconstexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); template<class K, class M>constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); constexpr iterator erase(iterator position); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(flat_map& y) noexcept; constexpr void clear() noexcept; // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; constexpr const key_container_type& keys() const noexcept { return c.keys; }constexpr const mapped_container_type& values() const noexcept { return c.values; }// map operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair<iterator, iterator> equal_range(const key_type& x); constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template constexpr pair<iterator, iterator> equal_range(const K& x); templateconstexpr pair<const_iterator, const_iterator> equal_range(const K& x) const; friend constexpr bool operator==(const flat_map& x, const flat_map& y); friend constexpr synth-three-way-result<value_type>operator<=>(const flat_map& x, const flat_map& y); friend constexpr void swap(flat_map& x, flat_map& y) noexcept{ x.swap(y); }private: containers c; // exposition only key_compare compare; // exposition onlystruct key-equiv { // exposition onlyconstexpr key-equiv(key_compare c) : comp(c) { }constexpr bool operator()(const_reference x, const_reference y) const {return !comp(x.first, y.first) && !comp(y.first, x.first); } key_compare comp; }; }; template<class KeyContainer, class MappedContainer, class Compare = less> flat_map(KeyContainer, MappedContainer, Compare = Compare())-> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_map(KeyContainer, MappedContainer, Allocator)-> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_map(KeyContainer, MappedContainer, Compare, Allocator)-> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare = less> flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare = Compare())-> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator)-> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare, Allocator)-> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class InputIterator, class Compare = less<iter-key-type>> flat_map(InputIterator, InputIterator, Compare = Compare())-> flat_map<iter-key-type, iter-mapped-type, Compare>; template<class InputIterator, class Compare = less<iter-key-type>> flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare())-> flat_map<iter-key-type, iter-mapped-type, Compare>; template<ranges::input_range R, class Compare = less<range-key-type>, class Allocator = allocator> flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> flat_map<range-key-type, range-mapped-type, Compare, vector<range-key-type, alloc-rebind<Allocator, range-key-type>>, vector<range-mapped-type, alloc-rebind<Allocator, range-mapped-type>>>; template<ranges::input_range R, class Allocator> flat_map(from_range_t, R&&, Allocator)-> flat_map<range-key-type, range-mapped-type, less<range-key-type>, vector<range-key-type, alloc-rebind<Allocator, range-key-type>>, vector<range-mapped-type, alloc-rebind<Allocator, range-mapped-type>>>; template<class Key, class T, class Compare = less> flat_map(initializer_list<pair<Key, T>>, Compare = Compare())-> flat_map<Key, T, Compare>; template<class Key, class T, class Compare = less> flat_map(sorted_unique_t, initializer_list<pair<Key, T>>, Compare = Compare())-> flat_map<Key, T, Compare>; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator>struct uses_allocator<flat_map<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>: bool_constant<uses_allocator_v<KeyContainer, Allocator> && uses_allocator_v<MappedContainer, Allocator>> { };}
The member type containers has the data members and special members specified above.
It has no base classes or members other than those specified.
23.6.8.3 Constructors [flat.map.cons]
constexpr flat_map(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializesc.keys with std::move(key_cont),c.values with std::move(mapped_cont), andcompare with comp; sorts the range [begin(), end()) with respect to value_comp(); and finally erases the duplicate elements as if by:auto zv = views::zip(c.keys, c.values);auto it = ranges::unique(zv, key-equiv(compare)).begin();auto dist = distance(zv.begin(), it);c.keys.erase(c.keys.begin() + dist, c.keys.end());c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: Linear in N if the container arguments are already sorted with respect to value_comp() and otherwise NlogN, where N is the value of key_cont.size() before this call.
constexpr flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializesc.keys with std::move(key_cont),c.values with std::move(mapped_cont), andcompare with comp.
Complexity: Constant.
23.6.8.4 Constructors with allocators [flat.map.cons.alloc]
The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<key_container_type, Alloc> is true and uses_allocator_v<mapped_container_type, Alloc> is true.
template<class Alloc> constexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> constexpr flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_map(key_cont, mapped_cont) andflat_map(key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_map(key_cont, mapped_cont) andflat_map(key_cont, mapped_cont, comp), respectively.
template<class Alloc> constexpr flat_map(sorted_unique_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> constexpr flat_map(sorted_unique_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_map(sorted_unique, key_cont, mapped_cont) andflat_map(sorted_unique, key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> constexpr explicit flat_map(const Alloc& a); template<class Alloc> constexpr flat_map(const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_map(const flat_map&, const Alloc& a); template<class Alloc> constexpr flat_map(flat_map&&, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_map(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_map(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_map(from_range_t, R&& rg, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_map(initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_map(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_map(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_map(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
23.6.8.5 Capacity [flat.map.capacity]
constexpr size_type size() const noexcept;
Returns: c.keys.size().
constexpr size_type max_size() const noexcept;
Returns: min<size_type>(c.keys.max_size(), c.values.max_size()).
23.6.8.6 Access [flat.map.access]
constexpr mapped_type& operator[](const key_type& x);
Effects: Equivalent to: return try_emplace(x).first->second;
constexpr mapped_type& operator[](key_type&& x);
Effects: Equivalent to: return try_emplace(std::move(x)).first->second;
template<class K> constexpr mapped_type& operator[](K&& x);
Constraints: The qualified-id Compare::is_transparent is valid and denotes a type.
Effects: Equivalent to: return try_emplace(std::forward(x)).first->second;
constexpr mapped_type& at(const key_type& x); constexpr const mapped_type& at(const key_type& x) const;
Returns: A reference to the mapped_type corresponding to x in *this.
Throws: An exception object of type out_of_range if no such element is present.
Complexity: Logarithmic.
template<class K> constexpr mapped_type& at(const K& x); template<class K> constexpr const mapped_type& at(const K& x) const;
Constraints: The qualified-id Compare::is_transparent is valid and denotes a type.
Preconditions: The expression find(x) is well-formed and has well-defined behavior.
Returns: A reference to the mapped_type corresponding tox in *this.
Throws: An exception object of type out_of_range if no such element is present.
Complexity: Logarithmic.
23.6.8.7 Modifiers [flat.map.modifiers]
template<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args);
Constraints: is_constructible_v<pair<key_type, mapped_type>, Args...> is true.
Effects: Initializes an object t of type pair<key_type, mapped_type> with std::forward(args)...; if the map already contains an element whose key is equivalent to t.first,*this is unchanged.
Otherwise, equivalent to:auto key_it = ranges::upper_bound(c.keys, t.first, compare);auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);c.keys.insert(key_it, std::move(t.first));c.values.insert(value_it, std::move(t.second));
Returns: The bool component of the returned pair is true if and only if the insertion took place, and the iterator component of the pair points to the element with key equivalent to t.first.
template<class P> constexpr pair<iterator, bool> insert(P&& x); template<class P> constexpr iterator insert(const_iterator position, P&& x);
Constraints: is_constructible_v<pair<key_type, mapped_type>, P> is true.
Effects: The first form is equivalent to return emplace(std::forward
(x));.
The second form is equivalent toreturn emplace_hint(position, std::forward
(x));.
template<class InputIterator> constexpr void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by:for (; first != last; ++first) { value_type value = *first; c.keys.insert(c.keys.end(), std::move(value.first)); c.values.insert(c.values.end(), std::move(value.second));}
Then, sorts the range of newly inserted elements with respect to value_comp(); merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by:auto zv = views::zip(c.keys, c.values);auto it = ranges::unique(zv, key-equiv(compare)).begin();auto dist = distance(zv.begin(), it);c.keys.erase(c.keys.begin() + dist, c.keys.end());c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: N + MlogM, where N is size() before the operation andM is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
Effects: Adds elements to c as if by:for (; first != last; ++first) { value_type value = *first; c.keys.insert(c.keys.end(), std::move(value.first)); c.values.insert(c.values.end(), std::move(value.second));}
Then, merges the sorted range of newly added elements and the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by:auto zv = views::zip(c.keys, c.values);auto it = ranges::unique(zv, key-equiv(compare)).begin();auto dist = distance(zv.begin(), it);c.keys.erase(c.keys.begin() + dist, c.keys.end());c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: Linear in N, where N is size() after the operation.
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R> constexpr void insert_range(R&& rg);
Effects: Adds elements to c as if by:for (const auto& e : rg) {c.keys.insert(c.keys.end(), e.first); c.values.insert(c.values.end(), e.second);}
Then, sorts the range of newly inserted elements with respect to value_comp(); merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by:auto zv = views::zip(c.keys, c.values);auto it = ranges::unique(zv, key-equiv(compare)).begin();auto dist = distance(zv.begin(), it);c.keys.erase(c.keys.begin() + dist, c.keys.end());c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: N + MlogM, where N is size() before the operation andM is ranges::distance(rg).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class... Args> constexpr pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> constexpr pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class... Args> constexpr iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args> constexpr iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
Constraints: is_constructible_v<mapped_type, Args...> is true.
Effects: If the map already contains an element whose key is equivalent to k,*this and args... are unchanged.
Otherwise equivalent to:auto key_it = ranges::upper_bound(c.keys, k, compare);auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);c.keys.insert(key_it, std::forward<decltype(k)>(k));c.values.emplace(value_it, std::forward(args)...);
Returns: In the first two overloads, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace for the first two overloads, and the same as emplace_hint for the last two overloads.
template<class K, class... Args> constexpr pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class K, class... Args> constexpr iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
Constraints:
-
The qualified-id Compare::is_transparent is valid and denotes a type.
-
is_constructible_v<key_type, K> is true.
-
is_constructible_v<mapped_type, Args...> is true.
-
For the first overload,is_convertible_v<K&&, const_iterator> andis_convertible_v<K&&, iterator> are both false.
Preconditions: The conversion from k into key_type constructs an object u, for which find(k) == find(u) is true.
Effects: If the map already contains an element whose key is equivalent to k,*this and args... are unchanged.
Otherwise equivalent to:auto key_it = upper_bound(c.keys.begin(), c.keys.end(), k, compare);auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);c.keys.emplace(key_it, std::forward(k));c.values.emplace(value_it, std::forward(args)...);
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class M> constexpr pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> constexpr pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class M> constexpr iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M> constexpr iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
Constraints: is_assignable_v<mapped_type&, M> is true andis_constructible_v<mapped_type, M> is true.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std::forward(obj) to e.second.
Otherwise, equivalent totry_emplace(std::forward<decltype(k)>(k), std::forward(obj)) for the first two overloads ortry_emplace(hint, std::forward<decltype(k)>(k), std::forward(obj)) for the last two overloads.
Returns: In the first two overloads, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace for the first two overloads and the same as emplace_hint for the last two overloads.
template<class K, class M> constexpr pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class K, class M> constexpr iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
Constraints:
-
The qualified-id Compare::is_transparent is valid and denotes a type.
-
is_constructible_v<key_type, K> is true.
-
is_assignable_v<mapped_type&, M> is true.
-
is_constructible_v<mapped_type, M> is true.
Preconditions: The conversion from k into key_type constructs an object u, for which find(k) == find(u) is true.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std::forward(obj) to e.second.
Otherwise, equivalent totry_emplace(std::forward(k), std::forward(obj)) for the first overload ortry_emplace(hint, std::forward(k), std::forward(obj)) for the second overload.
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
constexpr void swap(flat_map& y) noexcept;
Effects: Equivalent to:ranges::swap(compare, y.compare); ranges::swap(c.keys, y.c.keys); ranges::swap(c.values, y.c.values);
constexpr containers extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std::move(c).
constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);
Preconditions: key_cont.size() == mapped_cont.size() is true, the elements of key_cont are sorted with respect to compare, andkey_cont contains no equal elements.
Effects: Equivalent to:c.keys = std::move(key_cont);c.values = std::move(mapped_cont);
23.6.8.8 Erasure [flat.map.erasure]
template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> constexpr typename flat_map<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_map<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
Preconditions: Key and T meet the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(pair<const Key&, const T&>(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception,c is in a valid but unspecified state ([defns.valid]).
[Note 1:
c still meets its invariants, but can be empty.
â end note]
23.6.9 Class template flat_multimap [flat.multimap]
23.6.9.1 Overview [flat.multimap.overview]
A flat_multimap is a container adaptor that provides an associative container interface that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of values of another type T based on the keys.
flat_multimap supports iterators that meet the Cpp17InputIterator requirements and model therandom_access_iterator concept ([iterator.concept.random.access]).
A flat_multimap meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_multimap meets the requirements of an associative container ([associative.reqmts]), except that:
it does not meet the requirements related to node handles ([container.node]),
it does not meet the requirements related to iterator invalidation, and
the time complexity of the operations that insert or erase a single element from the map is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_multimap does not meet the additional requirements of an allocator-aware container ([container.alloc.reqmts]).
â end note]
A flat_multimap also provides most operations described in [associative.reqmts] for equal keys.
This means that a flat_multimap supports the a_eq operations in [associative.reqmts] but not the a_uniq operations.
For a flat_multimap<Key, T> the key_type is Key and the value_type is pair<Key, T>.
Except as otherwise noted, operations on flat_multimap are equivalent to those of flat_map, except that flat_multimap operations do not remove or replace elements with equal keys.
[Example 1:
flat_multimap constructors and emplace do not erase non-unique elements after sorting them.
â end example]
A flat_multimap maintains the following invariants:
it contains the same number of keys and values;
the keys are sorted with respect to the comparison object; and
the value at offset off within the value container is the value associated with the key at offset off within the key container.
If any member function in [flat.multimap.defn] exits via an exception, the invariants are restored.
[Note 2:
This can result in the flat_multimap being emptied.
â end note]
Any type C that meets the sequence container requirements ([sequence.reqmts]) can be used to instantiate flat_multimap, as long asC::iterator meets the Cpp17RandomAccessIterator requirements and invocations of member functions C::size and C::max_size do not exit via an exception.
In particular,vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector is not a sequence container.
â end note]
The program is ill-formed ifKey is not the same type as KeyContainer::value_type orT is not the same type as MappedContainer::value_type.
The effect of calling a constructor that takes both key_container_type andmapped_container_type arguments with containers of different sizes is undefined.
The effect of calling a constructor or member function that takes a sorted_equivalent_t argument with a container, containers, or range that are not sorted with respect to key_comp() is undefined.
The types iterator and const_iterator meet the constexpr iterator requirements ([iterator.requirements.general]).
23.6.9.2 Definition [flat.multimap.defn]
namespace std {template<class Key, class T, class Compare = less, class KeyContainer = vector, class MappedContainer = vector>class flat_multimap {public:// typesusing key_type = Key; using mapped_type = T; using value_type = pair<key_type, mapped_type>; using key_compare = Compare; using reference = pair<const key_type&, mapped_type&>; using const_reference = pair<const key_type&, const mapped_type&>; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements]using const_iterator = implementation-defined; // see [container.requirements]using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; class value_compare {private: key_compare comp; // exposition onlyconstexpr value_compare(key_compare c) : comp(c) { } // exposition onlypublic:constexpr bool operator()(const_reference x, const_reference y) const {return comp(x.first, y.first); }}; struct containers { key_container_type keys; mapped_container_type values; }; // [flat.multimap.cons], constructorsconstexpr flat_multimap() : flat_multimap(key_compare()) { }constexpr explicit flat_multimap(const key_compare& comp): c(), compare(comp) { }constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); constexpr flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); templateconstexpr flat_multimap(InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(), compare(comp){ insert(first, last); }templateconstexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(), compare(comp) { insert(sorted_equivalent, first, last); }template<container-compatible-range<value_type> R>constexpr flat_multimap(from_range_t, R&& rg): flat_multimap(from_range, std::forward(rg), key_compare()) { }template<container-compatible-range<value_type> R>constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp): flat_multimap(comp) { insert_range(std::forward(rg)); }constexpr flat_multimap(initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_multimap(il.begin(), il.end(), comp) { }constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_multimap(sorted_equivalent, il.begin(), il.end(), comp) { }// [flat.multimap.cons.alloc], constructors with allocatorstemplateconstexpr explicit flat_multimap(const Alloc& a); templateconstexpr flat_multimap(const key_compare& comp, const Alloc& a); templateconstexpr flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); templateconstexpr flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); templateconstexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_multimap(const flat_multimap&, const Alloc& a); templateconstexpr flat_multimap(flat_multimap&&, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multimap(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); templateconstexpr flat_multimap(initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_multimap(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); templateconstexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
flat_multimap& operator=(initializer_list<value_type>); // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // modifierstemplate<class... Args> constexpr iterator emplace(Args&&... args); template<class... Args>constexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr iterator insert(const value_type& x){ return emplace(x); }constexpr iterator insert(value_type&& x){ return emplace(std::move(x)); }constexpr iterator insert(const_iterator position, const value_type& x){ return emplace_hint(position, x); }constexpr iterator insert(const_iterator position, value_type&& x){ return emplace_hint(position, std::move(x)); }template constexpr iterator insert(P&& x); templateconstexpr iterator insert(const_iterator position, P&&); templateconstexpr void insert(InputIterator first, InputIterator last); templateconstexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list<value_type> il){ insert(il.begin(), il.end()); }constexpr void insert(sorted_equivalent_t, initializer_list<value_type> il){ insert(sorted_equivalent, il.begin(), il.end()); }constexpr containers extract() &&; constexpr void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); constexpr iterator erase(iterator position); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(flat_multimap&) noexcept; constexpr void clear() noexcept; // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; constexpr const key_container_type& keys() const noexcept { return c.keys; }constexpr const mapped_container_type& values() const noexcept { return c.values; }// map operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair<iterator, iterator> equal_range(const key_type& x); constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const; templateconstexpr pair<iterator, iterator> equal_range(const K& x); templateconstexpr pair<const_iterator, const_iterator> equal_range(const K& x) const; friend constexpr bool operator==(const flat_multimap& x, const flat_multimap& y); friend constexpr synth-three-way-result<value_type>operator<=>(const flat_multimap& x, const flat_multimap& y); friend constexpr void swap(flat_multimap& x, flat_multimap& y) noexcept{ x.swap(y); }private: containers c; // exposition only key_compare compare; // exposition only}; template<class KeyContainer, class MappedContainer, class Compare = less> flat_multimap(KeyContainer, MappedContainer, Compare = Compare())-> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_multimap(KeyContainer, MappedContainer, Allocator)-> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_multimap(KeyContainer, MappedContainer, Compare, Allocator)-> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare = less> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare = Compare())-> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator)-> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare, Allocator)-> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class InputIterator, class Compare = less<iter-key-type>> flat_multimap(InputIterator, InputIterator, Compare = Compare())-> flat_multimap<iter-key-type, iter-mapped-type, Compare>; template<class InputIterator, class Compare = less<iter-key-type>> flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare())-> flat_multimap<iter-key-type, iter-mapped-type, Compare>; template<ranges::input_range R, class Compare = less<range-key-type>, class Allocator = allocator> flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> flat_multimap<range-key-type, range-mapped-type, Compare, vector<range-key-type, alloc-rebind<Allocator, range-key-type>>, vector<range-mapped-type, alloc-rebind<Allocator, range-mapped-type>>>; template<ranges::input_range R, class Allocator> flat_multimap(from_range_t, R&&, Allocator)-> flat_multimap<range-key-type, range-mapped-type, less<range-key-type>, vector<range-key-type, alloc-rebind<Allocator, range-key-type>>, vector<range-mapped-type, alloc-rebind<Allocator, range-mapped-type>>>; template<class Key, class T, class Compare = less> flat_multimap(initializer_list<pair<Key, T>>, Compare = Compare())-> flat_multimap<Key, T, Compare>; template<class Key, class T, class Compare = less> flat_multimap(sorted_equivalent_t, initializer_list<pair<Key, T>>, Compare = Compare())-> flat_multimap<Key, T, Compare>; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator>struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>: bool_constant<uses_allocator_v<KeyContainer, Allocator> && uses_allocator_v<MappedContainer, Allocator>> { };}
The member type containers has the data members and special members specified above.
It has no base classes or members other than those specified.
23.6.9.3 Constructors [flat.multimap.cons]
constexpr flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializesc.keys with std::move(key_cont),c.values with std::move(mapped_cont), andcompare with comp; sorts the range [begin(), end()) with respect to value_comp().
Complexity: Linear in N if the container arguments are already sorted with respect to value_comp() and otherwise NlogN, where N is the value of key_cont.size() before this call.
constexpr flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializesc.keys with std::move(key_cont),c.values with std::move(mapped_cont), andcompare with comp.
Complexity: Constant.
23.6.9.4 Constructors with allocators [flat.multimap.cons.alloc]
The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<key_container_type, Alloc> is true and uses_allocator_v<mapped_container_type, Alloc> is true.
template<class Alloc> constexpr flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> constexpr flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multimap(key_cont, mapped_cont) andflat_multimap(key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_multimap(key_cont, mapped_cont) andflat_multimap(key_cont, mapped_cont, comp), respectively.
template<class Alloc> constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> constexpr flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multimap(sorted_equivalent, key_cont, mapped_cont) andflat_multimap(sorted_equivalent, key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> constexpr explicit flat_multimap(const Alloc& a); template<class Alloc> constexpr flat_multimap(const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_multimap(const flat_multimap&, const Alloc& a); template<class Alloc> constexpr flat_multimap(flat_multimap&&, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multimap(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_multimap(from_range_t, R&& rg, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_multimap(initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_multimap(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
23.6.9.5 Erasure [flat.multimap.erasure]
template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> constexpr typename flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
Preconditions: Key and T meet the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(pair<const Key&, const T&>(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception,c is in a valid but unspecified state ([defns.valid]).
[Note 1:
c still meets its invariants, but can be empty.
â end note]
23.6.10 Header <flat_set> synopsis [flat.set.syn]
#include // see [compare.syn]#include <initializer_list> // see [initializer.list.syn]namespace std {// [flat.set], class template flat_settemplate<class Key, class Compare = less, class KeyContainer = vector>class flat_set; struct sorted_unique_t { explicit sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique{}; template<class Key, class Compare, class KeyContainer, class Allocator>struct uses_allocator<flat_set<Key, Compare, KeyContainer>, Allocator>; // [flat.set.erasure], erasure for flat_settemplate<class Key, class Compare, class KeyContainer, class Predicate>constexpr typename flat_set<Key, Compare, KeyContainer>::size_type erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred); // [flat.multiset], class template flat_multisettemplate<class Key, class Compare = less, class KeyContainer = vector>class flat_multiset; struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; inline constexpr sorted_equivalent_t sorted_equivalent{}; template<class Key, class Compare, class KeyContainer, class Allocator>struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator>; // [flat.multiset.erasure], erasure for flat_multisettemplate<class Key, class Compare, class KeyContainer, class Predicate>constexpr typename flat_multiset<Key, Compare, KeyContainer>::size_type erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);}
23.6.11 Class template flat_set [flat.set]
23.6.11.1 Overview [flat.set.overview]
A flat_set is a container adaptor that provides an associative container interface that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of the keys themselves.
flat_set supports iterators that model the random_access_iterator concept ([iterator.concept.random.access]).
A flat_set meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_set meets the requirements of an associative container ([associative.reqmts]), except that:
it does not meet the requirements related to node handles ([container.node.overview]),
it does not meet the requirements related to iterator invalidation, and
the time complexity of the operations that insert or erase a single element from the set is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_set does not meet the additional requirements of an allocator-aware container, as described in [container.alloc.reqmts].
â end note]
A flat_set also provides most operations described in [associative.reqmts] for unique keys.
This means that a flat_set supports the a_uniq operations in [associative.reqmts] but not the a_eq operations.
For a flat_set, both the key_type and value_type are Key.
Descriptions are provided here only for operations on flat_set that are not described in one of those sets of requirements or for operations where there is additional semantic information.
A flat_set maintains the invariant that the keys are sorted with respect to the comparison object.
If any member function in [flat.set.defn] exits via an exception, the invariant is restored.
[Note 2:
This can result in the flat_set's being emptied.
â end note]
Any sequence container ([sequence.reqmts]) supporting Cpp17RandomAccessIterator can be used to instantiate flat_set.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector is not a sequence container.
â end note]
The program is ill-formed if Key is not the same type as KeyContainer::value_type.
The effect of calling a constructor or member function that takes a sorted_unique_t argument with a range that is not sorted with respect to key_comp(), or that contains equal elements, is undefined.
The types iterator and const_iterator meet the constexpr iterator requirements ([iterator.requirements.general]).
23.6.11.2 Definition [flat.set.defn]
namespace std {template<class Key, class Compare = less, class KeyContainer = vector>class flat_set {public:// typesusing key_type = Key; using value_type = Key; using key_compare = Compare; using value_compare = Compare; using reference = value_type&; using const_reference = const value_type&; using size_type = typename KeyContainer::size_type; using difference_type = typename KeyContainer::difference_type; using iterator = implementation-defined; // see [container.requirements]using const_iterator = implementation-defined; // see [container.requirements]using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using container_type = KeyContainer; // [flat.set.cons], constructorsconstexpr flat_set() : flat_set(key_compare()) { }constexpr explicit flat_set(const key_compare& comp): c(), compare(comp) { }constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare()); constexpr flat_set(sorted_unique_t, container_type cont, const key_compare& comp = key_compare()): c(std::move(cont)), compare(comp) { }templateconstexpr flat_set(InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(), compare(comp){ insert(first, last); }templateconstexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(first, last), compare(comp) { }template<container-compatible-range<value_type> R>constexpr flat_set(from_range_t, R&& rg): flat_set(from_range, std::forward(rg), key_compare()) { }template<container-compatible-range<value_type> R>constexpr flat_set(from_range_t, R&& rg, const key_compare& comp): flat_set(comp){ insert_range(std::forward(rg)); }constexpr flat_set(initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_set(il.begin(), il.end(), comp) { }constexpr flat_set(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_set(sorted_unique, il.begin(), il.end(), comp) { }// [flat.set.cons.alloc], constructors with allocatorstemplateconstexpr explicit flat_set(const Alloc& a); templateconstexpr flat_set(const key_compare& comp, const Alloc& a); templateconstexpr flat_set(const container_type& cont, const Alloc& a); templateconstexpr flat_set(const container_type& cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_set(sorted_unique_t, const container_type& cont, const Alloc& a); templateconstexpr flat_set(sorted_unique_t, const container_type& cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_set(const flat_set&, const Alloc& a); templateconstexpr flat_set(flat_set&&, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_set(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_set(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); templateconstexpr flat_set(initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_set(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); templateconstexpr flat_set(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_set(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a); constexpr flat_set& operator=(initializer_list<value_type>); // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // [flat.set.modifiers], modifierstemplate<class... Args> constexpr pair<iterator, bool> emplace(Args&&... args); template<class... Args>constexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr pair<iterator, bool> insert(const value_type& x){ return emplace(x); }constexpr pair<iterator, bool> insert(value_type&& x){ return emplace(std::move(x)); }template constexpr pair<iterator, bool> insert(K&& x); constexpr iterator insert(const_iterator position, const value_type& x){ return emplace_hint(position, x); }constexpr iterator insert(const_iterator position, value_type&& x){ return emplace_hint(position, std::move(x)); }template constexpr iterator insert(const_iterator hint, K&& x); templateconstexpr void insert(InputIterator first, InputIterator last); templateconstexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list<value_type> il){ insert(il.begin(), il.end()); }constexpr void insert(sorted_unique_t, initializer_list<value_type> il){ insert(sorted_unique, il.begin(), il.end()); }constexpr container_type extract() &&; constexpr void replace(container_type&&); constexpr iterator erase(iterator position); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(flat_set& y) noexcept; constexpr void clear() noexcept; // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; // set operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair<iterator, iterator> equal_range(const key_type& x); constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const; templateconstexpr pair<iterator, iterator> equal_range(const K& x); templateconstexpr pair<const_iterator, const_iterator> equal_range(const K& x) const; friend constexpr bool operator==(const flat_set& x, const flat_set& y); friend constexpr synth-three-way-result<value_type>operator<=>(const flat_set& x, const flat_set& y); friend constexpr void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); }private: container_type c; // exposition only key_compare compare; // exposition only}; template<class KeyContainer, class Compare = less> flat_set(KeyContainer, Compare = Compare())-> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_set(KeyContainer, Allocator)-> flat_set<typename KeyContainer::value_type, less, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_set(KeyContainer, Compare, Allocator)-> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Compare = less> flat_set(sorted_unique_t, KeyContainer, Compare = Compare())-> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_set(sorted_unique_t, KeyContainer, Allocator)-> flat_set<typename KeyContainer::value_type, less, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_set(sorted_unique_t, KeyContainer, Compare, Allocator)-> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class InputIterator, class Compare = less<iter-value-type>> flat_set(InputIterator, InputIterator, Compare = Compare())-> flat_set<iter-value-type, Compare>; template<class InputIterator, class Compare = less<iter-value-type>> flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare())-> flat_set<iter-value-type, Compare>; template<ranges::input_range R, class Compare = less<ranges::range_value_t>, class Allocator = allocator<ranges::range_value_t>> flat_set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> flat_set<ranges::range_value_t, Compare, vector<ranges::range_value_t, alloc-rebind<Allocator, ranges::range_value_t>>>; template<ranges::input_range R, class Allocator> flat_set(from_range_t, R&&, Allocator)-> flat_set<ranges::range_value_t, less<ranges::range_value_t>, vector<ranges::range_value_t, alloc-rebind<Allocator, ranges::range_value_t>>>; template<class Key, class Compare = less> flat_set(initializer_list, Compare = Compare())-> flat_set<Key, Compare>; template<class Key, class Compare = less> flat_set(sorted_unique_t, initializer_list, Compare = Compare())-> flat_set<Key, Compare>; template<class Key, class Compare, class KeyContainer, class Allocator>struct uses_allocator<flat_set<Key, Compare, KeyContainer>, Allocator>: bool_constant<uses_allocator_v<KeyContainer, Allocator>> { };}
23.6.11.3 Constructors [flat.set.cons]
constexpr explicit flat_set(container_type cont, const key_compare& comp = key_compare());
Effects: Initializes c with std::move(cont) andcompare with comp, sorts the range [begin(), end()) with respect to compare, and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: Linear in N if cont is already sorted with respect to compare and otherwise NlogN, where N is the value of cont.size() before this call.
23.6.11.4 Constructors with allocators [flat.set.cons.alloc]
The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<container_type, Alloc> is true.
template<class Alloc> constexpr flat_set(const container_type& cont, const Alloc& a); template<class Alloc> constexpr flat_set(const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent toflat_set(cont) and flat_set(cont, comp), respectively, except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_set(cont) and flat_set(cont, comp), respectively.
template<class Alloc> constexpr flat_set(sorted_unique_t, const container_type& cont, const Alloc& a); template<class Alloc> constexpr flat_set(sorted_unique_t, const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent toflat_set(sorted_unique, cont) andflat_set(sorted_unique, cont,
comp), respectively,
except that c is constructed with
uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> constexpr explicit flat_set(const Alloc& a); template<class Alloc> constexpr flat_set(const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_set(const flat_set&, const Alloc& a); template<class Alloc> constexpr flat_set(flat_set&&, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_set(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_set(from_range_t, R&& rg, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_set(initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_set(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_set(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_set(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
23.6.11.5 Modifiers [flat.set.modifiers]
template<class K> constexpr pair<iterator, bool> insert(K&& x); template<class K> constexpr iterator insert(const_iterator hint, K&& x);
Constraints: The qualified-id Compare::is_transparent is valid and denotes a type.
is_constructible_v<value_type, K> is true.
Preconditions: The conversion from x into value_type constructs an object u, for which find(x) == find(u) is true.
Effects: If the set already contains an element equivalent to x,*this and x are unchanged.
Otherwise, inserts a new element as if by emplace(std::forward(x)).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the element whose key is equivalent to x.
template<class InputIterator> constexpr void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by:c.insert(c.end(), first, last);
Then, sorts the range of newly inserted elements with respect to compare; merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: N + MlogM, where N is size() before the operation andM is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
Effects: Equivalent to insert(first, last).
Complexity: Linear.
template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R> constexpr void insert_range(R&& rg);
Effects: Adds elements to c as if by:for (const auto& e : rg) {c.insert(c.end(), e);}
Then, sorts the range of newly inserted elements with respect to compare; merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: N + MlogM, where N is size() before the operation and M is ranges::distance(rg).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
constexpr void swap(flat_set& y) noexcept;
Effects: Equivalent to:ranges::swap(compare, y.compare); ranges::swap(c, y.c);
constexpr container_type extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std::move(c).
constexpr void replace(container_type&& cont);
Preconditions: The elements of cont are sorted with respect to compare, andcont contains no equal elements.
Effects: Equivalent to: c = std::move(cont);
23.6.11.6 Erasure [flat.set.erasure]
template<class Key, class Compare, class KeyContainer, class Predicate> constexpr typename flat_set<Key, Compare, KeyContainer>::size_type erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred);
Preconditions: Key meets the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(as_const(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception,c is in a valid but unspecified state ([defns.valid]).
[Note 1:
c still meets its invariants, but can be empty.
â end note]
23.6.12 Class template flat_multiset [flat.multiset]
23.6.12.1 Overview [flat.multiset.overview]
A flat_multiset is a container adaptor that provides an associative container interface that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of the keys themselves.
flat_multiset supports iterators that model therandom_access_iterator concept ([iterator.concept.random.access]).
A flat_multiset meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_multiset meets the requirements of an associative container ([associative.reqmts]), except that:
it does not meet the requirements related to node handles ([container.node.overview]),
it does not meet the requirements related to iterator invalidation, and
the time complexity of the operations that insert or erase a single element from the set is linear, including the ones that take an insertion position iterator.
[Note 1:
A flat_multiset does not meet the additional requirements of an allocator-aware container, as described in [container.alloc.reqmts].
â end note]
A flat_multiset also provides most operations described in [associative.reqmts] for equal keys.
This means that a flat_multiset supports the a_eq operations in [associative.reqmts] but not the a_uniq operations.
For a flat_multiset, both the key_type and value_type are Key.
Descriptions are provided here only for operations on flat_multiset that are not described in one of the general sections or for operations where there is additional semantic information.
A flat_multiset maintains the invariant that the keys are sorted with respect to the comparison object.
If any member function in [flat.multiset.defn] exits via an exception, the invariant is restored.
[Note 2:
This can result in the flat_multiset's being emptied.
â end note]
Any sequence container ([sequence.reqmts]) supporting Cpp17RandomAccessIterator can be used to instantiate flat_multiset.
In particular,vector ([vector]) and deque ([deque]) can be used.
[Note 3:
vector is not a sequence container.
â end note]
The program is ill-formed if Key is not the same type as KeyContainer::value_type.
The effect of calling a constructor or member function that takes a sorted_equivalent_t argument with a range that is not sorted with respect to key_comp() is undefined.
The types iterator and const_iterator meet the constexpr iterator requirements ([iterator.requirements.general]).
23.6.12.2 Definition [flat.multiset.defn]
namespace std {template<class Key, class Compare = less, class KeyContainer = vector>class flat_multiset {public:// typesusing key_type = Key; using value_type = Key; using key_compare = Compare; using value_compare = Compare; using reference = value_type&; using const_reference = const value_type&; using size_type = typename KeyContainer::size_type; using difference_type = typename KeyContainer::difference_type; using iterator = implementation-defined; // see [container.requirements]using const_iterator = implementation-defined; // see [container.requirements]using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using container_type = KeyContainer; // [flat.multiset.cons], constructorsconstexpr flat_multiset() : flat_multiset(key_compare()) { }constexpr explicit flat_multiset(const key_compare& comp): c(), compare(comp) { }constexpr explicit flat_multiset(container_type cont, const key_compare& comp = key_compare()); constexpr flat_multiset(sorted_equivalent_t, container_type cont, const key_compare& comp = key_compare()): c(std::move(cont)), compare(comp) { }templateconstexpr flat_multiset(InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(), compare(comp){ insert(first, last); }templateconstexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()): c(first, last), compare(comp) { }template<container-compatible-range<value_type> R>constexpr flat_multiset(from_range_t, R&& rg): flat_multiset(from_range, std::forward(rg), key_compare()) { }template<container-compatible-range<value_type> R>constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp): flat_multiset(comp){ insert_range(std::forward(rg)); }constexpr flat_multiset(initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_multiset(il.begin(), il.end(), comp) { }constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp = key_compare()): flat_multiset(sorted_equivalent, il.begin(), il.end(), comp) { }// [flat.multiset.cons.alloc], constructors with allocatorstemplateconstexpr explicit flat_multiset(const Alloc& a); templateconstexpr flat_multiset(const key_compare& comp, const Alloc& a); templateconstexpr flat_multiset(const container_type& cont, const Alloc& a); templateconstexpr flat_multiset(const container_type& cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const Alloc& a); templateconstexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const key_compare& comp, const Alloc& a); templateconstexpr flat_multiset(const flat_multiset&, const Alloc& a); templateconstexpr flat_multiset(flat_multiset&&, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multiset(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multiset(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc>constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc>constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); templateconstexpr flat_multiset(initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_multiset(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); templateconstexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); templateconstexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a); constexpr flat_multiset& operator=(initializer_list<value_type>); // iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacityconstexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // [flat.multiset.modifiers], modifierstemplate<class... Args> constexpr iterator emplace(Args&&... args); template<class... Args>constexpr iterator emplace_hint(const_iterator position, Args&&... args); constexpr iterator insert(const value_type& x){ return emplace(x); }constexpr iterator insert(value_type&& x){ return emplace(std::move(x)); }constexpr iterator insert(const_iterator position, const value_type& x){ return emplace_hint(position, x); }constexpr iterator insert(const_iterator position, value_type&& x){ return emplace_hint(position, std::move(x)); }templateconstexpr void insert(InputIterator first, InputIterator last); templateconstexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R>constexpr void insert_range(R&& rg); constexpr void insert(initializer_list<value_type> il){ insert(il.begin(), il.end()); }constexpr void insert(sorted_equivalent_t, initializer_list<value_type> il){ insert(sorted_equivalent, il.begin(), il.end()); }constexpr container_type extract() &&; constexpr void replace(container_type&&); constexpr iterator erase(iterator position); constexpr iterator erase(const_iterator position); constexpr size_type erase(const key_type& x); template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(flat_multiset& y) noexcept; constexpr void clear() noexcept; // observersconstexpr key_compare key_comp() const; constexpr value_compare value_comp() const; // set operationsconstexpr iterator find(const key_type& x); constexpr const_iterator find(const key_type& x) const; template constexpr iterator find(const K& x); template constexpr const_iterator find(const K& x) const; constexpr size_type count(const key_type& x) const; template constexpr size_type count(const K& x) const; constexpr bool contains(const key_type& x) const; template constexpr bool contains(const K& x) const; constexpr iterator lower_bound(const key_type& x); constexpr const_iterator lower_bound(const key_type& x) const; template constexpr iterator lower_bound(const K& x); template constexpr const_iterator lower_bound(const K& x) const; constexpr iterator upper_bound(const key_type& x); constexpr const_iterator upper_bound(const key_type& x) const; template constexpr iterator upper_bound(const K& x); template constexpr const_iterator upper_bound(const K& x) const; constexpr pair<iterator, iterator> equal_range(const key_type& x); constexpr pair<const_iterator, const_iterator> equal_range(const key_type& x) const; templateconstexpr pair<iterator, iterator> equal_range(const K& x); templateconstexpr pair<const_iterator, const_iterator> equal_range(const K& x) const; friend constexpr bool operator==(const flat_multiset& x, const flat_multiset& y); friend constexpr synth-three-way-result<value_type>operator<=>(const flat_multiset& x, const flat_multiset& y); friend constexpr void swap(flat_multiset& x, flat_multiset& y) noexcept{ x.swap(y); }private: container_type c; // exposition only key_compare compare; // exposition only}; template<class KeyContainer, class Compare = less> flat_multiset(KeyContainer, Compare = Compare())-> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_multiset(KeyContainer, Allocator)-> flat_multiset<typename KeyContainer::value_type, less, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_multiset(KeyContainer, Compare, Allocator)-> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Compare = less> flat_multiset(sorted_equivalent_t, KeyContainer, Compare = Compare())-> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_multiset(sorted_equivalent_t, KeyContainer, Allocator)-> flat_multiset<typename KeyContainer::value_type, less, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_multiset(sorted_equivalent_t, KeyContainer, Compare, Allocator)-> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class InputIterator, class Compare = less<iter-value-type>> flat_multiset(InputIterator, InputIterator, Compare = Compare())-> flat_multiset<iter-value-type, Compare>; template<class InputIterator, class Compare = less<iter-value-type>> flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare())-> flat_multiset<iter-value-type, Compare>; template<ranges::input_range R, class Compare = less<ranges::range_value_t>, class Allocator = allocator<ranges::range_value_t>> flat_multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator())-> flat_multiset<ranges::range_value_t, Compare, vector<ranges::range_value_t, alloc-rebind<Allocator, ranges::range_value_t>>>; template<ranges::input_range R, class Allocator> flat_multiset(from_range_t, R&&, Allocator)-> flat_multiset<ranges::range_value_t, less<ranges::range_value_t>, vector<ranges::range_value_t, alloc-rebind<Allocator, ranges::range_value_t>>>; template<class Key, class Compare = less> flat_multiset(initializer_list, Compare = Compare())-> flat_multiset<Key, Compare>; template<class Key, class Compare = less> flat_multiset(sorted_equivalent_t, initializer_list, Compare = Compare())-> flat_multiset<Key, Compare>; template<class Key, class Compare, class KeyContainer, class Allocator>struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator>: bool_constant<uses_allocator_v<KeyContainer, Allocator>> { };}
23.6.12.3 Constructors [flat.multiset.cons]
constexpr explicit flat_multiset(container_type cont, const key_compare& comp = key_compare());
Effects: Initializes c with std::move(cont) andcompare with comp, and sorts the range [begin(), end()) with respect to compare.
Complexity: Linear in N if cont is already sorted with respect to compare and otherwise NlogN, where N is the value of cont.size() before this call.
23.6.12.4 Constructors with allocators [flat.multiset.cons.alloc]
The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<container_type, Alloc> is true.
template<class Alloc> constexpr flat_multiset(const container_type& cont, const Alloc& a); template<class Alloc> constexpr flat_multiset(const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multiset(cont) andflat_multiset(cont, comp), respectively, except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_multiset(cont) andflat_multiset(cont, comp), respectively.
template<class Alloc> constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const Alloc& a); template<class Alloc> constexpr flat_multiset(sorted_equivalent_t, const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multiset(sorted_equivalent, cont) andflat_multiset(sorted_equivalent, cont, comp), respectively, except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> constexpr explicit flat_multiset(const Alloc& a); template<class Alloc> constexpr flat_multiset(const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_multiset(const flat_multiset&, const Alloc& a); template<class Alloc> constexpr flat_multiset(flat_multiset&&, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multiset(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multiset(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> constexpr flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_multiset(from_range_t, R&& rg, const Alloc& a); template<[container-compatible-range](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<value_type> R, class Alloc> constexpr flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_multiset(initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_multiset(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> constexpr flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
23.6.12.5 Modifiers [flat.multiset.modifiers]
template<class... Args> constexpr iterator emplace(Args&&... args);
Constraints: is_constructible_v<value_type, Args...> is true.
Effects: First, initializes an object t of type value_type with std::forward(args)..., then inserts t as if by:auto it = ranges::upper_bound(c, t, compare);c.insert(it, std::move(t));
Returns: An iterator that points to the inserted element.
template<class InputIterator> constexpr void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by:c.insert(c.end(), first, last);
Then, sorts the range of newly inserted elements with respect to compare, and merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range.
Complexity: N + MlogM, where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
Effects: Equivalent to insert(first, last).
Complexity: Linear.
constexpr void swap(flat_multiset& y) noexcept;
Effects: Equivalent to:ranges::swap(compare, y.compare); ranges::swap(c, y.c);
constexpr container_type extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std::move(c).
constexpr void replace(container_type&& cont);
Preconditions: The elements of cont are sorted with respect to compare.
Effects: Equivalent to: c = std::move(cont);
23.6.12.6 Erasure [flat.multiset.erasure]
template<class Key, class Compare, class KeyContainer, class Predicate> constexpr typename flat_multiset<Key, Compare, KeyContainer>::size_type erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
Preconditions: Key meets the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(as_const(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception,c is in a valid but unspecified state ([defns.valid]).
[Note 1:
c still meets its invariants, but can be empty.
â end note]
23.6.13 Container adaptors formatting [container.adaptors.format]
For each ofqueue,priority_queue, andstack, the library provides the following formatter specialization where adaptor-type is the name of the template:
namespace std {template<class charT, class T, formattable Container, class... U>struct formatter<adaptor-type<T, Container, U...>, charT> {private:using maybe-const-container = // exposition only**fmt-maybe-const<Container, charT>; using maybe-const-adaptor = // exposition only**maybe-const<is_const_v<maybe-const-container>, // see [ranges.syn]adaptor-type<T, Container, U...>>; formatter<ranges::ref_view<maybe-const-container>, charT> underlying_; // exposition onlypublic:templateconstexpr typename ParseContext::iterator parse(ParseContext& ctx); templatetypename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const; };}
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(r.c, ctx);