This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Ready status.

### 3085. `char_traits::copy` precondition too weak

Section: 23.2.2 [char.traits.require] Status: Ready Submitter: Jonathan Wakely Opened: 2018-03-16 Last modified: 2022-11-11

Priority: 2

View other active issues in [char.traits.require].

View all other issues in [char.traits.require].

View all issues with Ready 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.

All of libstdc++, libc++ and VC++ simply use `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`.

N.B. `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` (23.4.3.7.7 [string.copy]), and `basic_string_view::copy` (23.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:

> > 1. Edit 23.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-condition | Complexity
> >    > --- | --- | --- | ---
> >    > `[…]`
> >    > `X::copy(s,p,n)` | `X::char_type*` | Preconditions: `p` not in `[s,s+n)`The ranges `[p,p+n)` and `[s,s+n)` do not overlap. Returns: `s`. for each `i` 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` and `char_traits::move` might be equivalent).

[Kona 2022-11-11; Move to Ready]

LWG voted for Option A (6 for, 0 against, 1 netural)

Proposed resolution:

1. Edit 23.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-condition | Complexity
   > --- | --- | --- | ---
   > `[…]`
   > `X::copy(s,p,n)` | `X::char_type*` | Preconditions: `p` not in `[s,s+n)`The ranges `[p,p+n)` and `[s,s+n)` do not overlap. Returns: `s`. for each `i` in `[0,n)`, performs `X::assign(s[i],p[i])`. | linear
   > `[…]`