Comparison Operator for Structure key in C++ Map

800 views Asked by At
#include<bits/stdc++.h>
using namespace std;

struct segment{
    int a;
    int b;
    int c;

    bool const operator<(const segment &o) const {
        return a < o.a;
    }
};


int main()
{
    map<segment,int> myMap;
    map<segment,int>::iterator it;
    struct segment x,y,z;

    x.a=2;
    x.b=4;
    x.c=6;

    y.a=2;
    y.b=5;
    y.c=8;

    z.a=2;
    z.b=4;
    z.c=6;        

    myMap[y]++;
    myMap[z]++;
    myMap[x]++;

    for( it =myMap.begin(); it != myMap.end(); it++)
        cout<<(*it).first.a<<" "<<(*it).second<<endl;
    return 0;
}

it gives result as

2 3

but i want it to print

2 1
2 2

In short I want to increment the value of the map if exactly the same struct instance is fed instead of making a new copy

3

There are 3 answers

1
Ami Tavory On

As far as your map is concerned, there is only one unique object here. In terms of the comparison you specified, and the implied equivalence, x == y and y == z. Why? Neither of them is smaller than the other, so, according to STL logic by comparison, they must be equivalent.

Perhaps you're looking for a std::multimap.

Alternatively, if you want to define inequality (and hence implied equivalence) in terms of all the members, you could do something like this:

#include <tuple>

bool const operator<(const segment &o) const {
    return std::make_tuple(a, b, c) < std::make_tuple(o.a, o.b, o.c);
}

P.S. You should avoid including stuff from bits, as you're including stuff from the implementation. Instead, try to use stuff like

// See? no bits.
#include <map> 
0
Tim3880 On

You can change your less operator to:

bool const operator<(const segment &o) const {
    return a < o.a || (a == o.a && b < o.b) || (a==o.a && b==o.b && c < o.c) ;
}

This compares the values in the order of a, b, c.

But you can change it anyway you want to compare the structure.

0
xcvr On

IMO the best way to compare multiple members is using std::tie as it is much harder to mess up:

bool const operator<(const segment &o) const {
    return std::tie(a, b, c) < std::tie(o.a, o.b, o.c);
}

Edit: Would just like to add this link to cppreference as the example there is almost exactly your question.