隐藏的朋友:声明和定义

时间:2019-06-27 16:57:47

标签: c++ friend argument-dependent-lookup

安东尼·威廉姆斯(Anthony Williams)在最近的blog post中谈到了隐藏的朋友。如果我正确理解的话,主要思想是在某些情况下ADL无法找到声明为好友的函数。简单的例子:

namespace N {
    struct A {
        friend void foo(A) { }
    };

    struct B {
        operator A();
    };

    // (*)
    void bar(A) { }
}

void func() {
    N::A a;
    bar(a);   // OK, bar is found via ADL
    foo(a);   // OK, foo is found via ADL

    N::B b;
    bar(b);   // OK, bar is found via ADL
    foo(b);   // NOT OK, foo cannot be found
}

在博客文章的所有示例中,friend函数都是在类内部定义的。是否可以声明一个朋友功能,然后在以后的(*)点对其进行定义,以使其保持隐藏?看来隐藏的朋友只能在类范围(或在另一个编译单元)中定义。

2 个答案:

答案 0 :(得分:1)

隐藏的朋友需要完全内联定义,即在class定义内部。是的,如果您在其他地方定义朋友(在定义可以导致名称空间可见性的地方),它将打破仅基于ADL搜索才能发现基于隐藏朋友的限制,因此可以解决重载。

WG21 recommendations中的其他内容用于指定隐藏的朋友, 注意,隐藏的朋友是完全内联定义的,例如以下代码段:

#include <ostream>
#include <compare>
class C  {
    friend ostream& operator << ( ostream&, C const& )  {}
    friend auto   operator <=>( C const&, C const& )  = default;
};

答案 1 :(得分:0)

隐藏的朋友可以定义,但是在那个TU中它们不是隐藏的。作为示例,请考虑以下标头:

class A {
    // this is hidden friend defined inline
    friend int operator+(A, int) { return 0; }
    // this is hidden friend defined out of line
    friend int operator+(int, A);
    // not a hidden friend (see below)
    friend int operator+(A, A);
};
int operator+(A, A); // this is no longer hidden friend in any TU

,然后是单独的cpp文件:

#include "a.hpp"

// This is not a hidden friend in this TU, but is in other TUs.
int A::operator+(int, A) {
    return 2;
}

当您具有依赖于其他大型标头实现的操作员/ ADL自定义点时,这样做非常有用。