I experienced the following phenomenon when writing some C++ code:
I have a map looking like this:
std::map<test_struct_t*, unsigned int, cmp_by_value> testmap;
This map lies globally in my program and the struct is defined as:
struct test_struct_t {
int x; int y; int val;
bool operator<(const test_struct_t &o) const {
return x < o.x || y < o.y || val < o.val;
}
test_struct_t(int a, int b, int c) : x(a), y(b), val(c) {}
};
The custom comparator I wrote is:
struct cmp_by_value {
bool operator()(const test_struct_t *a, const test_struct_t *b) const
{
return *a < *b;
}
};
Now, in my main method I do the following:
testmap.insert({new test_struct_t(0, 0, 2 ), 6});
testmap.insert({new test_struct_t(0, 1, 2 ), 6});
testmap.insert({new test_struct_t(1, 1, 0 ), 6});
testmap.insert({new test_struct_t(1, 2, 0 ), 6});
testmap.insert({new test_struct_t(2, 1, 0 ), 6});
testmap.insert({new test_struct_t(1, 2, 1 ), 6});
testmap.insert({new test_struct_t(1, 2, 0 ), 6});
And then I print the values in the map with some format method:
std::string format(test_struct_t *e) {
std::stringstream ss;
ss << "(" << e->x << "," << e->y << ") = " << e->val;
return ss.str();
}
And in the main:
std::map<test_struct_t*, unsigned int>::iterator it;
for (it = testmap.begin(); it != testmap.end(); ++it) {
std::cout << format(it->first) << std::endl;
}
My program gives the following output:
(1,1) = 0
(1,2) = 0
(1,2) = 1
(2,1) = 0
(1,2) = 0
(0,0) = 2
(0,1) = 2
Can anyone explain to me why there is the duplicate entry "(1,2) k =0"? When I remove one of the other inserted statements, everything is fine and there is no duplicate. Any ideas?
EDIT: What I also found very interesting is that:
testmap[new test_struct_t(0, 0, 2 )] = 6;
testmap[new test_struct_t(0, 1, 2 )] = 6;
testmap[new test_struct_t(1, 1, 0 )] = 6;
testmap[new test_struct_t(1, 2, 0 )] = 6;
testmap[new test_struct_t(2, 1, 0 )] = 6;
testmap[new test_struct_t(1, 2, 1 )] = 6;
testmap[new test_struct_t(1, 2, 0 )] = 6;
Gives this:
(0,0) = 2
(1,1) = 0
(1,2) = 0
(0,1) = 2
Your operator<
does not define a strict weak ordering. Try
bool operator<(const test_struct_t &o) const {
return std::tie(x,y,val)<std::tie(o.x,o.y,o.val);
}