2

いくつかのメンバーを持つ構造体があり、そのためにoperator==が実装されています。operator ==の助けを借りて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に挿入すると、何が起こりますか?

4

4 に答える 4

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);
  }
}
于 2012-10-08T13:02:19.247 に答える
6

いいえ、それは安全ではありません。あなたが定義した方法<a < bそしてb < a両方が同時に真実になるでしょう。

したがって、この構造体をstd :: setに挿入すると、何が起こりますか?

動作は定義されていないため、何でも許可され、実装によって異なる可能性があります。

于 2012-10-08T12:59:23.390 に答える
3

さて、あなたのコードは、もしそうなら、それは間違いなく間違っているA!=Bことを意味することを示唆しています。A<BA>B

、で行ったのと同じ方法で、>および演算子を実装する必要があります。つまり、オブジェクトをメンバーごとに比較します。メンバーに基づいて「多い」か「少ない」かを判断する方法はあなた次第です。<operator==AB

標準ライブラリコンテナのいずれかで使用している演算子を使用すると、UBが取得されます。

于 2012-10-08T12:59:12.923 に答える
2

operator<独自の用語で定義する必要があります。operator<の観点から実装することはできませんoperator==が、逆はできる場合があります。

この真理値表のパラドックスを考えてみましょう:

"a" < "b" : TRUE
"b" < "a" : TRUE

の実装でoperator<上記のパラドックスが発生する場合は、operator==厳密な弱順序付けを正しく実装していません。あなたが実装したのは、ごちゃごちゃした混乱です。

どのメンバー文字列が他の文字列よりも優先されるかを判断し、重要度の高いものから順に比較する必要があります。

たとえば、文字列の優先順位が重要度の高いものから重要度の低いものまで:

  1. str1
  2. str2
  3. str3
  4. 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);
}
于 2012-10-08T15:26:22.313 に答える