[英]Is it safe to use operator != as operator < in a std::set?
我有一個帶有一些成員的結構,我有一個實現的運算符==。 在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時會發生什么?
不,這是非常不安全的。 實現它的最簡單方法是通過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);
}
}
不,那不安全。 您定義的方式<
, a < b
和b < a
將同時為真。
所以當我將這個結構插入到std :: set時會發生什么?
行為是未定義的,因此任何事情都是允許的,並且在不同的實現上可能會有所不同。
那么你的代碼建議如果A!=B
,那意味着A<B
肯定是錯誤的,因為它也可以是A>B
您將必須以與operator==
相同的方式實現>
和<
運算operator==
,這意味着通過成員方式比較對象。 由您決定如何確定A
是否比基於其成員的B
“更多”或“更少”。
如果您在任何標准庫容器中使用該運算符,您將獲得UB。
您需要按照自己的術語定義operator<
。 雖然您可以執行相反的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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.