Search code examples
c++c++11stdstdset

Inserting pair in std::set is inconsistent (doesn't recognize <pair>.second)


This code performs differently if I add a condition:

First case:

#include<bits/stdc++.h>
using namespace std;

struct comp
{
    bool operator()(pair<int,pair<int,int> > a, pair<int,pair<int,int> > b)
    {
        return a.first>b.first;
    }
};

int main()
{
    set<pair<int,pair<int,int>>,comp> s;
    auto d = s.insert({4,{6,10}});
    cout<<(d.first)->first<<" "<<(d.first)->second.first<<" "<<(d.first)->second.second<<endl;
    d = s.insert({4,{0,4}});
    cout<<(d.first)->first<<" "<<(d.first)->second.first<<" "<<(d.first)->second.second<<endl;
}

Output:

4 6 10
4 6 10

Second case: (with condition on .second)

#include<bits/stdc++.h>
using namespace std;

struct comp
{
    bool operator()(pair<int,pair<int,int> > a, pair<int,pair<int,int> > b)
    {
        if(a.first==b.first)
            return a.second.first<b.second.first;
        return a.first>b.first;
    }
};

int main()
{
    set<pair<int,pair<int,int>>,comp> s;
    auto d = s.insert({4,{6,10}});
    cout<<(d.first)->first<<" "<<(d.first)->second.first<<" "<<(d.first)->second.second<<endl;
    d = s.insert({4,{0,4}});
    cout<<(d.first)->first<<" "<<(d.first)->second.first<<" "<<(d.first)->second.second<<endl;
}

Output:

4 6 10
4 0 4

Why does the set not add a different pair in the first case? I thought the extra condition only decides the order, and doesn't differentiate between elements.


Solution

  • Your first comparator only takes the first item of the pair in consideration. When you try to insert the second pair, it is considered equal to the already inserted pair, and thus not inserted.

    Instead, you get back the object that was already inserted in the set, which is the expected behavior.

    Remember, a set, by definition, only has one instance of a particular object, and your comparator helps it to state how 2 objects compare to each other.