klimucha
klimucha

Reputation: 1

How to solve comparing structs as key map c++

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

Answers (2)

PaulMcKenzie
PaulMcKenzie

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

Del
Del

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

Related Questions