6

比較を正しく設定するのに苦労しています。これが私の問題の例です。私のコードは誤って{1,2}={2,1}を想定しています:http://ideone.com/i7huL

#include <iostream>
#include <map>
using namespace std;

struct myStruct {
  int a;
  int b;
  bool operator<(const myStruct& rhs) const {
           return rhs.a < this->a && rhs.b < this->b;
  }
};


int main() {
       std::map  <myStruct, int> mymap ;
       myStruct m1={1,2};
       myStruct m2={2,1};
       mymap.insert(make_pair(m1,3));
       std::map<myStruct, int>::iterator it1 = mymap.find(m1);
       std::map<myStruct, int>::iterator it2 = mymap.find(m2);
       cout << it1->second << it2->second;
       // here it1->second=it2->second=3, although I would have expected it2 to be equal to map.end().
}

使用できます|| &&の代わりに、しかしこれが正しい方法かどうかはわかりません。リンクしたコードの場合のように、エラーを発生させずにマップ内のオブジェクトを検索できるように、operator<を実装したいだけです。

ありがとう。

4

7 に答える 7

7

はい、この演算子の実装はあまり意味がありません。私がお勧めします:

  bool operator<(const myStruct& rhs) const {
      return rhs.a < this->a || (rhs.a == this->a && rhs.b < this->b);
  }
于 2012-07-28T19:15:20.283 に答える
7
bool operator<(const myStruct& rhs) const {
  if (a < rhs.a) return true;
  if (a == rhs.a) return b < rhs.b;
  return false;
}

多くのデータメンバーへの一般化を探している場合は、C ++ 11 std :: tie:を使用した優れた例があります。

struct S {
    int n;
    std::string s;
    float d;
    bool operator<(const S& rhs) const {
        return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d);
    }
};
于 2012-07-28T19:18:03.673 に答える
5

問題は、オペレーターが厳密な弱順序を定義していないことです。あなたの例がどのようにあなたのオペレーターに降りかかるか{1,2}を考えてみてください。、、およびを{2,1}想定します。X = {1,2}Y = {2,1}

X <Yですか?1 <2 AND 2 <1ですか?いいえ、したがってXはY以上です。

Y <Xですか?2 <1 AND 1 <2ですか?いいえ、したがってYはX以上です。

では、XがY以上で、YがX以上の場合、何が残っているのでしょうか。それらは等しい。

構造体のメンバーの1つを選択するか、主要な比較にする必要がありaますb。一次比較の結果が等しい場合にのみ二次比較をチェックします。何かをアルファベット順に並べるときと同じように。最初に最初の文字をチェックし、それらが等しい場合にのみ次の文字に進みます。ハンス・パッサントはこの例を提供しています。

これは、オペレーターにとってより深刻な問題の例です。上で示したものは必ずしも悪いわけではありません。おそらくあなたはに等しいと見なされたい からです。基本的な問題は、次のような一連の値で発生します。{1,2}{2,1}X = {1,1}, Y = {1,2}, Z = {2,2}

演算子を使用すると、1は2未満であるため、Xは間違いなくZよりも小さくなります。ただし、XはYに等しく、YはZに等しくなります。厳密な弱順序に従うために、X = Y、およびYの場合= Zの場合、XはZと等しくなります。ただし、ここではそうではありません。

于 2012-07-28T19:24:26.887 に答える
3

あなたは4つのintメンバーに一般化することについて質問しました、これが私が最大の明快さのためにそのようなコードをどのように構成するかです。

bool operator<(const myStruct& rhs) const
{
  if (a < rhs.a)
    return true;
  if (a > rhs.a)
    return false;
  if (b < rhs.b)
    return true;
  if (b > rhs.b)
    return false;
  if (c < rhs.c)
    return true;
  if (c > rhs.c)
    return false;
  if (d < rhs.d)
    return true;
  if (d > rhs.d)
    return false;
  return false;
}

このようなコードは、必要な数のデータメンバーに簡単に拡張できます。

于 2012-07-28T19:24:10.613 に答える
1

最も単純なソリューションはstd::tie、タプルを比較するために使用します。

return std::tie(rhs.a, rhs.b) < std::tie(a, b);

これは、非常に迅速かつ簡単に、より多くのデータメンバーに一般化されます。

于 2012-07-28T19:33:06.470 に答える
1

私は、異なる要素が2つ見つかるまで、要素が等しいかどうかを比較してこれを書くことを好みます。

bool operator<(const myStruct& rhs) const {
    if (a != rhs.a)
        return a < rhs.a;
    if (b != rhs.b)
        return b < rhs.b;
    return false; // this and rhs are equal.
}

||を組み合わせて単一の式を書くよりも、これがより明確で拡張可能であることがわかります。および&&(@HansPassantによる)、および各合格テストをareturn true;またはに導く@jahhajのアプローチよりもコンパクトですreturn false;。値の分布について何かを知らない限り、パフォーマンスはほぼ同じです。operator==()を避けて使用するという議論がありますが、operator<()それは最大限に一般的なテンプレートコードを書き込もうとしている場合にのみ当てはまります。

于 2012-07-29T17:40:22.217 に答える
0

問題は、構造が何を表しているのかを知る必要があるということです。そうしないと、<演算子の定義は任意になります。他の人はあなたに適切な答えを与えることができません。構造が2Dの点のカルチス座標を表す場合の例を考えてみましょう。この場合、構造の原点からの距離など、意味のある順序付け演算子を定義できます。

つまり、距離d1 = this-> a * this-> a + this-> b *this->b距離d2=rhs.a * rhs.a + rhs.b * rhs.b if(d1 <d2)return true ; それ以外の場合はfalseを返します。

于 2012-07-28T19:26:29.873 に答える