问题 clang / g ++与朋友功能的区别


为什么下面的代码用g ++编译好但是在clang上得到错误?

#include <iostream>

class Object {};

class Print
{
public:
    template <typename CharT>
    inline friend std::basic_ostream<CharT> & operator<<(std::basic_ostream<CharT> & out, const Object&)
    {
        return (out << "object");
    }
    static void f( const Object& str )
    {
        std::cout << str;
    }
};

int main()
{
    std::cout << Object() << std::endl;
    return 0;
}

证明链接: 克++ / 铛++

当我将友元函数移动到全局命名空间时,为两个编译器编译好的代码(铛++ / 克++)。

在这种情况下,哪种实现更兼容C ++ Standart?


3041
2018-01-17 19:42


起源

Clang可能是对的。我认为这可能是重复的 stackoverflow.com/q/15745776/2073257 - Daniel Frey
@DanielFrey在我的情况下即使我删除模板我得到了同样的错误: coliru.stacked-crooked.com/a/765458742bfcea4d - alexolut
注: GCC 5.0拒绝你的例子。我想是的 gcc.gnu.org/bugzilla/show_bug.cgi?id=59366 两天前有一个修复程序 - Jonathan Wakely
Xeo对链接问题的评论是解释(独立于模板),同样也是@ TemplateRex在他对这个问题的回答中引用标准的引用。 - Daniel Frey


答案:


Clang在这里是正确的。在类中定义的友元函数只能在其参数上使用参数依赖查找而不是通过普通查找来查找。因为 Print 不是相关的范围 Objectoperator<< 不应该找到。标准的部分引用:

7.3.1.2命名空间成员定义[namespace.memdef]

3首先在名称空间中声明的每个名称都是其成员   命名空间。如果非本地类中的朋友声明首先声明   朋友是一个类,函数,类模板或函数模板97   最内层封闭命名空间的成员。 朋友的声明   本身不会使名称对非限定查找可见(3.4.1)   或合格的查找(3.4.3)。 [注意:朋友的名字将是   如果在提供匹配的声明,则在其命名空间中可见   命名空间范围(在类定义授予之前或之后)   友谊)。 - 结束说明] 如果朋友的功能或功能模板是   调用时,可以通过查找的名称查找找到其名称   来自名称空间的函数和与类型相关联的类   函数参数(3.4.2)。

正如@sehe提到的那样,添加一个正确的方法 operator<< 至 Object 是将其定义为全局函数(使用 Object 接口)或作为 friend 内部功能(使用 private 功能来自 Object),而不是某些辅助类。另见Herb Sutter的旧GotW专栏 “课堂上有什么?”


9
2018-01-17 20:07





iffy的事情是声明一个静态(朋友)运算符 另一个 类(不相关)。

  1. 你可以在周围的范围内创建它

    • 在语义上没有区别
    • 没有理由把它当成朋友(如 Printer 是不是以任何方式使用)
    • 如果你需要,你仍然可以成为朋友

    住在科利鲁

  2. 或者, 使 另一堂课 有关;

    将命名空间(第3.4.2节)与函数查找类型相关联的方法有很多种。例如,这个黑客将被认为是关联的 Print class命名空间 Object 类型所以ADL仍然有效:

    template <typename> struct Object_ {};
    typedef Object_<class Print> Object;
    

    看到这个 住在科利鲁 同样


4
2018-01-17 20:08



或者,关联 Print 用你的类命名空间 Object 类型所以ADL仍然有效: 住在科利鲁 - sehe
#2 hack是如何工作的? - 0x499602D2
@ 0x499602D2 ADL在与参数类型关联的所有名称空间中查找不合格的自由函数。 “关联命名空间”包括声明模板参数类型的命名空间。 - sehe
那么编译器会查看模板参数的关联名称空间吗?哇,刚学到新东西! - 0x499602D2
让我们 在聊天中继续讨论。 - sehe