gpt4 book ai didi

c++ - 运算符重载 clang++ 和 g++ 不同的输出

转载 作者:可可西里 更新时间:2023-11-01 16:34:36 26 4
gpt4 key购买 nike

通过这个示例程序,我观察到 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();
}

主要.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 中处理:

In resolving dependent names, names from the following sources are considered:

— Declarations that are visible at the point of definition of the template.

— Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context.

在你的例子中,你的运算符的声明在模板的定义点是不可见的,因为 header 是在之后包含的,并且它不存在于函数参数的任何关联命名空间中(即 ::std ::std::ostream::Bar::Bar::Foo* ),所以它不会被发现。

现在,在 ::std 中有一个重载需要一个 void* ,它将通过参数相关查找找到。 ::Bar::Foo* 将转换为 void* 并打印地址。

也就是说,在符合标准的编译器中。

我忘了在这里添加这个,只留在评论中,但它很重要:

始终 在包含它们所应用的类型的同一命名空间中定义适用于您的类型的运算符。让 Argument Dependent Lookup 为您施展魔法。它专为满足这一特定目的而设计,请使用它。

关于c++ - 运算符重载 clang++ 和 g++ 不同的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15975739/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com