Custom comparison for set accessing member variables of a class where the actual keys belong to

94 Views Asked by At

How to specify custom compare for the following example? The idea is to access member variable within a class for comparison.

struct MyStruct {
    unsigned p;
    unsigned t;
};

class MyClass {
public:
    void call() {
        ob["o1_10"] ={10, 1};
        mbp[ob["o1_10"].p].insert("o1_10");

        ob["o2_20_2"] ={20, 2};
        mbp[ob["o2_20"].p].insert("o2_20");


        ob["o4_4_4"] ={4, 4};
        mbp[ob["o4_4"].p].insert("o4_4");

        ob["o5_10"] ={10, 4};
        mbp[ob["o5_10"].p].insert("o5_10");
    }
    
    
private:
    map<unsigned,set<string, Compare>> mbp;
    // Question: how to define compare using struct, operator(), statice metthod or external method so that
    //           compare fetches ob[ol] and ob[0l2] and decide based on some rules
    //           so, comparions is not based on ol and o2 and it is based on some p and t in ob[o1] and ob[02]
    // Eg:
    // bool compare(const string& o1, const string& o2) const {
    //     if (ob.at(o1).p > ob.at(o2).p)   return true;
    //     if (ob.at(o1).p == ob.at(o2).p && ob.at(o1).t < ob.at(o2).t) return true;

    //     return false;
    // }
    
    map<string, MyStruct> ob;
};


int main() {
    MyClass my_class;
    my_class.call();

    return 0;
}

It is important to note that comparison keys are not instances of the class. Instead, I want to use the key to access instances of the class to compare. If this can be achieved, I can save some memory.

I have tried the followings and each give me different errors:

  1. struct within class
  2. functor
  3. using bind
1

There are 1 best solutions below

9
On

You need to overload operator< like this.

With this operator you can use your class both in std::set and std::map (as key). In practice you probably also want to overload ALL compare operators (For C++20 overload the spaceship operator instead).

#include <map>
#include <set>
#include <iostream>

class my_class_t
{
public:
    my_class_t(int x, int y) :
        m_x{x},
        m_y{y}
    {
    }

    friend bool operator<(const my_class_t& lhs, const my_class_t& rhs);

private:
    int m_x;
    int m_y;
};

bool operator<(const my_class_t& lhs, const my_class_t& rhs)
{
    if (lhs.m_x == rhs.m_x) 
    {
        return lhs.m_y < rhs.m_y;
    }

    return lhs.m_x < rhs.m_x;
}

int main()
{
    std::set<my_class_t> set{{1,1},{2,1},{2,2}};
    std::map<my_class_t,int> map{{{1,1},1}, {{1,2},2}};
    int value = map[{1,2}];
    std::cout << value;
    return value;
}