操作符重载clang++和g++不同的输出
Operator overloading clang++ and g++ different output
对于这个示例程序,我观察到g++和clang中的不同行为
foo:
#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);
}
用clang++和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
在这种特殊情况下,clang++是正确的。
问题是如何在模板print
中执行查找。在print
内部的表达式中,对operator<<
的调用依赖于。相关名称的名称解析在14.6.4:
在解析依赖名称时,考虑来自以下来源的名称:
-在模板定义点可见的声明。
-与实例化上下文(14.6.4.1)和定义上下文的函数实参类型相关联的命名空间的声明。
在你的例子中,你的操作符的声明在模板的定义点是不可见的,因为头文件是在之后包含的,它不存在于函数参数的任何相关的命名空间中(即::std::ostream
的::std
和::Bar::Foo*
的::Bar
),所以它不会被发现。
现在,在::std
中有一个重载,它接受一个void*
,它将通过参数依赖查找找到。::Bar::Foo*
将被转换为void*
,地址将被打印。
也就是说,在符合标准的编译器中。
我忘记在这里添加了,只在评论中留下了它,但它足够重要:
始终将应用于类型的操作符定义在保存其应用的类型的同一命名空间中。让参数依赖查找为你实现它的魔力。
相关文章:
- 递归函数计算序列中的平方和(并输出过程)
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 请解释"函数1(p1,p2,p3);"的输出
- C++:将控制台输出存储在宏中更好吗
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 为什么我的代码在输出中增加了93天
- 如何从void函数输出字符串
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- AES加密到解密未正确输出
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- C++格式化输出问题
- 将值从二维数组输出到文本文件
- 集合上的输出迭代器:assign和increment迭代器
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- 为什么rk4.do_step不输出C++中的初始条件
- 输出没有重复元素的动态数组(收缩数组)C++
- 如何根据单词在文本中出现的概率输出单词