char_traits::copy
precondition too weakSection: 27.2.2 [char.traits.require] Status: C++23 Submitter: Jonathan Wakely Opened: 2018-03-16 Last modified: 2023-11-22
Priority: 2
View other active issues in [char.traits.require].
View all other issues in [char.traits.require].
View all issues with C++23 status.
Discussion:
Table 54, Character traits requirements, says that char_traits::move
allows the ranges to overlap,
but char_traits::copy
requires that p
is not in the range [s, s + n)
. This
appears to be an attempt to map to the requirements of memmove
and memcpy
respectively,
allowing those to be used to implement the functions, however the requirements for copy
are
weaker than those for memcpy
. The C standard says for memcpy
"If copying takes place
between objects that overlap, the behavior is undefined" which is a stronger requirement than the start
of the source range not being in the destination range.
memcpy
for char_traits<char>::copy
,
resulting in undefined behaviour in this example:
char p[] = "abc"; char* s = p + 1; std::char_traits<char>::copy(s, p, 2); assert(std::char_traits<char>::compare(p, "aab", 3) == 0);
If the intention is to allow memcpy
as a valid implementation then the precondition is
wrong (unfortunately nobody realized this when fixing char_traits::move
in LWG DR 7).
If the intention is to require memmove
then it is strange to have separate copy
and
move
functions that both use memmove
.
std::copy
and std::copy_backward
are not valid implementations of
char_traits::copy
either, due to different preconditions.
Changing the precondition implicitly applies to basic_string::copy
(27.4.3.7.7 [string.copy]),
and basic_string_view::copy
(27.3.3.8 [string.view.ops]), which are currently required
to support partially overlapping ranges:
std::string s = "abc"; s.copy(s.data() + 1, s.length() - 1); assert(s == "aab");
[2018-04-03 Priority set to 2 after discussion on the reflector.]
[2018-08-23 Batavia Issues processing]
No consensus for direction; revisit in San Diego. Status to Open.
[2022-04-25; Daniel rebases wording on N4910]
Previous resolution [SUPERSEDED]:
This wording is relative to N4910.
Option A:
Edit 27.2.2 [char.traits.require], Table 75 — "Character traits requirements" [tab:char.traits.req], as indicated:
Table 75 — Character traits requirements [tab:char.traits.req] Expression Return type Assertion/note
pre/post-conditionComplexity […]
X::copy(s,p,n)
X::char_type*
Preconditions: The rangesp
not in[s,s+n)
[p,p+n)
and[s,s+n)
do not overlap.
Returns:s
.
for eachi
in[0,n)
, performs
X::assign(s[i],p[i])
.linear […]
Option B:
NAD (i.e. implementations need to be fixed, in practice
char_traits::copy
andchar_traits::move
might be equivalent).
[Kona 2022-11-11; Move to Ready]
LWG voted for Option A (6 for, 0 against, 1 netural)
[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Voting → WP.]
Proposed resolution:
Edit 27.2.2 [char.traits.require], Table 75 — "Character traits requirements" [tab:char.traits.req], as indicated:
Table 75 — Character traits requirements [tab:char.traits.req] Expression Return type Assertion/note
pre/post-conditionComplexity […]
X::copy(s,p,n)
X::char_type*
Preconditions: The rangesp
not in[s,s+n)
[p,p+n)
and[s,s+n)
do not overlap.
Returns:s
.
for eachi
in[0,n)
, performs
X::assign(s[i],p[i])
.linear […]