上記のコードの問題は、が定義されているかどうかではなく、ルックアップ*operator!=
によって決して見つからないという事実です。
関数をクラスのフレンドとして宣言すると、宣言は名前空間レベルの関数を宣言するという意味で奇妙ですが、その宣言は、囲んでいる型の ADL を介してのみ使用できます。yourは2 つの引数のいずれもoperator!=
とらないため、事実上、ルックアップで見つけることは不可能です。IneqComp
operator!=
一連の型で利用できるのデフォルトの実装を提供したい場合は、さまざまな方法で問題に取り組むことができます。
IneqCmp
まず、継承を使用して ADL セットに追加できます。
struct IntCont : IneqCmp<IntCont> {
// ...
};
IneqCmp<IntCont>
ADL は引数のクラスと基本クラスを検索するため、内部でルックアップが効果的にトリガーされ、friend
宣言とフリー関数が検索されます。
もう 1 つの方法は、ジェネリックoperator!=
が定義される名前空間 (他の方法では見つからないようにするため) とtag
型を追加することです。次に、そのタグから継承します。
namespace inequality_comparable {
struct tag {};
template <typename T>
bool operator!=( T const & a, T const & b ) {
return !(a==b);
}
}
struct IntCont : inequality_comparable::tag {
};
bool operator==( IntCont const & a, IntCont const & b ) {
return ...;
}
int main() {
IntCont a,b;
std::cout << a != b << "\n";
}
ここでの秘訣はinequality_comparable::tag
、 が型のベースであるためinequality_comparable
、ルックアップに名前空間を追加することです。コンパイラが遭遇a != b
すると、現在のスコープで定義されたクラス、クラスとそのベース、およびそのベースが定義されている名前空間main
を使用しようとします。operator!=
IntCont
IntCont
*オペレーターが実際に生成されたことを確認したい場合は、追加してみてください。
bool operator!=(IntCont a, IntCont b){
return !(a==b);
}
インスタンス化のために演算子が定義されている場合、IneqCmp
コンパイラ エラーが発生します。または、シンボルの生成されたオブジェクト ファイルをコンパイルして調べることもできます。