简体   繁体   English

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

[英]Operator overloading clang++ and g++ different output

With this sample program I observe a different behavior in g++ and clang 通过这个示例程序,我在g ++和clang中观察到了不同的行为

Foo.h: 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 Foo.cpp中

#include <Foo.h>

using namespace std;

ostream& operator <<(ostream& os, const Bar::Foo* foo)
{
    return os << foo->x();
}

main.cpp 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);
}

Compiling with clang++ and g++ produce different results: 使用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

Which one is correct and why?. 哪一个是正确的,为什么?

In this particular case, clang++ is correct. 在这种特殊情况下,clang ++是正确的。

The problem is how lookup is performed inside the template print . 问题是如何在模板print内执行查找。 In the expression inside print the call to operator<< is dependent . print的表达式中,对operator<<的调用是依赖的 Name resolution for dependent names is handled in 14.6.4: 从属名称的名称解析在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. - 来自实例化上下文(14.6.4.1)和定义上下文中与函数参数类型相关联的名称空间的声明。

In your case, the declaration of your operator is not visible at the point of definition of the template, since the header is included afterwards, and it does not live in any of the associated namespaces of the function arguments (namely ::std for ::std::ostream and ::Bar for ::Bar::Foo* ), so it won't be found. 在您的情况下,您的运算符的声明在模板定义时是不可见的,因为之后包含标头,并且它不存在于函数参数的任何关联命名空间中(即::std for ::std::ostream::Bar for ::Bar::Foo* ),因此无法找到它。

Now, there is an overload in ::std that takes a void* , and that will be found by Argument Dependent Lookup. 现在, ::std中有一个带有void*的重载,并且可以通过Argument Dependent Lookup找到。 The ::Bar::Foo* will be converted to a void* and the address will be printed. ::Bar::Foo*将转换为void*并打印地址。

That is, in a standard compliant compiler. 也就是说,在符合标准的编译器中。

I forgot to add this here, and left it only in the comment, but it is important enough: 我忘了在这里添加这个,只留在评论中,但这很重要:

Always define the operators that apply to your types in the same namespace that holds the types on which they apply. 始终在包含它们所应用的类型的同一名称空间中定义应用于类型的运算符。 Let Argument Dependent Lookup do it's magic for you. 让Argument Dependent Lookup让你觉得它很神奇。 It was specifically designed to serve this particular purpose, use it. 它专门用于服务于此特定目的,使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 g ++和clang ++使用运算符&lt;()重载的不同行为 - g++ and clang++ different behaviour with operator<() overloading clang ++与g ++的-fsanitize = address的不同输出 - different output for -fsanitize=address with clang++ vs g++ 继承模板化的operator = in C ++ 14:与g ++和clang ++的不同行为 - Inheriting templated operator= in C++14: different behaviour with g++ and clang++ 这是 g++ 或 clang++ 中的错误 - Is this a bug in g++ or clang++ C ++朋友函数模板重载和SFINAE在clang ++,g ++,vc ++中的不同行为(C ++ 14模式) - C++ friend function template overloading and SFINAE different behaviors in clang++, g++, vc++ (C++14 mode) g ++和clang ++使用静态成员的递归初始化的不同行为 - g++ and clang++ different behaviour with recursive initialization of a static member g ++和clang ++使用变量模板和SFINAE的不同行为 - g++ and clang++ different behaviour with variable template and SFINAE g ++和clang ++使用指向可变参数模板函数的指针的不同行为 - g++ and clang++ different behaviour with pointer to variadic template functions g ++和clang ++使用自动参数的模板特化的不同行为 - g++ and clang++ different behaviour with template specialization for auto argument g++ 和 clang++ 与可变参数容器的不同行为 - g++ and clang++ different behaviour with variadic container
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM