I have a struct with some members and I have an implemented operator== for it. Is it safe to implement the operator< with the help of operator==? I want to use this struct in a set, and I want to check that this struct is unique.
struct Data
{
std::string str1;
std::string str2;
std::string str3;
std::string str4;
bool operator==(const Data& rhs)
{
if (str1 == rhs.str1
&& str2 == rhs.str2
&& str3 == rhs.str3
&& str4 == rhs.str4
)
return true;
else
return false;
}
// Is this ok??
bool operator<(const Data& rhs)
{
return !this->operator==(rhs);
}
}
So when I insert this struct to a std::set what will happen?
Nope, it's quite unsafe. The simplest way to implement it is through
std::tie
.Well your code suggests that if
A!=B
, that means thatA<B
which is definitely wrong, since it can as well beA>B
.You will have to implement your
>
and<
operators the same way you did with theoperator==
, which means by comparing the objects member-wise. It's up to you to decide how to determine ifA
is "more" or "less" thanB
based on their members.If you use the operator as you have it in any of the standard library containers, you will get UB.
You need to define
operator<
in its own terms. You cannot implementoperator<
in terms ofoperator==
, although you may be able to do the reverse.Consider the paradox in this truth table:
If your implementation of
operator<
yields the above paradox, which it does if you implement it in terms ofoperator==
then you have not correctly implemented strict weak ordering. What you've implemented is a jumbled mess.You need to determine which of the member strings take precedence over the others, and then perform a comparison between them in order -- from most important to least important.
For example, if the precedence of the string is, from most important to least important:
str1
str2
str3
str4
...then this yields the following algorithm for
operator<
:Using this, you could optionally next re-implement
operator==
in terms ofoperator<
. You assume the inherent inefficiency of time complexity in doing so, however:No, that is not safe. The way you've defined
<
,a < b
andb < a
will both be true at the same time.The behaviour is undefined, so anything is permitted, and it will likely be different on different implementations.