web-dev-qa-db-ja.com

C ++では、両方向でoperator ==をオーバーロードする必要がありますか?

私がクラスで働いているとしましょう:

class Foo{
public:
  std:string name;
  /*...*/
}/*end Foo*/

そして私はoperator==のオーバーロードを提供します

bool operator==(const Foo& fooObj, const std::string& strObj) {
    return (fooObj.name == strObj);
}

同じロジックを逆に再実装する必要もありますか?

bool operator==(const std::string& strObj, const Foo& fooObj) {
    return (strObj == fooObj.name);
}
54
hehe3301

(C++ 20以降)

p1185 をC++ 20に受け入れれば、複数のオーバーロードを提供する必要はありません。この論文は、(とりわけ)標準にこれらの変更を加えました。

[over.match.oper]

3.4 -[...] !=演算子([expr.eq])の場合、書き換えられた候補には、演算子==のすべてのメンバー、非メンバー、および組み込み候補が含まれます。書き換えられた式(x == y)は、その演算子==を使用してコンテキスト的にboolに変換されたときに整形式になります。等価演算子の場合、書き換えられた候補には、各メンバー、非メンバー、および書き換えられた式==が整形式である演算子(y == x)の組み込み候補の2つのパラメーターの順序が逆になった合成候補も含まれますその演算子==を使用してコンテキスト的にブールに変換された場合。 [注:メンバー候補から合成された候補は、2番目のパラメーターとして暗黙的なオブジェクトパラメーターを持っているため、2番目のパラメーターではなく、最初のパラメーターに対して暗黙的な変換が考慮されます。 —注] [...]

8 [...]書き換えられた候補が!=演算子のオーバーロード解決によって選択された場合、選択された候補がパラメーターの順序が逆の合成候補である場合、x != y(y == x) ? false : trueとして解釈されます。または、(x == y) ? false : trueそれ以外の場合は、選択された書き換え済みoperator==候補を使用します。書き換えられた候補が==演算子のオーバーロード解決によって選択された場合、x == yは選択された書き換えられた(y == x) ? true : false候補を使用してoperator==として解釈されます。

上記は、オペランドの順序を逆にした演算子をnotだけでなく、無料で!=も取得できることを意味します!さらに、operator==関数は、意味があればメンバーになることができます。上記の最初の段落のメモにあるように、それがメンバーまたはフリー関数であると暗黙の変換に影響するため、それを覚えておく必要があります。


(C++ 17まで)

文字列が左側にあり、Fooが右側にある比較をサポートする場合に行います。実装は、オーバーロードされたoperator==への引数を並べ替えて動作させません。

ただし、実装のロジックを繰り返すことは避けられます。オペレーターが期待どおりに動作する必要があると仮定します。

inline bool operator==(const std::string& objA, const Foo& objB) {
    return objB == objA; // Reuse previously defined operator
}
75
StoryTeller

そうです。他の多くの言語と同じように、C++は面倒で、異なる型の2つのオブジェクト間の比較では、順序に応じて2つの異なる比較演算子が呼び出されます。

もちろん、あなたはそれらが一貫していて驚くべきことではないことを望んでいるので、2番目は最初の観点から定義されるべきです。

6