我有一个带有一些成员的结构,我有一个实现的运算符==。实施运营商是否安全<在operator ==的帮助下?我想在一个集合中使用这个结构,我想检查这个结构是否是唯一的。
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);
}
}
所以当我将这个结构插入到std :: set时会发生什么?
答案 0 :(得分:9)
不,这很不安全。实现它的最简单方法是通过std::tie
。
#include <tuple>
struct Data
{
std::string str1;
std::string str2;
std::string str3;
std::string str4;
bool operator<(const Data& rhs) const // you forgot a const
{
return
std::tie(str1, str2, str3, str4) <
std::tie(rhs.str1, rhs.str2, rhs.str3, rhs.str4);
}
}
答案 1 :(得分:6)
不,那不安全。您定义<
,a < b
和b < a
的方式同时适用。
所以当我将这个结构插入到std :: set时会发生什么?
行为未定义,因此任何内容都是允许的,并且在不同的实现中可能会有所不同。
答案 2 :(得分:3)
您的代码建议如果A!=B
,那意味着A<B
肯定是错误的,因为它也可能是A>B
。
您必须以与>
相同的方式实施<
和operator==
运算符,这意味着通过成员比较对象。您可以根据自己的成员决定如何确定A
是否比B
“更多”或“更少”。
如果您在任何标准库容器中使用该运算符,您将获得UB。
答案 3 :(得分:2)
您需要以自己的方式定义operator<
。您无法在operator<
方面实施operator==
,但您可以采取相反的措施。
考虑这个真值表中的悖论:
"a" < "b" : TRUE
"b" < "a" : TRUE
如果你的operator<
的实现产生了上述悖论,如果你用operator==
来实现它,那么你没有正确实现严格的弱排序。你实施的是乱七八糟的混乱。
您需要确定哪些成员字符串优先于其他成员字符串,然后按顺序执行它们之间的比较 - 从最重要到最不重要。
例如,如果字符串的优先级从最重要到最不重要:
str1
str2
str3
str4
...然后这会产生operator<
的以下算法:
bool operator<(const Data& rhs) const
{
if( str1 < rhs.str1 )
return true;
if( rhs.str1 < str1 )
return false;
if( str2 < rhs.str2 )
return true;
if( rhs.str2 < str2 )
return false;
if( str3 < rhs.str3 )
return true;
if( rhs.str3 < str3 )
return false;
if( str4 < rhs.str4 )
return true;
if( rhs.str4 < str4 )
return false;
return false;
}
使用此功能,您可以选择根据operator==
重新实施operator<
。然而,您可以假设时间复杂性固有的低效率:
bool operator==(const Data& rhs) const
{
return !operator<(rhs) && !rhs.operator<(*this);
}