c++stlsetcomparatorstrict-weak-ordering

std::set comparator - STL Sort based on multiple attributes


I'm testing std::set with a custom comparator. But I see the same object getting inserted twice.

Following is the object class:

 class Info
    {
        public:
            Info(string n, string oN, int dom):
                    name(n),
                    objName(oN),
                    domain(dom)
            {}
    

        void setName(std::string n) { name = n;}
        void setObjName(std::string n) { objName = n;}
        void setDomain(int dom) { domain = dom; }

        std::string getName() const { return name;}
        std::string getObjName() const { return objName;}
        int getDomain() const { return domain;}

    private:
        std::string name;
        std::string objName;
        int domain;
};

Following is my custom comparator:

struct InfoCmp {
bool operator() (const Info &lhs, const Info &rhs) const {
    if((lhs.getName() < rhs.getName()) || (lhs.getObjName() < rhs.getObjName()) || (lhs.getDomain() < rhs.getDomain()) ){
        return true;
        }
    return false;
    }
};

Following is the usage:

Info rst1("rst1", "rstObj1", 1);
Info rst2("rst2", "rstObj2", 2);
Info rst3("rst1", "rstObj3", 3);

std::set<Info,InfoCmp> resetSet;

resetSet.insert(rst1);
resetSet.insert(rst2);
resetSet.insert(rst3);
resetSet.insert(rst1);
resetSet.insert(rst2);
resetSet.insert(rst3);

I see rst2 inserted twice, but it shouldn't be as per my comparator.


Solution

  • I see that you've come up with your own solution, after recognizing from the comments that your original did not impose a strict object ordering as required by set. Here's a different version that only requires operator< and not operator==, making it consistent with the classes and algorithms of the standard library. It also simplifies things if you're e.g. doing a case insensitive comparison.

    struct InfoCmp {
        bool operator() (const Info &lhs, const Info &rhs) const {
            if(lhs.getName() < rhs.getName())
                return true;
            if(rhs.getName() < lhs.getName())
                return false;
            if(lhs.getObjName() < rhs.getObjName())
                return true;
            if(rhs.getObjName() < lhs.getObjName())
                return false;
            return lhs.getDomain() < rhs.getDomain();
            }
        };