我有2个翻译单位.在一个(称为util.cpp / h)中,我声明并定义了两个运算符(我忽略了可读性的真正实现,无论如何,problam都会发生):
// 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 }
为什么当没有运算符>>编译器找到正确的运算符在命名空间中,找不到有什么时候?为什么运算符影响编译器找到正确的能力,即使它有不同的签名?
解决这个问题的一个尝试就是放了
的std :: istream的&安培;运算符>>(std :: istream& is,const char * str){:: operator>>(is,str); }
解决方法
A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived
class (10.2).
您的案例中的“名称”将是运算符>>命名空间构成嵌套声明区域.
解决这个问题的最简单方法是使用一个使用声明来声明命名空间本地运算符<< ;:
namespace your_namespece { std::istream& operator>>(std::istream& is,SomeClass& obj) { return is; }; using ::operator>>; }
请注意,此功能不会干扰Koenig查找(至少在您的情况下,原则上可以),因此仍然会找到std ::的IO运算符.
PS:另一种工作方式是将这个问题定义为SomeClass的运算符为inline friend
.这些函数在命名空间级别(“他们的”类之外)被声明,但从那里不可见.他们只能通过Koenig查找找到.