I have a struct called foo, and also a map called mp, but for some reason, when I insert {5, 0, 3} and query for {5, 3, 0}, the map says that it contains {5, 3, 0} when it actually doesn't:
#include <bits/stdc .h>
using namespace std;
struct foo {
int v1, v2, v3;
friend bool operator<(const foo &a, const foo &b) {
return a.v1 < b.v1;
}
friend bool operator==(const foo &a, const foo &b) {
return (a.v1 == b.v1) && (a.v2 == b.v2) && (a.v3 == b.v3);
}
};
int main() {
map<foo, int> mp;
mp[{5, 0, 3}] = 1;
if(mp[{5, 3, 0}]) {
cout << "YES\n";
} else {
cout << "NO\n";
}
return 0;
}
Output:
YES
Does anyone know why my code is doing this? If so, what do I need to change?
CodePudding user response:
Your comparison operator does not match your equality operator. A std::map
does not use the equality operator; it uses "less than". If neither a < b
nor b < a
then the map considers a
and b
equivalent. In your case:
foo{5, 0, 3} < foo{5, 3, 0}
isfalse
because5 < 5
is false.foo{5, 3, 0} < foo{5, 0, 3}
isfalse
because5 < 5
is false.
So the map considers these objects equivalent. So mp[{5, 3, 0}]
finds the map element you just set to 1, hence it is a true value.
To get the result you want, your operator<
needs to account for all three members, not just v1
.
CodePudding user response:
int v1, v2, v3;
friend bool operator<(const foo &a, const foo &b) {
return a.v1 < b.v1;
}
firstly, this only checks the first value. So 5,0,0 will be considered the same a 5,9,9, etc.
if(mp[{5, 3, 0}])
This doesn't work the way you think. Operator[] will create a new entry if one doesn't exist. However as it is inserting a value of 0, your if statement is giving the result you expect, but it is not doing it in the way you expect. This kind of "side effect" is bad, this is where bugs creep in. You shoudl use methods like map.find() instead
CodePudding user response:
Using "namespace::std" is not good. the c standard library aka "std" has misinterpreted your code. generally "namespace::std" attracts errors with structures because there are 2 types of structures so simply since you typed "using namespace::std"; the compiler thinks that the value in the standard library, is the actual integer. Also, i don't know who uses "<bits/stdc .h>".
Quick fix:
`struct foo {
int v1, v2, v3;
friend bool operator<(const foo &a, const foo &b) {
return a.v1 < b.v1;
}
friend bool operator==(const foo &a, const foo &b) {
return (a.v1 == b.v1) && (a.v2 == b.v2) && (a.v3 == b.v3);
}
};
int main() {
map<foo, int> mp;
mp[{5, 0, 3}] = 1;
if(mp[{5, 3, 0}]) {
cout << "YES\n";
} else {
cout << "NO\n";
}
return 0;
}`