Skip to content

Commit c3a973b

Browse files
authored
Merge 2021-10 LWG Motion 13
P2077R3 Heterogeneous erasure overloads for associative containers
2 parents 24a4674 + d9dfc81 commit c3a973b

File tree

3 files changed

+105
-2
lines changed

3 files changed

+105
-2
lines changed

source/compatibility.tex

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,29 @@
9696
std::format("{}", t.bit); // ill-formed, previously returned \tcode{"0"}
9797
\end{codeblock}
9898

99+
\rSec2[diff.cpp20.containers]{\ref{containers}: containers library}
100+
101+
\diffref{associative.reqmts,unord.req}
102+
\change
103+
Heterogeneous \tcode{extract} and \tcode{erase} overloads
104+
for associative containers.
105+
\rationale
106+
Improve efficiency of erasing elements from associative containers.
107+
\effect
108+
Valid \CppXX{} code may fail to compile in this revision of \Cpp{}.
109+
For example:
110+
\begin{codeblock}
111+
struct B {
112+
auto operator<=>(const B&) const = default;
113+
};
114+
115+
struct D : private B {
116+
void f(std::set<B, std::less<>>& s) {
117+
s.erase(*this); // ill formed; previously well-formed
118+
}
119+
};
120+
\end{codeblock}
121+
99122
\rSec1[diff.cpp17]{\Cpp{} and ISO \CppXVII{}}
100123

101124
\rSec2[diff.cpp17.general]{General}

source/containers.tex

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,16 @@
17201720
\tcode{c(r, ke)} and \tcode{!c(ke, r)}, with \tcode{c(r, ke)} implying
17211721
\tcode{!c(ke, r)}.
17221722
\item
1723+
\tcode{kx} is a value such that
1724+
\begin{itemize}
1725+
\item
1726+
\tcode{a} is partitioned with respect to \tcode{c(r, rx)} and \tcode{!c(kx, r)},
1727+
with \tcode{c(r, kx)} implying \tcode{!c(kx, r)}
1728+
\item
1729+
\tcode{kx} is not convertible to
1730+
either \tcode{iterator} or \tcode{const_iterator},
1731+
\end{itemize}
1732+
\item
17231733
\tcode{A} denotes the storage allocator used by \tcode{X}, if any, or \tcode{allocator<X::value_type>} otherwise,
17241734
\item
17251735
\tcode{m} denotes an allocator of a type convertible to \tcode{A},
@@ -2001,6 +2011,14 @@
20012011
\tcode{node_type}. &
20022012
$\log (\tcode{a.size()})$ \\ \rowsep
20032013

2014+
\tcode{a_tran.\brk{}extract(\brk{}kx)} &
2015+
\tcode{node_type} &
2016+
\effects Removes the first element in the container with key \tcode{r}
2017+
such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.\br
2018+
\returns A \tcode{node_type} owning the element if found,
2019+
otherwise an empty \tcode{node_type}. &
2020+
$\log(\tcode{a_tran.size()})$ \\ \rowsep
2021+
20042022
\tcode{a.\brk{}extract(\brk{}q)} &
20052023
\tcode{node_type} &
20062024
\effects Removes the element pointed to by \tcode{q}.\br
@@ -2030,6 +2048,13 @@
20302048
\returns The number of erased elements. &
20312049
$\log (\tcode{a.size()}) + \tcode{a.count(k)}$ \\ \rowsep
20322050

2051+
\tcode{a_tran.\brk{}erase(kx)} &
2052+
\tcode{size_type} &
2053+
\effects Erases all elements in the container with key \tcode{r}
2054+
such that \tcode{!c(r, kx) \&\& !c(kx, r)} is \tcode{true}.\br
2055+
\returns The number of erased elements. &
2056+
$\log(\tcode{a_tran.size())} + \tcode{a_tran.count(kx)}$ \\ \rowsep
2057+
20332058
\tcode{a.erase(q)} &
20342059
\tcode{iterator} &
20352060
\effects Erases the element pointed to by \tcode{q}.\br
@@ -2204,10 +2229,16 @@
22042229
\pnum
22052230
The member function templates
22062231
\tcode{find}, \tcode{count}, \tcode{contains},
2207-
\tcode{lower_bound}, \tcode{upper_bound}, and \tcode{equal_range}
2232+
\tcode{lower_bound}, \tcode{upper_bound}, \tcode{equal_range},
2233+
\tcode{erase}, and \tcode{extract}
22082234
shall not participate in overload resolution unless
22092235
the \grammarterm{qualified-id} \tcode{Compare::is_transparent} is valid
22102236
and denotes a type\iref{temp.deduct}.
2237+
Additionally, the member function templates \tcode{extract} and \tcode{erase}
2238+
shall not participate in overload resolution if
2239+
\tcode{is_convertible_v<K\&\&, iterator> || is_convertible_v<K\&\&, const_iterator>}
2240+
is \tcode{true},
2241+
where \tcode{K} is the type substituted as the first template argument.
22112242

22122243
\pnum
22132244
A deduction guide for an associative container shall not participate in overload resolution
@@ -2428,6 +2459,16 @@
24282459
\end{itemize}
24292460
where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran},
24302461
\item
2462+
\tcode{kx} is a value such that
2463+
\begin{itemize}
2464+
\item \tcode{eq(r1, kx) == eq(kx, r1)},
2465+
\item \tcode{hf(r1) == hf(kx)} if \tcode{eq(r1, kx)} is \tcode{true},
2466+
\item \tcode{(eq(r1, kx) \&\& eq(r1, r2)) == eq(r2, kx)}, and
2467+
\item \tcode{kx} is not convertible to
2468+
either \tcode{iterator} or \tcode{const_iterator}
2469+
\end{itemize}
2470+
where \tcode{r1} and \tcode{r2} are keys of elements in \tcode{a_tran},
2471+
\item
24312472
\tcode{n} denotes a value of type \tcode{size_type},
24322473
\item
24332474
\tcode{z} denotes a value of type \tcode{float}, and
@@ -2813,6 +2854,13 @@
28132854
\tcode{node_type}. &
28142855
Average case \bigoh{1}, worst case \bigoh{\tcode{a.size()}}. \\ \rowsep
28152856
%
2857+
\tcode{a_tran.\brk{}extract(kx)} &
2858+
\tcode{node_type} &
2859+
\effects Removes an element in the container with key equivalent to \tcode{kx}.\br
2860+
\returns A \tcode{node_type} owning the element if found,
2861+
otherwise an empty \tcode{node_type}. &
2862+
Average case \bigoh{1}, worst case \bigoh{\tcode{a_tran.}\br{}\tcode{size()}}. \\ \rowsep
2863+
%
28162864
\tcode{a.extract(q)} &
28172865
\tcode{node_type} &
28182866
\effects Removes the element pointed to by \tcode{q}.\br
@@ -2845,6 +2893,14 @@
28452893
\bigoh{\tcode{a.size()}}.
28462894
\\ \rowsep
28472895
%
2896+
\tcode{a_tran.\brk{}erase(kx)}
2897+
& \tcode{size_type}
2898+
& \effects Erases all elements with key equivalent to \tcode{kx}.\br
2899+
\returns The number of elements erased.
2900+
& Average case \bigoh{\tcode{a_tran.}\br{}\tcode{count(kx)}}, worst case
2901+
\bigoh{\tcode{a_tran.}\br{}\tcode{size()}}.
2902+
\\ \rowsep
2903+
%
28482904
\tcode{a.erase(q)}
28492905
& \tcode{iterator}
28502906
& \effects Erases the element pointed to by \tcode{q}.\br
@@ -3126,12 +3182,18 @@
31263182

31273183
\pnum
31283184
The member function templates
3129-
\tcode{find}, \tcode{count}, \tcode{equal_range}, and \tcode{contains}
3185+
\tcode{find}, \tcode{count}, \tcode{equal_range}, \tcode{contains},
3186+
\tcode{extract}, and \tcode{erase}
31303187
shall not participate in overload resolution unless
31313188
the \grammarterm{qualified-id}s
31323189
\tcode{Pred::is_transparent} and
31333190
\tcode{Hash::is_transparent}
31343191
are both valid and denote types\iref{temp.deduct}.
3192+
Additionally, the member function templates \tcode{extract} and \tcode{erase}
3193+
shall not participate in overload resolution if
3194+
\tcode{is_convertible_v<K\&\&, iterator> || is_convertible_v<K\&\&, const_iterator>}
3195+
is \tcode{true},
3196+
where \tcode{K} is the type substituted as the first template argument.
31353197

31363198
\pnum
31373199
A deduction guide for an unordered associative container shall not participate in overload resolution
@@ -6674,6 +6736,7 @@
66746736

66756737
node_type extract(const_iterator position);
66766738
node_type extract(const key_type& x);
6739+
template<class K> node_type extract(K&& x);
66776740
insert_return_type insert(node_type&& nh);
66786741
iterator insert(const_iterator hint, node_type&& nh);
66796742

@@ -6697,6 +6760,7 @@
66976760
iterator erase(iterator position);
66986761
iterator erase(const_iterator position);
66996762
size_type erase(const key_type& x);
6763+
template<class K> size_type erase(K&& x);
67006764
iterator erase(const_iterator first, const_iterator last);
67016765
void swap(map&)
67026766
noexcept(allocator_traits<Allocator>::is_always_equal::value &&
@@ -7213,12 +7277,14 @@
72137277

72147278
node_type extract(const_iterator position);
72157279
node_type extract(const key_type& x);
7280+
template<class K> node_type extract(K&& x);
72167281
iterator insert(node_type&& nh);
72177282
iterator insert(const_iterator hint, node_type&& nh);
72187283

72197284
iterator erase(iterator position);
72207285
iterator erase(const_iterator position);
72217286
size_type erase(const key_type& x);
7287+
template<class K> size_type erase(K&& x);
72227288
iterator erase(const_iterator first, const_iterator last);
72237289
void swap(multimap&)
72247290
noexcept(allocator_traits<Allocator>::is_always_equal::value &&
@@ -7513,12 +7579,14 @@
75137579

75147580
node_type extract(const_iterator position);
75157581
node_type extract(const key_type& x);
7582+
template<class K> node_type extract(K&& x);
75167583
insert_return_type insert(node_type&& nh);
75177584
iterator insert(const_iterator hint, node_type&& nh);
75187585

75197586
iterator erase(iterator position);
75207587
iterator erase(const_iterator position);
75217588
size_type erase(const key_type& x);
7589+
template<class K> size_type erase(K&& x);
75227590
iterator erase(const_iterator first, const_iterator last);
75237591
void swap(set&)
75247592
noexcept(allocator_traits<Allocator>::is_always_equal::value &&
@@ -7787,12 +7855,14 @@
77877855

77887856
node_type extract(const_iterator position);
77897857
node_type extract(const key_type& x);
7858+
template<class K> node_type extract(K&& x);
77907859
iterator insert(node_type&& nh);
77917860
iterator insert(const_iterator hint, node_type&& nh);
77927861

77937862
iterator erase(iterator position);
77947863
iterator erase(const_iterator position);
77957864
size_type erase(const key_type& x);
7865+
template<class K> size_type erase(K&& x);
77967866
iterator erase(const_iterator first, const_iterator last);
77977867
void swap(multiset&)
77987868
noexcept(allocator_traits<Allocator>::is_always_equal::value &&
@@ -8216,6 +8286,7 @@
82168286

82178287
node_type extract(const_iterator position);
82188288
node_type extract(const key_type& x);
8289+
template<class K> node_type extract(K&& x);
82198290
insert_return_type insert(node_type&& nh);
82208291
iterator insert(const_iterator hint, node_type&& nh);
82218292

@@ -8239,6 +8310,7 @@
82398310
iterator erase(iterator position);
82408311
iterator erase(const_iterator position);
82418312
size_type erase(const key_type& k);
8313+
template<class K> size_type erase(K&& x);
82428314
iterator erase(const_iterator first, const_iterator last);
82438315
void swap(unordered_map&)
82448316
noexcept(allocator_traits<Allocator>::is_always_equal::value &&
@@ -8811,12 +8883,14 @@
88118883

88128884
node_type extract(const_iterator position);
88138885
node_type extract(const key_type& x);
8886+
template<class K> node_type extract(K&& x);
88148887
iterator insert(node_type&& nh);
88158888
iterator insert(const_iterator hint, node_type&& nh);
88168889

88178890
iterator erase(iterator position);
88188891
iterator erase(const_iterator position);
88198892
size_type erase(const key_type& k);
8893+
template<class K> size_type erase(K&& x);
88208894
iterator erase(const_iterator first, const_iterator last);
88218895
void swap(unordered_multimap&)
88228896
noexcept(allocator_traits<Allocator>::is_always_equal::value &&
@@ -9176,12 +9250,14 @@
91769250

91779251
node_type extract(const_iterator position);
91789252
node_type extract(const key_type& x);
9253+
template<class K> node_type extract(K&& x);
91799254
insert_return_type insert(node_type&& nh);
91809255
iterator insert(const_iterator hint, node_type&& nh);
91819256

91829257
iterator erase(iterator position);
91839258
iterator erase(const_iterator position);
91849259
size_type erase(const key_type& k);
9260+
template<class K> size_type erase(K&& x);
91859261
iterator erase(const_iterator first, const_iterator last);
91869262
void swap(unordered_set&)
91879263
noexcept(allocator_traits<Allocator>::is_always_equal::value &&
@@ -9501,12 +9577,14 @@
95019577

95029578
node_type extract(const_iterator position);
95039579
node_type extract(const key_type& x);
9580+
template<class K> node_type extract(K&& x);
95049581
iterator insert(node_type&& nh);
95059582
iterator insert(const_iterator hint, node_type&& nh);
95069583

95079584
iterator erase(iterator position);
95089585
iterator erase(const_iterator position);
95099586
size_type erase(const key_type& k);
9587+
template<class K> size_type erase(K&& x);
95109588
iterator erase(const_iterator first, const_iterator last);
95119589
void swap(unordered_multiset&)
95129590
noexcept(allocator_traits<Allocator>::is_always_equal::value &&

source/support.tex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@
562562
#define @\defnlibxname{cpp_lib_apply}@ 201603L // also in \libheader{tuple}
563563
#define @\defnlibxname{cpp_lib_array_constexpr}@ 201811L // also in \libheader{iterator}, \libheader{array}
564564
#define @\defnlibxname{cpp_lib_as_const}@ 201510L // also in \libheader{utility}
565+
#define @\defnlibxname{cpp_lib_associative_heterogeneous_erasure}@ 202110L
566+
// also in \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set}
565567
#define @\defnlibxname{cpp_lib_assume_aligned}@ 201811L // also in \libheader{memory}
566568
#define @\defnlibxname{cpp_lib_atomic_flag_test}@ 201907L // also in \libheader{atomic}
567569
#define @\defnlibxname{cpp_lib_atomic_float}@ 201711L // also in \libheader{atomic}

0 commit comments

Comments
 (0)