12

重複の可能性:
「tuple」と「tie」を介して比較演算子を実装するのは良い考えですか?


時々私はいくつかの醜いファンクターを書く必要があります。

lhs.date_ < rhs.date_ ||
lhs.date_ == rhs.date_ && lhs.time_ < rhs.time_ ||
lhs.date_ == rhs.date_ && lhs.time_ == rhs.time_ && lhs.id_ < rhs.id_ .....

それは本当に私を悩ませました。
だから私は次のような書き込みを避け始めました:

std::make_tuple( lhs.date_, lhs.time_, lhs.id_ ) < 
    std::make_tuple(rhs.date_, rhs.time_, rhs.id_ );

私はほとんど満足していますが、おそらく目的のためにタプルを使用していないことに注意してください。

このソリューションを批判できますか?
それとも良い習慣ですか?
そのような比較をどのように回避しますか?

更新:
オブジェクトのコピーを避けるために std::tie を指摘してくれてありがとう。
そして、重複した質問を指摘してくれてありがとう

4

2 に答える 2

14

std::tuple比較演算子の宣言には、次のように記載されています。

lhs と rhs を辞書式に比較します。つまり、最初の要素が等しい場合はそれらを比較し、2 番目の要素が等しい場合はそれらを比較し、3 番目の要素を比較する、というように続きます。

だから、あなたがしていることは、不要な一時的なものを作成する可能性を除いて(おそらく最適化されていない)、私には問題ないようです。

equalityはでは!( lhs < rhs ) && !( rhs < lhs )なくを意味することに注意してください。それはequalityです。同等同等がクラスで同じ意味であると仮定すると、これで問題ありません。これは、たとえばキーによる/へのアクセスと同じであることに注意してください。lhs == rhssetmap

一時変数を回避するために、引数への左辺値参照std::tieのタプルを作成する which を使用できます。

std::tie( lhs.date_, lhs.time_, lhs.id_ ) < 
    std::tie( rhs.date_, rhs.time_, rhs.id_ );

同様に、右辺値参照std::forward_as_tupleのタプルを作成します。

于 2012-05-29T20:19:17.953 に答える
0

make_tupleの代わりにtieを使用する方が良い場合があります(メンバーのコピー/移動を回避する価値があるかどうかによって異なります)が、そうでない場合はこれで機能し、ひどいことは何もありません。

あなたがそれについて考えるならば、多くのPOD構造体は基本的に「名前付きタプル」であり、C ++は実際、メンバーごとの同等性比較(およびコピー、移動など)を提供することによってそれに対応し、ほとんどの場合、それを( lexicographical)by-memberless-than比較も意味があります。ただし、残念ながら、C ++は、明示的に書き出す以外に、メンバーの辞書式比較を指定する方法を提供していません。もちろん、内省的な言語では追加するのは非常に簡単ですが、C++ではそうではありません。

明白な答えの1つは、クラスを実際に名前付きタプルにすることです。メンバーをintdate_、int64_t time_、およびstring id_にする代わりに、タプルから継承し、タプルネスをユーザーから隠すアクセサーメソッドを記述します。しかし、この場合、比較実装の醜さをアクセサー実装の醜さと交換しただけであり、それがより良いかどうかは明らかではありません。

マクロを使用して醜さをまとめることもできますが、これはおそらくそれほど良いことではありません。

DEFINE_NAMED_TUPLE_CLASS(MyDate, int date, int64_t time, string id)
  ...
END_NAMED_TUPLE_CLASS

または、タグを「class」に変更して比較演算子を定義するだけで処理する「named_tuple_class」を持つ拡張C++を前処理できる独自の外部コードジェネレーターを構築することもできます。しかし、それは大変な作業です。

于 2012-05-29T20:40:48.693 に答える