微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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.

在您的情况下,您的运算符的声明在模板定义点不可见,因为标题之后包含,并且它不存在于函数参数的任何关联命名空间中(即:: std for: :std :: ostream and :: Bar for :: Bar :: Foo *),所以它不会被找到.

现在,:: std中有一个重载,它占用一个void *,这将由Argument Dependent Lookup找到. :: Bar :: Foo *将被转换为一个void *,并打印地址.

也就是说,在标准兼容的编译器中.

我忘了在这里添加,只留在评论中,但它是足够重要的:

始终在同一个名称空间中定义适用于您的类型的运算符,该名称空间中包含它们应用的类型.让论据依赖查找对你来说是个魔术.它是专门为了这个特殊目的而设计的,使用它.

原文地址:https://www.jb51.cc/c/112077.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐