Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::unique example with no equivalence relationship (remove consecutive spaces)

Tags:

c++

std

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.

like image 923
Andre Avatar asked Oct 12 '17 11:10

Andre


1 Answers

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).

like image 114
Jarod42 Avatar answered Oct 07 '22 11:10

Jarod42