Reputation: 1
None topic solved my problem of comparing structs as key map in C++.
Structs code following:
struct XYZ{
int x, y, z;
}
struct XYZComp{
bool operator()(const XYZ& l, const XYZ& r)
{
return ((l.x==r.x)&&(l.y==r.y)&&(l.z==r.z));
}
}
Main looks like
int main()
{
map<XYZ, int, XYZComp> m;
m.insert(std::make_pair<XYZ,int>({1,2,3}, 1)); //ok
map<XYZ, int, XYZComp>::iterator it = m.find({1,0,3});
if(it!=m.end())
{
std::cout<<"Key exists in map";
}
else
{
m.insert(std::make_pair<XYZ,int>({1,0,3}, 1));
//never come here
//compiler thinks key already exists in map
}
return 0;
}
I just tried without XYZComparer but it still doesn't work.
struct XYZ{
int x,y,z;
bool operator==(const XYZ& xyz)
{
return (x=xyz.x) && (y=xyz.y) && (z=xyz.z);
}
bool operator<(const XYZ& xyz)
{
return (x>xyz.x) && (y>xyz.y) && (z>xyz.z);
}
}
How to solve comparing these structs XYZ while i am trying existing item in map.
Edit: Compiler thinks structs are the same when at least one number is correct.
Upvotes: 0
Views: 5651
Reputation: 35455
The std::map
uses <
to order items. Thus your struct XYZComp
needs to supply a user-defined operator <
.
A very simple solution is to use std::tie:
#include <tuple>
//..
struct XYZComp
{
int x,y,z;
bool operator < (const XYZComp& xyz) const
{
return std::tie(x, y, z) < std::tie(xyz.x, xyz.y, xyz.z);
}
//...
};
The std::tie
introduces lexicographical ordering to your struct's elements.
You could do the same thing by cascading down the < comparisons, but then the code becomes longer and is easier to make a mistake:
struct XYZComp
{
int x,y,z;
bool operator < (const XYZComp& xyz) const
{
if ( x < xyz.x )
return true;
if ( x == xyz.x && y < xyz.y )
return true;
if ( x == xyz.x && y == xyz.y )
return z < xyz.z;
return false;
}
//...
};
Upvotes: 6
Reputation: 1329
The comparator of std::set
and std::map
should function as <
, not ==
. The binary search tree not only needs to know if objects are equal; it needs to give them an order because the data structure is sorted. Overload the <
operator for your objects.
The objects are considered equal if !comp(a, b) && !comp(b, a)
. (Source)
If you overload <
, you need not explicitly supply the comparator to the container type because the default is comparator is std::less
, which wraps the <
operator.
Upvotes: 1