【问题标题】:Clang and g++ treat operator overload differently?Clang 和 g++ 对待运算符重载的方式不同吗?
【发布时间】:2015-03-24 13:44:09
【问题描述】:

我正在使用 C++14(-std=c++1y 在 g++ 4.9.1 和 clang 3.5 上)。

首先,这里是 Exhibit A(存在 Foo 命名空间):

#include <iostream>
#include <sstream>

namespace Foo
{
    struct A
    {};
}

void operator<<(std::ostream &os, Foo::A const &a)
{}

int main()
{
    Foo::A a;

    std::ostringstream() << a;

    return 0;
}

Clang 和 g++ 都对此表示反对,尽管出于不同的原因。


Exhibit B(没有 Foo 命名空间):

#include <iostream>
#include <sstream>

struct A
{};

void operator<<(std::ostream &os, A const &a)
{}

int main()
{
    A a;

    std::ostringstream() << a;

    return 0;
}

g++ 仍然出错,但 Clang 成功编译。

这是合理的预期吗?这是怎么回事?

【问题讨论】:

  • 我见过一些关于将临时值绑定到非常量引用的 cmets。我要提出两点:首先,通过将上面的代码更改为 void operator
  • @NeilKirk 我认为您不小心编译了(工作)左值版本。这是我遇到麻烦的右值。
  • 当operatorstd::operator&lt;&lt;,它接受basic_ostream&lt;CharT,Traits&gt;&amp;&amp;
  • @NeilKirk 我发现这是 Clang 和 g++ 之间的区别。当结构 A 不在命名空间中时,Clang 将编译代码而 g++ 不会。当 struct A 在 Foo 命名空间中时,编译器都不喜欢它。
  • 这是一个问题。这是 libstdc++ vs libc++。

标签: c++ namespaces operator-overloading rvalue


【解决方案1】:

首先,该标准为右值输出流 ([ostream.rvalue]) 提供了一个包罗万象的operator&lt;&lt;

template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);

效果os &lt;&lt; x

返回os

(对于右值输入流还有一个匹配的operator&gt;&gt; - 请参阅 [istream.rvalue]。)

这是被调用的operator&lt;&lt;

其次,与模板通常一样,在此函数模板的主体中,os &lt;&lt; x 中的operator&lt;&lt; 的非限定查找是在模板定义上下文中完成的,它没有您的operator&lt;&lt; 可用。相反,您的重载必须由 ADL 找到,这反过来意味着它必须与 A 在同一个命名空间中。

您的第二个版本应该可以编译,并且在这两种情况下编译器都发现您的重载很好。问题是 libstdc++ 的实现(归结为 return os &lt;&lt; x;)不符合要求,因为它假定 os &lt;&lt; x 必须返回 os。没有这个要求。

编辑:libstdc++ 错误报告为here;此后它已在主干中修复,并且该修复已向后移植到 4.8 和 4.9 分支。

【讨论】:

    【解决方案2】:

    不允许将临时对象绑定到非常量引用。在这种情况下std::ostringstream() 创建一个临时对象并尝试绑定到operator&lt;&lt; 的非常量引用参数

    【讨论】:

    • 我可以通过仅从 Foo 命名空间中删除 struct A 来编译它(即,只需将其放在全局命名空间中,然后在运算符中将 Foo::A 更改为 A
    • @Badmanchild 你确定吗?你能提供 ideone 链接吗?
    • 我会放在那里 -- 一秒钟
    • 嗯,你是对的——我把它放在 ideone 上,得到了和你一样的错误。这似乎是g ++和clang之间的区别......这是clang已经实现但g ++尚未解决的C ++ 14-ish吗?还是编译这段代码的时候clang出错了?
    • 我也是用g++本地编译的,和你一样报错,所以不是ideone的问题。
    猜你喜欢
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    • 1970-01-01
    相关资源
    最近更新 更多