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

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

Section: 21.2.2 [char.traits.require] Status: Open Submitter: Jonathan Wakely Opened: 2018-03-16 Last modified: 2020-09-06

Priority: 2

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

View all issues with Open 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` (21.3.3.7.7 [string.copy]), and `basic_string_view::copy` (21.4.3.7 [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.

Proposed resolution:

This wording is relative to N4727.

Option A:

> 1. Edit 21.2.2 [char.traits.require], Table 54 — "Character traits requirements", as indicated:

>    > Table 54 — Character traits requirements
>    > Expression | Return type | Assertion/note pre/post-condition | Complexity
>    > --- | --- | --- | ---
>    > `[…]`
>    > `X::copy(s,p,n)` | `X::char_type*` | Requires: `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).