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:
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;
}