(注:Tuple
およびtie
は、BoostまたはC++ 11から取得できます。)
2つの要素のみを含む小さな構造体を作成するとき、厳密な弱順序のためのstd::pair
のように、そのデータ型に対してすべての重要な処理が既に行われているため、operator<
を選択する傾向があります。
欠点は、ほとんど役に立たない変数名です。たとえ自分でtypedef
を作成したとしても、2日後にfirst
とsecond
が正確に何であったか、特に両方が同じタイプである場合は思い出せません。 pair
sをネストするとかなりひどいので、これは3つ以上のメンバーではさらに悪化します。
そのためのもう1つのオプションは、BoostまたはC++ 11のTuple
ですが、実際には見栄えがよく明確ではありません。そこで、必要な比較演算子を含め、構造体を自分で書くことに戻ります。
特にoperator<
は非常に面倒なので、Tuple
に定義された操作に依存するだけでこの混乱を回避することを考えました。
operator<
の例、例:厳密な弱順序付けの場合:
bool operator<(MyStruct const& lhs, MyStruct const& rhs){
return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}
(tie
は、渡された引数からT&
のTuple
参照を作成します。)
編集:Tuple
をプライベートに継承する@DeadMGからの提案は悪いものではありませんが、かなりの欠点があります。
operator=
)を簡単にバイパスできますtie
ソリューションを使用すると、特定のメンバーが順序に関係ない場合は除外できますこの実装に考慮する必要がある欠点はありますか?
これにより、正しい演算子を自分で作成するよりも簡単に作成できるようになります。プロファイリングで比較操作がアプリケーションの時間のかかる部分であることが示されている場合にのみ、別のアプローチを検討してください。さもなければ、これを維持することの容易さは、可能なパフォーマンスの懸念を上回るはずです。
私はこの同じ問題に遭遇し、私のソリューションはc ++ 11可変長テンプレートを使用しています。コードは次のとおりです。
.h部分:
/***
* Generic lexicographical less than comparator written with variadic templates
* Usage:
* pass a list of arguments with the same type pair-wise, for intance
* lexiLessthan(3, 4, true, false, "hello", "world");
*/
bool lexiLessthan();
template<typename T, typename... Args>
bool lexiLessthan(const T &first, const T &second, Args... rest)
{
if (first != second)
{
return first < second;
}
else
{
return lexiLessthan(rest...);
}
}
そして、引数なしの基本ケースの.cpp:
bool lexiLessthan()
{
return false;
}
これで、例は次のようになります。
return lexiLessthan(
lhs.one_member, rhs.one_member,
lhs.another, rhs.another,
lhs.yet_more, rhs.yet_more
);
私の意見では、あなたはまだstd::Tuple
解決策と同じ問題に取り組んでいない、つまり、各メンバー変数の数と名前の両方を知る必要があり、関数でそれを2回複製している。 private
継承を選択できます。
struct somestruct : private std::Tuple<...> {
T& GetSomeVariable() { ... }
// etc
};
このアプローチはlittle少し複雑ですが、オーバーロードするすべての演算子のすべての場所ではなく、1つの場所で変数と名前を維持するだけです。
複数の演算子オーバーロード、またはTupleの複数のメソッドを使用する場合は、Tupleをクラスのメンバーにするか、Tupleから派生させることをお勧めします。そうでなければ、あなたがしていることはもっと多くの仕事です。 2つの間で決定するとき、答えるべき重要な質問は次のとおりです。クラスにbeタプルを追加しますか?そうでない場合は、タプルを含め、委任を使用してインターフェイスを制限することをお勧めします。
タプルのメンバーを「名前変更」するためのアクセサーを作成できます。