这是 libc++ 的错误吗?

n. *_* m. 5 c++ libc++

该函数std::char_traits::copy的实现libc++如下:

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;
}
Run Code Online (Sandbox Code Playgroud)

情况_LIBCPP_ASSERT似乎倒退了。难道不应该吗

__s1 < __s2 || __s1 >= __s2+__n
Run Code Online (Sandbox Code Playgroud)

我缺少什么?

S.M*_*.M. 5

在 C++23 正确之前,这不是一个 bug、libc++ 条件。std::char_traits::copy

src如果复制的字符范围重叠,即在 中,则行为未定义[dest, dest + count)

坏的:(src >= dest && src < dest + count)

断言:!(src >= dest && src < dest + count)-> !(src >= dest) || !(src < dest + count)-> (src < dest) || (src >= dest + count)-> __s2 < __s1 || __s2 >= __s1 + __n


这里应用的数学逻辑规则:!(a && b)!a || !b


use*_*522 3

在解决LWG 问题 3085(针对 C++23)之前,所示代码中进行的检查实际上是为char_traits::copy. 源范围的开头可能不位于目标范围内,但目标范围的开头可能位于源范围内。

但是,所示代码中的实现将是错误的。在循环中从头到尾复制可能会过早覆盖源元素。

LWG问题的解决使得前提条件更加严格,要求源和目标范围完全不重叠。显然,多个实现在其实现中没有正确考虑先前允许的重叠。