問題
A
自然な順序付け ( を持つoperator<
) と複数の代替順序付け (大文字と小文字を区別する、大文字と小文字を区別しないなど)を持つカスタム型があります。これで、std::pair
(またはstd::tuple
) からなる (1 つまたは複数の) ができA
ました。std::pair<A, int>
比較したいタイプの例を次に示しstd::pair<int, A>
ます。の比較関数をプラグインして、デフォルトの要素ごとの比較実装を使用して(または) を比較するにはどうすればよいですか?std::tuple<A, int, int>
std::tuple<int, A, int>
std::pair
std::tuple
A
コード
以下のコードはコンパイルされません。
#include <utility> // std::pair
#include <tuple> // std::tuple
#include <iostream> // std::cout, std::endl
struct A
{
A(char v) : value(v) {}
char value;
};
// LOCATION-1 (explained in the text below)
int main()
{
std::cout
<< "Testing std::pair of primitive types: "
<< (std::pair<char, int>('A', 1)
<
std::pair<char, int>('a', 0))
<< std::endl;
std::cout
<< "Testing std::tuple of primitive types: "
<< (std::tuple<char, int, double>('A', 1, 1.0)
<
std::tuple<char, int, double>('a', 0, 0.0))
<< std::endl;
// This doesn't compile:
std::cout
<< "Testing std::pair of custom types: "
<< (std::pair<A, int>('A', 1)
<
std::pair<A, int>('a', 0))
<< std::endl;
return 0;
}
operator<
に対して が定義されていないためですstruct A
。上記に追加するとLOCATION-1
、問題が解決します。
bool operator<(A const& lhs, A const& rhs)
{
return lhs.value < rhs.value;
}
これで、 の別の順序付けができましたstruct A
。
bool case_insensitive_less_than(A const& lhs, A const& rhs)
{
char const lhs_value_case_insensitive
= ('a' <= lhs.value && lhs.value <= 'z'
? (lhs.value + 0x20)
: lhs.value);
char const rhs_value_case_insensitive
= ('a' <= rhs.value && rhs.value <= 'z'
? (rhs.value + 0x20)
: rhs.value);
return lhs_value_case_insensitive < rhs_value_case_insensitive;
}
operator<
元の for struct A
(大文字と小文字を区別するもの)を保持したい場合std::pair<A, int>
、この別の順序とどのように比較できるでしょうか?
operator<
forの特別なバージョンを追加するとstd::pair<A, int>
問題が解決することはわかっています。
bool operator<(std::pair<A, int> const& lhs, std::pair<A, int> const& rhs)
{
return (case_insensitive_less_than(lhs.first, rhs.first)
? true
: case_insensitive_less_than(rhs.first, lhs.first)
? false
: (lhs.second < rhs.second));
}
ただし、これは次善の解決策だと思います。
まず、 の場合std::pair
、要素単位の比較を再実装するのは簡単ですが、それはstd::tuple
複雑で (可変個引数テンプレートの処理)、エラーが発生しやすい可能性があります。
第 2 に、これが問題を解決するためのベスト プラクティスの方法であるとはほとんど信じられません。operator<
次のクラスのそれぞれに対して の特殊なバージョンを定義する必要があると想像してください: std::tuple<A, int, int>
、std::tuple<int, A, int>
、std::tuple<int, int, A>
、std::tuple<A, A, int>
... (これは実際的な方法でさえありません) !)
operator<
よく書かれた組み込みのforを再利用し、私の forstd::tuple
をプラグインすることは、私が望むものです。出来ますか?前もって感謝します!less-than
struct A