演算子のオーバーロードのC++解決の奇妙な動作を見つけました、私は自分自身を説明することはできません。それを説明するいくつかのリソースへのポインタは、答えと同じくらい素晴らしいでしょう。
私は2つの翻訳ユニットを持っています。1つ(util.cpp / hと呼ばれる)では、2つの演算子を宣言して定義します(読みやすさのために実際の実装を省略します。とにかく問題が発生します)。
// util.h
#ifndef GUARD_UTIL
#define GUARD_UTIL
#include <iostream>
std::istream& operator>>(std::istream& is, const char* str);
std::istream& operator>>(std::istream& is, char* str);
#endif
と:
//util.cpp
#include "util.h"
#include <iostream>
std::istream& operator>>(std::istream& is, const char* str) {
return is;
}
std::istream& operator>>(std::istream& is, char* str) {
return is;
}
これらの演算子は、もちろんグローバル名前空間にある場合、std型と組み込み型で動作し、どこからでも使用できるはずです。これらは、グローバル名前空間(たとえば、main()から)から、またはグローバル名前空間にあることをコンパイラーに明示的に通知することで正常に機能します(コード例を参照)。
別の変換ユニット(test.cpp / hと呼ばれる)では、名前空間内でこれらの演算子を使用します。これは、この名前空間に同様の演算子を配置するまで機能します。この演算子が追加されるとすぐに、コンパイラー(gccやclangなど)は実行可能な演算子>>を見つけることができなくなります。
// test.h
#ifndef GUARD_TEST
#define GUARD_TEST
#include <iostream>
namespace Namespace {
class SomeClass {
public:
void test(std::istream& is);
};
// without the following line everything compiles just fine
std::istream& operator>>(std::istream& is, SomeClass& obj) { return is; };
}
#endif
と:
//test.cpp
#include "test.h"
#include "util.h"
#include <iostream>
void Namespace::SomeClass::test(std::istream& is) {
::operator>>(is, "c"); //works
is >> "c" //fails
}
名前空間に演算子>>がないのに、コンパイラが正しい演算子を検出するのに、存在する場合は検出できないのはなぜですか?署名が異なっていても、演算子が正しいものを見つけるコンパイラの機能に影響を与えるのはなぜですか?
これを修正する1つの試みは、
std :: istream&operator >>(std :: istream&is、const char * str){:: operator >>(is、str); }
名前空間に入れますが、リンカーが以前の定義について文句を言うよりも。だから追加:なぜリンカーはコンパイラーが見つけられないものを見つけることができるのですか?