The function std::char_traits::copy
is implemented in libc++
like this:
template <class _CharT>
inline _LIBCPP_CONSTEXPR_AFTER_CXX17
_CharT*
char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
{
if (!__libcpp_is_constant_evaluated()) {
_LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
}
char_type* __r = __s1;
for (; __n; --__n, ++__s1, ++__s2)
assign(*__s1, *__s2);
return __r;
}
The condition in _LIBCPP_ASSERT
seems backwards. Shouldn't it be
__s1 < __s2 || __s1 >= __s2+__n
What am I missing?
Before resolution of LWG issue 3085 (targeting C++23) the check made in the shown code is actually the only precondition specified for char_traits::copy
. The beginning of the source range may not lie in the destination range, but the beginning of the destination range may lie in the source range.
However, then the implementation in the shown code would be wrong. Copying from beginning to end in a loop will potentially overwrite source elements too early.
The resolution of the LWG issue makes the precondition stricter to require source and destination range to not overlap at all. Apparently multiple implementations had not considered the previously-allowed overlap correctly in their implementation.