Skip to content

Commit 7e12653

Browse files
committed
New issue from Hui Xie: "flat_map's transparent comparator no longer works for string literals"
1 parent e71585b commit 7e12653

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

xml/issue4239.xml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4239" status="New">
5+
<title>`flat_map`'s transparent comparator no longer works for string literals</title>
6+
<section>
7+
<sref ref="[flat.map.modifiers]"/>
8+
</section>
9+
<submitter>Hui Xie</submitter>
10+
<date>29 Mar 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
According to the spec, the following code should hard error
16+
</p>
17+
<blockquote><pre>
18+
std::flat_map&lt;std::string, int, std::less&lt;&gt;&gt; m;
19+
m.try_emplace("abc", 5); // <span style="color:red;font-weight:bolder">hard error</span>
20+
</pre></blockquote>
21+
<p>
22+
The reason is that we specify in <sref ref="[flat.map.modifiers]"/> p21 the effect to be
23+
as if `ranges::upper_bound` is called.
24+
</p>
25+
26+
<p>
27+
`ranges::upper_bound` requires `indirect_strict_weak_order`, which requires the comparator to be
28+
invocable for all combinations. In this case, it requires
29+
</p>
30+
<blockquote><pre>
31+
const char (&amp;)[4] &lt; const char (&amp;)[4]
32+
</pre></blockquote>
33+
<p>
34+
to be well-formed, which is no longer the case in C++26 after <paper num="P2865R6"/>.
35+
<p/>
36+
We should just use `std::upper_bound` instead. libstdc++ already uses `std::upper_bound`.
37+
libc++ uses `ranges::upper_bound` but clang has not yet implemented <paper num="P2865"/>
38+
properly.
39+
</p>
40+
</discussion>
41+
42+
<resolution>
43+
<p>
44+
This wording is relative to <paper num="N5008"/>.
45+
</p>
46+
47+
<ol>
48+
49+
<li><p>Modify <sref ref="[flat.map.modifiers]"/> as indicated:</p>
50+
51+
<blockquote>
52+
<pre>
53+
template&lt;class K, class... Args&gt;
54+
constexpr pair&lt;iterator, bool&gt; try_emplace(K&amp;&amp; k, Args&amp;&amp;... args);
55+
template&lt;class K, class... Args&gt;
56+
constexpr iterator try_emplace(const_iterator hint, K&amp;&amp; k, Args&amp;&amp;... args);
57+
</pre>
58+
<blockquote>
59+
<p>
60+
-19- <i>Constraints</i>: [&hellip;]
61+
<p/>
62+
-20- <i>Preconditions</i>: [&hellip;]
63+
<p/>
64+
-21- <i>Effects</i>: If the map already contains an element whose key is equivalent to `k`,
65+
`*this` and `args...` are unchanged. Otherwise equivalent to:
66+
</p>
67+
<blockquote><pre>
68+
auto key_it = <ins>upper_bound(<i>c</i>.keys.begin(), <i>c</i>.keys.end(), k, <i>compare</i>)</ins><del>ranges::upper_bound(<i>c</i>.keys, k, <i>compare</i>)</del>;
69+
auto value_it = <i>c</i>.values.begin() + distance(<i>c</i>.keys.begin(), key_it);
70+
<i>c</i>.keys.emplace(key_it, std::forward&lt;K&gt;(k));
71+
<i>c</i>.values.emplace(value_it, std::forward&lt;Args&gt;(args)...);
72+
</pre></blockquote>
73+
</blockquote>
74+
</blockquote>
75+
76+
</li>
77+
78+
</ol>
79+
</resolution>
80+
81+
</issue>

0 commit comments

Comments
 (0)