c – 运算符超载cl和g不同的输出
使用这个示例程序,我观察到g和clang中的不同行为
foo.h中: #include <iostream> namespace Bar { class Foo { public: Foo(int x) : _x(x) {} int x() const { return _x; } private: int _x; }; } std::ostream& operator <<(std::ostream& os,const Bar::Foo* foo); Foo.cpp中 #include <Foo.h> using namespace std; ostream& operator <<(ostream& os,const Bar::Foo* foo) { return os << foo->x(); } main.cpp中 #include <iostream> using namespace std; template<typename T> void print(const T& t) { cout << t << endl; } #include <Foo.h> int main(int argc,char** argv) { Bar::Foo* foo = new Bar::Foo(5); print(foo); } 用俚语和g编译产生不同的结果: air:~ jose$clang++ Foo.cpp main.cpp -I. air:~ jose$./a.out 0x7ff9e84000e0 air:~ jose$g++ Foo.cpp main.cpp -I. air:~ jose$./a.out 5 哪一个是正确的,为什么? 解决方法
在这种特殊情况下,cl声是正确的.
问题是如何在模板打印中执行查找.在表达式中,打印对运算符<<是依赖的依赖名称的名称解析在14.6.4中处理:
在您的情况下,您的运算符的声明在模板定义点不可见,因为标题之后包含,并且它不存在于函数参数的任何关联命名空间中(即:: std for: :std :: ostream and :: Bar for :: Bar :: Foo *),所以它不会被找到. 现在,:: std中有一个重载,它占用一个void *,这将由Argument Dependent Lookup找到. :: Bar :: Foo *将被转换为一个void *,并打印地址. 也就是说,在标准兼容的编译器中. 我忘了在这里添加,只留在评论中,但它是足够重要的: 始终在同一个名称空间中定义适用于您的类型的运算符,该名称空间中包含它们应用的类型.让论据依赖查找对你来说是个魔术.它是专门为了这个特殊目的而设计的,使用它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |