Skip to content

Commit abfbf8f

Browse files
authored
Merge 2025-11 LWG Motion 4
P3567R2 `flat_meow` fixes
2 parents 72039ac + 1e42c87 commit abfbf8f

File tree

2 files changed

+152
-25
lines changed

2 files changed

+152
-25
lines changed

source/containers.tex

Lines changed: 150 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17052,7 +17052,9 @@
1705217052

1705317053
\pnum
1705417054
If any member function in \ref{flat.map.defn} exits via an exception
17055-
the invariants are restored.
17055+
the invariants of the object argument are restored.
17056+
For the move constructor and move assignment operator,
17057+
the invariants of both arguments are restored.
1705617058
\begin{note}
1705717059
This can result in the \tcode{flat_map} being emptied.
1705817060
\end{note}
@@ -17137,6 +17139,11 @@
1713717139
// \ref{flat.map.cons}, constructors
1713817140
constexpr flat_map() : flat_map(key_compare()) { }
1713917141

17142+
constexpr flat_map(const flat_map&);
17143+
constexpr flat_map(flat_map&&);
17144+
constexpr flat_map& operator=(const flat_map&);
17145+
constexpr flat_map& operator=(flat_map&&);
17146+
1714017147
constexpr explicit flat_map(const key_compare& comp)
1714117148
: @\exposid{c}@(), @\exposid{compare}@(comp) { }
1714217149

@@ -17277,6 +17284,8 @@
1727717284
constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
1727817285
template<@\exposconcept{container-compatible-range}@<value_type> R>
1727917286
constexpr void insert_range(R&& rg);
17287+
template<@\exposconcept{container-compatible-range}@<value_type> R>
17288+
constexpr void insert_range(sorted_unique_t, R&& rg);
1728017289

1728117290
constexpr void insert(initializer_list<value_type> il)
1728217291
{ insert(il.begin(), il.end()); }
@@ -17317,7 +17326,7 @@
1731717326
template<class K> constexpr size_type erase(K&& x);
1731817327
constexpr iterator erase(const_iterator first, const_iterator last);
1731917328

17320-
constexpr void swap(flat_map& y) noexcept;
17329+
constexpr void swap(flat_map& y) noexcept(@\seebelow@);
1732117330
constexpr void clear() noexcept;
1732217331

1732317332
// observers
@@ -17360,7 +17369,7 @@
1736017369
friend constexpr @\exposid{synth-three-way-result}@<value_type>
1736117370
operator<=>(const flat_map& x, const flat_map& y);
1736217371

17363-
friend constexpr void swap(flat_map& x, flat_map& y) noexcept
17372+
friend constexpr void swap(flat_map& x, flat_map& y) noexcept(noexcept(x.swap(y)))
1736417373
{ x.swap(y); }
1736517374

1736617375
private:
@@ -17835,10 +17844,10 @@
1783517844
\effects
1783617845
Adds elements to \exposid{c} as if by:
1783717846
\begin{codeblock}
17838-
for (const auto& e : rg) {
17839-
@\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), e.first);
17840-
@\exposid{c}@.values.insert(@\exposid{c}@.values.end(), e.second);
17841-
}
17847+
ranges::for_each(rg, [&](value_type e) {
17848+
@\exposid{c}@.keys.insert(@\exposid{c}@.keys.end(), std::move(e.first));
17849+
@\exposid{c}@.values.insert(@\exposid{c}@.values.end(), std::move(e.second));
17850+
});
1784217851
\end{codeblock}
1784317852
Then, sorts the range of newly inserted elements
1784417853
with respect to \tcode{value_comp()};
@@ -17864,6 +17873,22 @@
1786417873
Since this operation performs an in-place merge, it may allocate memory.
1786517874
\end{itemdescr}
1786617875

17876+
\indexlibrarymember{insert_range}{flat_map}%
17877+
\begin{itemdecl}
17878+
template<@\exposconcept{container-compatible-range}@<value_type> R>
17879+
constexpr void insert_range(sorted_unique_t, R&& rg);
17880+
\end{itemdecl}
17881+
17882+
\begin{itemdescr}
17883+
\pnum
17884+
\effects
17885+
Equivalent to \tcode{insert_range(rg)}.
17886+
17887+
\pnum
17888+
\complexity
17889+
Linear in $N$, where $N$ is \tcode{size()} after the operation.
17890+
\end{itemdescr}
17891+
1786717892
\indexlibrarymember{try_emplace}{flat_map}%
1786817893
\begin{itemdecl}
1786917894
template<class... Args>
@@ -18066,7 +18091,10 @@
1806618091

1806718092
\indexlibrarymember{swap}{flat_map}%
1806818093
\begin{itemdecl}
18069-
constexpr void swap(flat_map& y) noexcept;
18094+
constexpr void swap(flat_map& y)
18095+
noexcept(is_nothrow_swappable_v<key_container_type> &&
18096+
is_nothrow_swappable_v<mapped_container_type> &&
18097+
is_nothrow_swappable_v<key_compare>);
1807018098
\end{itemdecl}
1807118099

1807218100
\begin{itemdescr}
@@ -18228,7 +18256,9 @@
1822818256

1822918257
\pnum
1823018258
If any member function in \ref{flat.multimap.defn} exits via an exception,
18231-
the invariants are restored.
18259+
the invariants of the object argument are restored.
18260+
For the move constructor and move assignment operator,
18261+
the invariants of both arguments are restored.
1823218262
\begin{note}
1823318263
This can result in the \tcode{flat_multimap} being emptied.
1823418264
\end{note}
@@ -18311,6 +18341,11 @@
1831118341
// \ref{flat.multimap.cons}, constructors
1831218342
constexpr flat_multimap() : flat_multimap(key_compare()) { }
1831318343

18344+
constexpr flat_multimap(const flat_multimap&);
18345+
constexpr flat_multimap(flat_multimap&&);
18346+
constexpr flat_multimap& operator=(const flat_multimap&);
18347+
constexpr flat_multimap& operator=(flat_multimap&&);
18348+
1831418349
constexpr explicit flat_multimap(const key_compare& comp)
1831518350
: @\exposid{c}@(), @\exposid{compare}@(comp) { }
1831618351

@@ -18444,6 +18479,8 @@
1844418479
constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
1844518480
template<@\exposconcept{container-compatible-range}@<value_type> R>
1844618481
constexpr void insert_range(R&& rg);
18482+
template<@\exposconcept{container-compatible-range}@<value_type> R>
18483+
constexpr void insert_range(sorted_equivalent_t, R&& rg);
1844718484

1844818485
constexpr void insert(initializer_list<value_type> il)
1844918486
{ insert(il.begin(), il.end()); }
@@ -18459,7 +18496,10 @@
1845918496
template<class K> constexpr size_type erase(K&& x);
1846018497
constexpr iterator erase(const_iterator first, const_iterator last);
1846118498

18462-
constexpr void swap(flat_multimap&) noexcept;
18499+
constexpr void swap(flat_multimap&)
18500+
noexcept(is_nothrow_swappable_v<key_container_type> &&
18501+
is_nothrow_swappable_v<mapped_container_type> &&
18502+
is_nothrow_swappable_v<key_compare>);
1846318503
constexpr void clear() noexcept;
1846418504

1846518505
// observers
@@ -18503,7 +18543,8 @@
1850318543
friend constexpr @\exposid{synth-three-way-result}@<value_type>
1850418544
operator<=>(const flat_multimap& x, const flat_multimap& y);
1850518545

18506-
friend constexpr void swap(flat_multimap& x, flat_multimap& y) noexcept
18546+
friend constexpr void swap(flat_multimap& x, flat_multimap& y)
18547+
noexcept(noexcept(x.swap(y)))
1850718548
{ x.swap(y); }
1850818549

1850918550
private:
@@ -18871,7 +18912,9 @@
1887118912

1887218913
\pnum
1887318914
If any member function in \ref{flat.set.defn} exits via an exception,
18874-
the invariant is restored.
18915+
the invariant of the object argument is restored.
18916+
For the move constructor and move assignment operator,
18917+
the invariants of both arguments are restored.
1887518918
\begin{note}
1887618919
This can result in the \tcode{flat_set}'s being emptied.
1887718920
\end{note}
@@ -18925,6 +18968,11 @@
1892518968
// \ref{flat.set.cons}, constructors
1892618969
constexpr flat_set() : flat_set(key_compare()) { }
1892718970

18971+
constexpr flat_set(const flat_set&);
18972+
constexpr flat_set(flat_set&&);
18973+
constexpr flat_set& operator=(const flat_set&);
18974+
constexpr flat_set& operator=(flat_set&&);
18975+
1892818976
constexpr explicit flat_set(const key_compare& comp)
1892918977
: @\exposid{c}@(), @\exposid{compare}@(comp) { }
1893018978

@@ -19050,6 +19098,8 @@
1905019098
constexpr void insert(sorted_unique_t, InputIterator first, InputIterator last);
1905119099
template<@\exposconcept{container-compatible-range}@<value_type> R>
1905219100
constexpr void insert_range(R&& rg);
19101+
template<@\exposconcept{container-compatible-range}@<value_type> R>
19102+
constexpr void insert_range(sorted_unique_t, R&& rg);
1905319103

1905419104
constexpr void insert(initializer_list<value_type> il)
1905519105
{ insert(il.begin(), il.end()); }
@@ -19065,7 +19115,7 @@
1906519115
template<class K> constexpr size_type erase(K&& x);
1906619116
constexpr iterator erase(const_iterator first, const_iterator last);
1906719117

19068-
constexpr void swap(flat_set& y) noexcept;
19118+
constexpr void swap(flat_set& y) noexcept(@\seebelow@);
1906919119
constexpr void clear() noexcept;
1907019120

1907119121
// observers
@@ -19106,7 +19156,8 @@
1910619156
friend constexpr @\exposid{synth-three-way-result}@<value_type>
1910719157
operator<=>(const flat_set& x, const flat_set& y);
1910819158

19109-
friend constexpr void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); }
19159+
friend constexpr void swap(flat_set& x, flat_set& y) noexcept(noexcept(x.swap(y)))
19160+
{ x.swap(y); }
1911019161

1911119162
private:
1911219163
container_type @\exposidnc{c}@; // \expos
@@ -19378,9 +19429,9 @@
1937819429
\effects
1937919430
Adds elements to \exposid{c} as if by:
1938019431
\begin{codeblock}
19381-
for (const auto& e : rg) {
19382-
@\exposid{c}@.insert(@\exposid{c}@.end(), e);
19383-
}
19432+
ranges::for_each(rg, [&](auto&& e) {
19433+
@\exposid{c}@.insert(@\exposid{c}@.end(), std::forward<decltype(e)>(e));
19434+
});
1938419435
\end{codeblock}
1938519436
Then,
1938619437
sorts the range of newly inserted elements with respect to \exposid{compare};
@@ -19399,9 +19450,27 @@
1939919450
Since this operation performs an in-place merge, it may allocate memory.
1940019451
\end{itemdescr}
1940119452

19453+
\indexlibrarymember{insert_range}{flat_set}%
19454+
\begin{itemdecl}
19455+
template<@\exposconcept{container-compatible-range}@<value_type> R>
19456+
constexpr void insert_range(sorted_unique_t, R&& rg);
19457+
\end{itemdecl}
19458+
19459+
\begin{itemdescr}
19460+
\pnum
19461+
\effects
19462+
Equivalent to \tcode{insert_range(rg)}.
19463+
19464+
\pnum
19465+
\complexity
19466+
Linear in $N$, where $N$ is \tcode{size()} after the operation.
19467+
\end{itemdescr}
19468+
1940219469
\indexlibrarymember{swap}{flat_set}%
1940319470
\begin{itemdecl}
19404-
constexpr void swap(flat_set& y) noexcept;
19471+
constexpr void swap(flat_set& y)
19472+
noexcept(is_nothrow_swappable_v<container_type> &&
19473+
is_nothrow_swappable_v<key_compare>);
1940519474
\end{itemdecl}
1940619475

1940719476
\begin{itemdescr}
@@ -19541,7 +19610,9 @@
1954119610

1954219611
\pnum
1954319612
If any member function in \ref{flat.multiset.defn} exits via an exception,
19544-
the invariant is restored.
19613+
the invariant of the object argument is restored.
19614+
For the move constructor and move assignment operator,
19615+
the invariants of both arguments are restored.
1954519616
\begin{note}
1954619617
This can result in the \tcode{flat_multiset}'s being emptied.
1954719618
\end{note}
@@ -19594,6 +19665,11 @@
1959419665
// \ref{flat.multiset.cons}, constructors
1959519666
constexpr flat_multiset() : flat_multiset(key_compare()) { }
1959619667

19668+
constexpr flat_multiset(const flat_multiset&);
19669+
constexpr flat_multiset(flat_multiset&&);
19670+
constexpr flat_multiset& operator=(const flat_multiset&);
19671+
constexpr flat_multiset& operator=(flat_multiset&&);
19672+
1959719673
constexpr explicit flat_multiset(const key_compare& comp)
1959819674
: @\exposid{c}@(), @\exposid{compare}@(comp) { }
1959919675

@@ -19721,6 +19797,8 @@
1972119797
constexpr void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
1972219798
template<@\exposconcept{container-compatible-range}@<value_type> R>
1972319799
constexpr void insert_range(R&& rg);
19800+
template<@\exposconcept{container-compatible-range}@<value_type> R>
19801+
constexpr void insert_range(sorted_equivalent_t, R&& rg);
1972419802

1972519803
constexpr void insert(initializer_list<value_type> il)
1972619804
{ insert(il.begin(), il.end()); }
@@ -19736,7 +19814,7 @@
1973619814
template<class K> constexpr size_type erase(K&& x);
1973719815
constexpr iterator erase(const_iterator first, const_iterator last);
1973819816

19739-
constexpr void swap(flat_multiset& y) noexcept;
19817+
constexpr void swap(flat_multiset& y) noexcept(@\seebelow@);
1974019818
constexpr void clear() noexcept;
1974119819

1974219820
// observers
@@ -19777,7 +19855,8 @@
1977719855
friend constexpr @\exposid{synth-three-way-result}@<value_type>
1977819856
operator<=>(const flat_multiset& x, const flat_multiset& y);
1977919857

19780-
friend constexpr void swap(flat_multiset& x, flat_multiset& y) noexcept
19858+
friend constexpr void swap(flat_multiset& x, flat_multiset& y)
19859+
noexcept(noexcept(x.swap(y)))
1978119860
{ x.swap(y); }
1978219861

1978319862
private:
@@ -20024,12 +20103,60 @@
2002420103

2002520104
\pnum
2002620105
\complexity
20027-
Linear.
20106+
Linear in $N$, where $N$ is \tcode{size()} after the operation.
20107+
\end{itemdescr}
20108+
20109+
\indexlibrarymember{insert_range}{flat_multiset}%
20110+
\begin{itemdecl}
20111+
template<@\exposconcept{container-compatible-range}@<value_type> R>
20112+
void insert_range(R&& rg);
20113+
\end{itemdecl}
20114+
20115+
\begin{itemdescr}
20116+
\pnum
20117+
\effects
20118+
Adds elements to \exposid{c} as if by:
20119+
\begin{codeblock}
20120+
ranges::for_each(rg, [&](auto&& e) {
20121+
@\exposid{c}@.insert(@\exposid{c}@.end(), std::forward<decltype(e)>(e));
20122+
});
20123+
\end{codeblock}
20124+
Then, sorts the range of newly inserted elements with respect to \exposid{compare},
20125+
and merges the resulting sorted range and
20126+
the sorted range of pre-existing elements into a single sorted range.
20127+
20128+
\pnum
20129+
\complexity
20130+
$N$ + $M \log M$, where $N$ is \tcode{size()} before the operation and $M$
20131+
is \tcode{ranges::distance(rg)}.
20132+
20133+
\pnum
20134+
\remarks
20135+
Since this operation performs an in-place merge,
20136+
it may allocate memory.
20137+
\end{itemdescr}
20138+
20139+
\indexlibrarymember{insert_range}{flat_multiset}%
20140+
\begin{itemdecl}
20141+
template<@\exposconcept{container-compatible-range}@<value_type> R>
20142+
constexpr void insert_range(sorted_equivalent_t, R&& rg);
20143+
\end{itemdecl}
20144+
20145+
\begin{itemdescr}
20146+
\pnum
20147+
\effects
20148+
Equivalent to \tcode{insert_range(rg)}.
20149+
20150+
\pnum
20151+
\complexity
20152+
Linear in $N$, where $N$ is \tcode{size()} after the operation.
2002820153
\end{itemdescr}
2002920154

2003020155
\indexlibrarymember{swap}{flat_multiset}%
2003120156
\begin{itemdecl}
20032-
constexpr void swap(flat_multiset& y) noexcept;
20157+
constexpr void swap(flat_multiset& y)
20158+
noexcept(is_nothrow_swappable_v<container_type> &&
20159+
is_nothrow_swappable_v<key_compare>);
2003320160
\end{itemdecl}
2003420161

2003520162
\begin{itemdescr}

source/support.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,8 @@
674674
#define @\defnlibxname{cpp_lib_execution}@ 201902L // also in \libheader{execution}
675675
#define @\defnlibxname{cpp_lib_expected}@ 202211L // also in \libheader{expected}
676676
#define @\defnlibxname{cpp_lib_filesystem}@ 201703L // also in \libheader{filesystem}
677-
#define @\defnlibxname{cpp_lib_flat_map}@ 202207L // also in \libheader{flat_map}
678-
#define @\defnlibxname{cpp_lib_flat_set}@ 202207L // also in \libheader{flat_set}
677+
#define @\defnlibxname{cpp_lib_flat_map}@ 202511L // also in \libheader{flat_map}
678+
#define @\defnlibxname{cpp_lib_flat_set}@ 202511L // also in \libheader{flat_set}
679679
#define @\defnlibxname{cpp_lib_format}@ 202311L // also in \libheader{format}
680680
#define @\defnlibxname{cpp_lib_format_path}@ 202506L // also in \libheader{filesystem}
681681
#define @\defnlibxname{cpp_lib_format_ranges}@ 202207L // also in \libheader{format}

0 commit comments

Comments
 (0)