There is an example on cppreference on how to use std::unique
to remove consecutive spaces from a string:
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';
However, in the requirements section for unique it states
Elements are compared using the given binary predicate p. The behavior is undefined if it is not an equivalence relation.
So my question is: is the given example valid? The predicate is clearly not reflexive (the two 'n' characters compare unequal) and thus not an equivalence relation.
The predicate indeed doesn't respect Equivalence_relation, in particular reflexivity:
a ~ a
The example you point may be valid though, first 'n'
can be different than second 'n'
.
problem is with self comparison which is false (except for space character).
One way to fix the predicate is to take address into account:
[](const char& l, const char& r)
{
return (&l == &r)
|| (l == r && std::is_space(l));
}
The fact is that comparing with itself is mostly useless for that algorithm, so the UB here does what author expect in most implementation.
Valid implementation might check reflexivity of predicate, and if wrong does anything (as UB).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With