111

(注: BoostまたはC ++ 11tupleからtie取得できます。)
2つの要素のみを含む小さな構造体を作成する場合、厳密な弱順序のstd::pairように、そのデータ型に対してすべての重要な処理が既に行われているため、を選択する傾向があります。 operator<
ただし、欠点は、ほとんど役に立たない変数名です。私自身がそれを作成したとしても、特に両方が同じタイプである場合、2日後に正確に何がtypedef何であったかを思い出せません。これは、2人以上のメンバーにとってはさらに悪化します。これは、ネストが非常に悪いためです。 そのための他のオプションはfirstsecondpair
tuple、BoostまたはC ++ 11のいずれかからですが、それは実際には見栄えがよくありません。それで、必要な比較演算子を含めて、自分で構造体を書くことに戻ります。
特に、operator<は非常に面倒な場合があるため、次のように定義された操作に依存するだけで、この混乱全体を回避することを考えましたtuple

operator<:たとえば、strict-weak-orderingの場合:

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作成します。)tupleT&


編集:@DeadMGから個人的に継承するという提案tupleは悪いものではありませんが、かなりの欠点があります:

  • オペレーターが独立している場合(おそらく友達)、私は公に継承する必要があります
  • キャスティングを使用すると、私の関数/演算子(operator=具体的には)を簡単にバイパスできます
  • このtieソリューションを使用すると、特定のメンバーが注文に関係ない場合は除外できます

この実装には、考慮する必要のある欠点がありますか?

4

4 に答える 4

66

これにより、正しいオペレーターを自分でローリングするよりも簡単に作成できるようになります。プロファイリングにより、比較操作がアプリケーションの時間のかかる部分であることが示された場合にのみ、別のアプローチを検討することをお勧めします。それ以外の場合、これを維持することの容易さは、考えられるパフォーマンスの問題よりも重要です。

于 2011-06-02T19:07:04.757 に答える
5

私はこれと同じ問題に遭遇し、私のソリューションでは 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
);
于 2013-05-10T07:37:53.583 に答える
3

私の意見では、解決策と同じ問題にまだ取り組んでいません。std::tupleつまり、各メンバー変数の数と名前の両方を知る必要があり、関数で2回複製しています。private継承を選択できます。

struct somestruct : private std::tuple<...> {
    T& GetSomeVariable() { ... }
    // etc
};

このアプローチは、最初は少し混乱していますが、オーバーロードするすべての演算子のすべての場所ではなく、変数と名前を 1 か所に維持するだけです。

于 2011-06-02T19:13:31.263 に答える
1

複数の演算子のオーバーロード、またはタプルの複数のメソッドを使用する予定がある場合は、タプルをクラスのメンバーにするか、タプルから派生させることをお勧めします。そうでなければ、あなたがしていることは、より多くの仕事です。この 2 つのどちらかを決定するとき、答えるべき重要な質問は次のとおりです。クラスをタプルにしたいですか? そうでない場合は、タプルを含め、委任を使用してインターフェイスを制限することをお勧めします。

タプルのメンバーを「名前変更」するためのアクセサーを作成できます。

于 2011-06-02T19:51:17.513 に答える