From abbb2262a6bdb5b581b64bcb40325998e307f809 Mon Sep 17 00:00:00 2001 From: Eisenwave Date: Sat, 15 Nov 2025 11:21:47 +0100 Subject: [PATCH] P3567R2 flat_meow fixes --- source/containers.tex | 168 ++++++++++++++++++++++++++++++++++++------ source/support.tex | 4 +- 2 files changed, 149 insertions(+), 23 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 148d3de34e..3c5966b2b5 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -17033,7 +17033,9 @@ \pnum If any member function in \ref{flat.map.defn} exits via an exception -the invariants are restored. +the invariants of the object argument are restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_map} being emptied. \end{note} @@ -17118,6 +17120,11 @@ // \ref{flat.map.cons}, constructors constexpr flat_map() : flat_map(key_compare()) { } + flat_map(const flat_map&); + flat_map(flat_map&&); + flat_map& operator=(const flat_map&); + flat_map& operator=(flat_map&&); + constexpr explicit flat_map(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -17258,6 +17265,8 @@ constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(sorted_unique_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -17298,7 +17307,7 @@ 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 swap(flat_map& y) noexcept(@\seebelow@); constexpr void clear() noexcept; // observers @@ -17341,7 +17350,7 @@ friend constexpr @\exposid{synth-three-way-result}@ operator<=>(const flat_map& x, const flat_map& y); - friend constexpr void swap(flat_map& x, flat_map& y) noexcept + friend constexpr void swap(flat_map& x, flat_map& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } private: @@ -17816,10 +17825,10 @@ \effects Adds elements to \exposid{c} as if by: \begin{codeblock} -for (const auto& e : rg) { - @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), e.first); - @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), e.second); -} +ranges::for_each(rg, [&](value_type e) { + @\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(e.first)); + @\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(e.second)); +}); \end{codeblock} Then, sorts the range of newly inserted elements with respect to \tcode{value_comp()}; @@ -17845,6 +17854,22 @@ Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} +\indexlibrarymember{insert_range}{flat_map}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void insert_range(sorted_unique_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{insert_range(rg)}. + +\pnum +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. +\end{itemdescr} + \indexlibrarymember{try_emplace}{flat_map}% \begin{itemdecl} template @@ -18047,7 +18072,10 @@ \indexlibrarymember{swap}{flat_map}% \begin{itemdecl} -constexpr void swap(flat_map& y) noexcept; +constexpr void swap(flat_map& y) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v && + is_nothrow_swappable_v); \end{itemdecl} \begin{itemdescr} @@ -18209,7 +18237,9 @@ \pnum If any member function in \ref{flat.multimap.defn} exits via an exception, -the invariants are restored. +the invariants of the object argument are restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_multimap} being emptied. \end{note} @@ -18292,6 +18322,11 @@ // \ref{flat.multimap.cons}, constructors constexpr flat_multimap() : flat_multimap(key_compare()) { } + flat_multimap(const flat_multimap&); + flat_multimap(flat_multimap&&); + flat_multimap& operator=(const flat_multimap&); + flat_multimap& operator=(flat_multimap&&); + constexpr explicit flat_multimap(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -18425,6 +18460,8 @@ constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(sorted_unique_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -18440,7 +18477,10 @@ template constexpr size_type erase(K&& x); constexpr iterator erase(const_iterator first, const_iterator last); - constexpr void swap(flat_multimap&) noexcept; + constexpr void swap(flat_multimap&) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v && + is_nothrow_swappable_v); constexpr void clear() noexcept; // observers @@ -18484,7 +18524,8 @@ friend constexpr @\exposid{synth-three-way-result}@ operator<=>(const flat_multimap& x, const flat_multimap& y); - friend constexpr void swap(flat_multimap& x, flat_multimap& y) noexcept + friend constexpr void swap(flat_multimap& x, flat_multimap& y) + noexcept(noexcept(x.swap(y))) { x.swap(y); } private: @@ -18852,7 +18893,9 @@ \pnum If any member function in \ref{flat.set.defn} exits via an exception, -the invariant is restored. +the invariant of the object argument is restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_set}'s being emptied. \end{note} @@ -18906,6 +18949,11 @@ // \ref{flat.set.cons}, constructors constexpr flat_set() : flat_set(key_compare()) { } + flat_set(const flat_set&); + flat_set(flat_set&&); + flat_set& operator=(const flat_set&); + flat_set& operator=(flat_set&&); + constexpr explicit flat_set(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -19031,6 +19079,8 @@ constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(sorted_unique_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -19359,9 +19409,9 @@ \effects Adds elements to \exposid{c} as if by: \begin{codeblock} -for (const auto& e : rg) { - @\exposid{c}@.insert(@\exposid{c}@.end(), e); -} +ranges::for_each(rg, [&](auto&& e) { + @\exposid{c}@.insert(@\exposid{c}@.end(), std::forward(e)); +}); \end{codeblock} Then, sorts the range of newly inserted elements with respect to \exposid{compare}; @@ -19380,9 +19430,27 @@ Since this operation performs an in-place merge, it may allocate memory. \end{itemdescr} +\indexlibrarymember{insert_range}{flat_set}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void insert_range(sorted_unique_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{insert_range(rg)}. + +\pnum +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. +\end{itemdescr} + \indexlibrarymember{swap}{flat_set}% \begin{itemdecl} -constexpr void swap(flat_set& y) noexcept; +constexpr void swap(flat_set& y) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v); \end{itemdecl} \begin{itemdescr} @@ -19522,7 +19590,9 @@ \pnum If any member function in \ref{flat.multiset.defn} exits via an exception, -the invariant is restored. +the invariant of the object argument is restored. +For the move constructor and move assignment operator, +the invariants of both arguments are restored. \begin{note} This can result in the \tcode{flat_multiset}'s being emptied. \end{note} @@ -19575,6 +19645,11 @@ // \ref{flat.multiset.cons}, constructors constexpr flat_multiset() : flat_multiset(key_compare()) { } + flat_multiset(const flat_multiset&); + flat_multiset(flat_multiset&&); + flat_multiset& operator=(const flat_multiset&); + flat_multiset& operator=(flat_multiset&&); + constexpr explicit flat_multiset(const key_compare& comp) : @\exposid{c}@(), @\exposid{compare}@(comp) { } @@ -19702,6 +19777,8 @@ constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<@\exposconcept{container-compatible-range}@ R> constexpr void insert_range(R&& rg); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(sorted_unique_t, R&& rg); constexpr void insert(initializer_list il) { insert(il.begin(), il.end()); } @@ -19717,7 +19794,7 @@ 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 swap(flat_multiset& y) noexcept(@\seebelow@); constexpr void clear() noexcept; // observers @@ -19758,7 +19835,8 @@ friend constexpr @\exposid{synth-three-way-result}@ operator<=>(const flat_multiset& x, const flat_multiset& y); - friend constexpr void swap(flat_multiset& x, flat_multiset& y) noexcept + friend constexpr void swap(flat_multiset& x, flat_multiset& y) + noexcept(noexcept(x.swap(y))) { x.swap(y); } private: @@ -20005,12 +20083,60 @@ \pnum \complexity -Linear. +Linear in $N$, where $N$ is \tcode{size()} after the operation. +\end{itemdescr} + +\indexlibrarymember{insert_range}{flat_multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Adds elements to \exposid{c} as if by: +\begin{codeblock} +ranges::for_each(rg, [&](auto&& e) { + @\exposid{c}@.insert(@\exposid{c}@.end(), std::forward(e)); +}); +\end{codeblock} +Then, sorts the range of newly inserted elements with respect to \exposid{compare}, +and merges the resulting sorted range and +the sorted range of pre-existing elements into a single sorted range. + +\pnum +\complexity +$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$ +is \tcode{ranges::distance(rg)}. + +\pnum +\remarks +Since this operation performs an in-place merge, +it may allocate memory. +\end{itemdescr} + +\indexlibrarymember{insert_range}{flat_multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void insert_range(sorted_unique_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{insert_range(rg)}. + +\pnum +\complexity +Linear in $N$, where $N$ is \tcode{size()} after the operation. \end{itemdescr} \indexlibrarymember{swap}{flat_multiset}% \begin{itemdecl} -constexpr void swap(flat_multiset& y) noexcept; +constexpr void swap(flat_multiset& y) + noexcept(is_nothrow_swappable_v && + is_nothrow_swappable_v); \end{itemdecl} \begin{itemdescr} diff --git a/source/support.tex b/source/support.tex index c6929d58ff..ef8f03faae 100644 --- a/source/support.tex +++ b/source/support.tex @@ -673,8 +673,8 @@ #define @\defnlibxname{cpp_lib_execution}@ 201902L // also in \libheader{execution} #define @\defnlibxname{cpp_lib_expected}@ 202211L // also in \libheader{expected} #define @\defnlibxname{cpp_lib_filesystem}@ 201703L // also in \libheader{filesystem} -#define @\defnlibxname{cpp_lib_flat_map}@ 202207L // also in \libheader{flat_map} -#define @\defnlibxname{cpp_lib_flat_set}@ 202207L // also in \libheader{flat_set} +#define @\defnlibxname{cpp_lib_flat_map}@ 202511L // also in \libheader{flat_map} +#define @\defnlibxname{cpp_lib_flat_set}@ 202511L // also in \libheader{flat_set} #define @\defnlibxname{cpp_lib_format}@ 202311L // also in \libheader{format} #define @\defnlibxname{cpp_lib_format_path}@ 202506L // also in \libheader{filesystem} #define @\defnlibxname{cpp_lib_format_ranges}@ 202207L // also in \libheader{format}