Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Set::find() not working as expected with objects stored as pointer and comparison functor defined

If my set::find() function works as expected in some scenarios and does not work in others.

Since I am storing object pointers in my set I have defined a functor for comparison as below:

template<class T> struct ptr_compare
{
    bool operator()(const T* lhs, const T* rhs) const
    {
        return *lhs < *rhs;
    }
};

My sample class is as below:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class A {
  private:
    string str;
  public:
    A(string s)
    {
        str = s;
    }
    bool operator <(const A& obj) const
    {
        return this->str.compare(obj.get_str());
    }
    
    string get_str() const
    {
        return str;
    }
};

If I write main() function as below then set::find() seem to work as expected:

int main()
{
    set<A*, ptr_compare<A>> myset;
    A* a1 = new A("sdkbf");
    A* a2 = new A("test");
    A* a3 = new A("sfj");
    
    myset.insert(a1);
    myset.insert(a2);
    myset.insert(a3);
    
    set<A*>::iterator it = myset.find(a2);
    if (it != myset.end())
    {
        cout << "found" << endl;
    }
    else
    {
        cout << "not found" << endl;
    }

    return 0;
}

Output of above: found

Now If I change the order in which I insert elements in set then set::find() does not work as expected:

int main()
{
    set<A*, ptr_compare<A>> myset;
    A* a1 = new A("sdkbf");
    A* a2 = new A("test");
    A* a3 = new A("sfj");
    
    myset.insert(a1);
    myset.insert(a3);
    myset.insert(a2);
    
    set<A*>::iterator it = myset.find(a2);
    if (it != myset.end())
    {
        cout << "found" << endl;
    }
    else
    {
        cout << "not found" << endl;
    }

    return 0;
}

Output of above: not found

Is this not right way to compare object pointers in a set.

>Solution :

The issue is with

bool operator <(const A& obj) const
{
    return this->str.compare(obj.get_str());
}

Here compare will return -1 if str is less than obj.get_str() and 1 if obj.get_str() is less than str. Both of those values get converted to true when returned as a bool from the function. This is not what you want. Instead, you can use std::strings operator < like

bool operator <(const A& obj) const
{
    return str < obj.str;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading