Reputation: 305
Before the last erase
, the elements in the s1
and s2
are the same.
The last erase
to the s1
erases 1 element in the set s1
. It is correct.
The last erase
to the s2
erases 3 elements in the set s2
. It is unexpected.
#include <iostream>
#include <cstdlib>
#include <cassert>
#include <set>
#include <functional>
using namespace std;
struct Ev {
int p = 0;
int l = 0;
int r = 0;
bool open = false;
friend ostream& operator<<(ostream& os, const Ev& ev);
};
ostream& operator<<(ostream& os, const Ev& ev) {
os << "p = " << ev.p << ", l = " << ev.l << ", r = " << ev.r << boolalpha
<< ", open = " << ev.open;
return os;
}
int main() {
auto lr_cmp = [](const Ev& lhs, const Ev& rhs) {
return lhs.r == rhs.l;
};
set<Ev, decltype(lr_cmp)> s1(lr_cmp);
set<Ev, decltype(lr_cmp)> s2(lr_cmp);
assert(s1.insert({0, 0, 1, true}).second);
assert(s1.insert({1, 1, 3, true}).second);
assert(s1.insert({2, 3, 4, true}).second);
assert(s1.insert({0, 4, 5, true}).second);
for (const auto& ev : s1) {
cout << ev << endl;
}
assert(s1.erase({3, 1, 3, false}) == 1);
cout << "--------------------------------" << endl;
assert(s2.insert({1, 1, 3, true}).second);
assert(s2.insert({1, 3, 4, true}).second);
assert(s2.insert({0, 0, 1, true}).second);
assert(s2.insert({0, 4, 5, true}).second);
assert(s2.erase({2, 3, 4, false}) == 1);
assert(s2.insert({2, 3, 4, true}).second);
for (const auto& ev : s2) {
cout << ev << endl;
}
assert(s2.erase({3, 1, 3, false}) == 1);
return 0;
}
Here is the output.
p = 0, l = 0, r = 1, open = true
p = 1, l = 1, r = 3, open = true
p = 2, l = 3, r = 4, open = true
p = 0, l = 4, r = 5, open = true
--------------------------------
p = 0, l = 0, r = 1, open = true
p = 1, l = 1, r = 3, open = true
p = 2, l = 3, r = 4, open = true
p = 0, l = 4, r = 5, open = true
prog.exe: prog.cc:51: int main(): Assertion `s2.erase({3, 1, 3, false}) == 1' failed.
Aborted
Upvotes: 0
Views: 67
Reputation: 62616
lr_cmp
is not a strict weak order. Amongst other failings, it isn't transitive.
Requirements
if
lr_cmp(a,b)==true
andlr_cmp(b,c)==true
thenlr_cmp(a,c)==true
This is not the case, e.g.
Ev a {1, 1, 3, true};
Ev b {1, 3, 4, true};
Ev c {0, 4, 5, true};
std::cout << std::boolalpha << lr_cmp(a,b) << lr_cmp(b,c) << lr_cmp(a,c);
Thus the behaviour of your program is undefined. Presumably either it is erasing (some?) elements that are equivalent under lr_cmp
, or not finding the element you want to remove.
equiv(a, b)
, an expression equivalent to!lr_cmp(a, b) && !lr_cmp(b, a)
{3, 1, 3, false}
is equivalent to {1, 1, 3, true}
and {0, 4, 5, true}
.
Upvotes: 2