没有等价关系的std :: unique示例(删除连续的空格)

And*_*dre 7 c++ std

关于如何使用从字符串中删除连续空格的cppreference有一个示例std::unique:

std::string s = "wanna go    to      space?";
auto end = std::unique(s.begin(), s.end(), [](char l, char r){
    return std::isspace(l) && std::isspace(r) && l == r;
});
// s now holds "wanna go to space?xxxxxxxx", where 'x' is indeterminate
std::cout << std::string(s.begin(), end) << '\n';
Run Code Online (Sandbox Code Playgroud)

但是,在唯一的要求部分中说明

使用给定的二元谓词p比较元素.如果行为不是等价关系,则行为未定义.

所以我的问题是:给定的例子是否有效?谓词显然不是反身的(两个'n'字符比较不相等),因此不是等价关系.

Jar*_*d42 2

该谓词确实不尊重Equivalence_relation,特别是自反性:

a ~ a
Run Code Online (Sandbox Code Playgroud)

您指出的示例可能是有效的,但第一个'n'可能与第二个不同'n'。问题在于自我比较是错误的(空格字符除外)。

修复谓词的一种方法是考虑地址:

[](const char& l, const char& r)
{
    return (&l == &r)
        || (l == r && std::is_space(l));
}
Run Code Online (Sandbox Code Playgroud)

事实上,与自身进行比较对于该算法来说基本上是无用的,因此这里的 UB 执行了作者在大多数实现中所期望的操作。

有效的实现可能会检查谓词的自反性,如果错误则执行任何操作(如 UB)。