Skip to content

Commit 553b5c9

Browse files
committed
New issue from Arthur: "Inconsistent constraints on flat_foo::emplace"
1 parent 04cd4c8 commit 553b5c9

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

xml/issue4180.xml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4180" status="New">
5+
<title>Inconsistent constraints on <tt>flat_<i>foo</i>::emplace</tt></title>
6+
<section><sref ref="[flat.multiset.modifiers]"/><sref ref="[flat.map.modifiers]"/></section>
7+
<submitter>Arthur O'Dwyer</submitter>
8+
<date>09 Dec 2024</date>
9+
<priority>99</priority>
10+
11+
<discussion>
12+
<p>
13+
The usual pattern in <sref ref="[containers]"/> is that `x.emplace(args...)` has a precondition
14+
(<sref ref="[sequence.reqmts]"/> p20, <sref ref="[associative.reqmts.general]"/> p48) but no
15+
<i>Constraints</i> element. That is, `emplace` is not SFINAE-friendly. And it has only the one overload,
16+
so it doesn't need a constraint for purposes of overload resolution.
17+
<p/>
18+
No Constraints on `emplace`: `deque` (<sref ref="[deque.modifiers]"/>), `list` (<sref ref="[list.modifiers]"/>),
19+
`vector` (<sref ref="[vector.modifiers]"/>), `containers` (<sref ref="[sequence.reqmts]"/> p19),
20+
`associative containers` (<sref ref="[associative.reqmts.general]"/> p47),
21+
`unordered containers` (<sref ref="[unord.req.general]"/> p78), `priority_queue` (<sref ref="[priqueue.members]"/> p5),
22+
`optional` (<sref ref="[optional.assign]"/> p29).
23+
<p/>
24+
Constraints on `emplace`: `flat_map` (<sref ref="[flat.map.modifiers]"/> p1),
25+
`flat_multiset` (<sref ref="[flat.multiset.modifiers]"/> p1), `any` (<sref ref="[any.modifiers]"/> p1),
26+
`expected` (<sref ref="[expected.object.assign]"/> p16), `variant` (<sref ref="[variant.mod]"/> p1).
27+
<p/>
28+
I believe a <i>Constraints</i> element was accidentally copy-pasted from the spec of <tt>flat_map::insert(P&amp;&amp;)</tt>
29+
&mdash; which does need the constraint because it's part of `insert`'s large overload set &mdash; to
30+
`flat_map::emplace`, and then from there to `flat_multiset::emplace`. The constraint is already (correctly) absent
31+
`from flat_set::emplace`.
32+
<p/>
33+
While we're touching this paragraph, also resolve the vague word "initializes" to "direct-non-list-initializes."
34+
Editorially, <tt>pair&lt;&hellip;&gt;</tt> is a verbose way to spell the `value_type` of a `flat_map`; we should
35+
be consistent and just say `value_type`.
36+
</p>
37+
</discussion>
38+
39+
<resolution>
40+
<p>
41+
This wording is relative to <paper num="N4993"/>.
42+
</p>
43+
44+
<blockquote class="note">
45+
<p>
46+
[<i>Drafting note</i>: <sref ref="[flat.set.modifiers]"/> is already OK as far as this issue is concerned:
47+
it has no wording for `emplace`.
48+
<p/>
49+
[flat.multimap.modifiers] is already OK ditto: it does not exist. ]
50+
</p>
51+
</blockquote>
52+
53+
<ol>
54+
<li><p>Modify <sref ref="[flat.multiset.modifiers]"/> as indicated:</p>
55+
56+
<blockquote>
57+
<pre>
58+
template&lt;class... Args&gt; iterator emplace(Args&amp;&amp;... args);
59+
</pre>
60+
<blockquote>
61+
<p>
62+
-1- <i><ins>Mandates</ins><del>Constraints</del></i>: <tt>is_constructible_v&lt;value_type, Args...&gt;</tt> is <tt>true</tt>.
63+
<p/>
64+
-2- <i>Effects</i>: First, <ins>direct-non-list-</ins>initializes an object `t` of type `value_type` with
65+
<tt>std::forward&lt;Args&gt;(args)...</tt>, then inserts `t` as if by:
66+
</p>
67+
<blockquote><pre>
68+
auto it = ranges::upper_bound(c, t, compare);
69+
c.insert(it, std::move(t));
70+
</pre></blockquote>
71+
<p>
72+
-3- <i>Returns</i>: An iterator that points to the inserted element.
73+
</p>
74+
</blockquote>
75+
</blockquote>
76+
77+
</li>
78+
79+
<li><p>Modify <sref ref="[flat.map.modifiers]"/> as indicated:</p>
80+
81+
<blockquote>
82+
<pre>
83+
template&lt;class... Args&gt; pair&lt;iterator, bool&gt; emplace(Args&amp;&amp;... args);
84+
</pre>
85+
<blockquote>
86+
<p>
87+
-1- <i><ins>Mandates</ins><del>Constraints</del></i>: <tt>is_constructible_v&lt;<ins>value_type</ins><del>pair&lt;key_type, mapped_type&gt;</del>, Args...&gt;</tt>
88+
is <tt>true</tt>.
89+
<p/>
90+
-2- <i>Effects</i>: <ins>First, direct-non-list-i</ins><del>I</del>nitializes an object `t` of type
91+
<tt><ins>value_type</ins><del>pair&lt;key_type, mapped_type&gt;</del></tt> with <tt>std::forward&lt;Args&gt;(args)...</tt>;
92+
if the map already contains an element whose key is equivalent to `t.first`, `*this` is unchanged. Otherwise, equivalent to:
93+
</p>
94+
<blockquote><pre>
95+
auto key_it = ranges::upper_bound(c.keys, t.first, compare);
96+
auto value_it = c.values.begin() + distance(c.keys.begin(), key_it);
97+
c.keys.insert(key_it, std::move(t.first));
98+
c.values.insert(value_it, std::move(t.second));
99+
</pre></blockquote>
100+
<p>
101+
-3- <i>Returns</i>: The `bool` component of the returned pair is `true` if and only if the insertion took place, and
102+
the iterator component of the pair points to the element with key equivalent to `t.first`.
103+
</p>
104+
</blockquote>
105+
</blockquote>
106+
107+
</li>
108+
</ol>
109+
</resolution>
110+
111+
</issue>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy