Обнаружил странное поведение C++ разрешения перегрузки оператора -, объяснить не могу. Указатель на какой-то ресурс, описывающий его, был бы так же хорош, как и ответ.
У меня есть 2 единицы перевода. В одном (под названием util.cpp/h )я объявляю и определяю два оператора (я опускаю реальные реализации для удобства чтения, проблема возникает в любом случае):
// 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;
}
Эти операторы, конечно, находятся в глобальном пространстве имен, поскольку они работают со стандартными типами и встроены -в типы и должны использоваться везде. Они просто отлично работают из глобального пространства имен (, например. из 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
}
Почему компилятор находит правильный оператор, когда в пространстве имен нет operator>>, но не может найти, когда он есть? Почему оператор влияет на способность компилятора найти правильный, даже если он имеет другую сигнатуру?
Одной из попыток исправить это было поставить
std ::istream& operator>> (std ::istream& is, const char *str ){ ::operator>> (is, str ); }
в пространство имен, но тогда компоновщик жалуется на предыдущие определения. Так что дополнительно :Почему компоновщик может найти то, чего не находит компилятор?