Skip to content

Commit 5dfad39

Browse files
committed
New issue from Peter Bindels: "Inconsistency between std::basic_string's data() and operator[] specification"
1 parent 9d06c68 commit 5dfad39

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

xml/issue4378.xml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4378" status="New">
5+
<title>Inconsistency between `std::basic_string`'s `data()` and `operator[]` specification</title>
6+
<section>
7+
<sref ref="[string.access]"/>
8+
</section>
9+
<submitter>Peter Bindels</submitter>
10+
<date>16 Sep 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
From the working draft <paper num="N5014"/>, the specification for `operator[]` in <sref ref="[string.access]"/>
16+
p2 says:
17+
</p>
18+
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
19+
<p>
20+
<i>Returns</i>: <tt>*(begin() + pos)</tt> if <tt>pos &lt; size()</tt>. Otherwise, returns a reference
21+
to an object of type `charT` with value `charT()`, where modifying the object to any value other than
22+
`charT()` leads to undefined behavior.
23+
</p>
24+
</blockquote>
25+
<p>
26+
The specification for data() in <sref ref="[string.accessors]"/> p1 (and p4) says, however:
27+
</p>
28+
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
29+
<p>
30+
<i>Returns</i>: A pointer `p` such that `p + i == addressof(operator[](i))` for each `i` in `[0, size()]`.
31+
</p>
32+
</blockquote>
33+
<p>
34+
The former implies that `str[str.size()]` is allowed to be the address of any null terminator,
35+
while the latter restricts it to only being the null terminator belonging to the string.
36+
<p/>
37+
Suggested fix: Change wording around `operator[]` to
38+
</p>
39+
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
40+
<p>
41+
<i>Returns</i>: `*(begin() + pos)` if <tt>pos &lt;= size()</tt>. The program shall not modify the value
42+
stored at `size()` to any value other than `charT()`; otherwise, the behavior is undefined.
43+
</p>
44+
</blockquote>
45+
<p>
46+
This moves it inline with the `data()` specification. Given the hardened precondition that
47+
<tt>pos &lt;= size()</tt> this does not change behavior for any in-contract access, and we do
48+
not define what the feature does when called with broken preconditions. I have been looking at
49+
the latter but that will be an EWG paper instead.
50+
</p>
51+
</discussion>
52+
53+
<resolution>
54+
<p>
55+
This wording is relative to <paper num="N5014"/>.
56+
</p>
57+
58+
<ol>
59+
60+
61+
<li><p>Modify <sref ref="[string.access]"/> as indicated:</p>
62+
63+
<blockquote>
64+
<pre>
65+
constexpr const_reference operator[](size_type pos) const;
66+
constexpr reference operator[](size_type pos);
67+
</pre>
68+
<blockquote>
69+
<p>
70+
-1- <i>Hardened preconditions</i>: <tt>pos &lt;= size()</tt> is `true`.
71+
<p/>
72+
-2- <i>Returns</i>: `*(begin() + pos)` if <tt>pos &lt;<ins>=</ins> size()</tt>. <del>Otherwise, returns a reference
73+
to an object of type `charT` with value `charT()`, where modifying the object to any value other
74+
than `charT()` leads to undefined behavior</del><ins>The program shall not modify the value
75+
stored at `size()` to any value other than `charT()`; otherwise, the behavior is undefined</ins>.
76+
</p>
77+
</blockquote>
78+
</blockquote>
79+
80+
</li>
81+
82+
</ol>
83+
</resolution>
84+
85+
</issue>

0 commit comments

Comments
 (0)