少し概要。私は強力なtypedefを提供するクラステンプレートを書いています。強力なtypedefによって、私はエイリアスを宣言した通常のtypedefとは対照的です。std :: vectorとstd :: stringの比較演算子がテンプレート関数として定義されているのはなぜですか?
using EmployeeId = StrongTypedef<int>;
は今、強い型定義と暗黙の変換上の思考の別の学校があります。アイデアを与えるために。これらの学校の1つは、すべての整数がEmployeeIdであるわけではありませんが、すべてのEmployeeIdは整数なので、EmployeeIdから暗黙の変換を整数に許可する必要があります。そして、あなたはこれを実装し、のようなものを書くことができます:x
は暗黙的に整数に変換される、その後、整数等価比較が使用されているので、
EmployeeId x(4);
assert(x == 4);
これは動作します。ここまでは順調ですね。
std::vector<int> v1{1,2};
EmployeeScores e(v1);
std::vector<int> v2(e); // implicit conversion
assert(v1 == v2);
しかし、私はまだこれを行うことはできません:だから私はこのようなことを行うことができます
using EmployeeScores = StrongTypedef<std::vector<int>>;
:今、私は整数のベクトルでこれをやりたい
assert(v1 == e);
を
これがうまくいかない理由は、std::vector
がその等価性チェックをどのように定義しているかにあります。
template <class T, class A>
bool operator==(const vector<T,A> & v1, const vector<T,A> & v2) {
...
}
これは関数テンプレートです。ルックアップの初期段階で破棄されるため、暗黙的にベクトルに変換される型を比較することはできません。平等を定義するための
別の方法は次のように次のようになります。この第2のケースで
template <class T, class A = std::allocator<T>>
class vector {
... // body
friend bool operator==(const vector & v1, const vector & v2) {
...
}
} // end of class vector
、等価演算子は次のように、それはクラスと一緒に生成されています普通の機能ですが、関数テンプレートではありませんメンバー関数これは友人のキーワードによって可能になる珍しいケースです。
質問がありました(ごめんなさい、背景が長かったです)、なぜstd::vector
は最初のフォームの代わりに2番目のフォームを使用していませんか?これにより、vector
はプリミティブ型のように振る舞います。そして、あなたがはっきりとわかるように、私のユースケースに役立ちます。 string
では、string
がクラステンプレートの単なるtypedefであることを忘れやすいので、この動作はさらに驚くべきことです。
友人の関数がクラスで生成されるため、ベクトルの含まれた型が等価比較をサポートしていないと、ハードエラーが発生することがあります。これはそうではありません;テンプレートクラスのメンバ関数のように、未使用の場合は生成されません。第2に、より一般的なケースでは、フリー関数は、クラスと同じヘッダに定義する必要がないという利点があり、利点があります。しかし、これは明らかにここで利用されていません。
だから、何ができますか?これには正当な理由があるのですか、それとも最適ではない選択ですか?
編集:私は2つのことを示す簡単な例を書いた:暗黙の変換は両方とも、友人のアプローチでは望みどおりに動作し、テンプレート化された型が等価演算子の要件を満たさないその場合、等価演算子が使用されていないと仮定すれば明らかです)。編集:最初のアプローチ:http://coliru.stacked-crooked.com/a/6f8910945f4ed346と対照的に改善されました。
なぜこれがダウンリストされましたか? – Untitled123
'friend'versionを使って、' assert(v1 == e); 'がコンパイルされますか? – YSC
@YSCはい、私はColiruへのリンクを追加しました。あなたの質問に完全に対処すれば教えてください。 –