繁体   English   中英

隐藏的朋友:声明和定义

[英]Hidden friends: declarations and definitions

在他最近的博客文章中,安东尼威廉姆斯谈到了隐藏的朋友。 如果我理解正确的话,主要思想是在某些情况下 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
}

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

隐藏的朋友需要完全内联定义,即在类定义的内部。 是的,如果您在其他地方定义友元,其中定义会导致命名空间可见性,它会打破基于隐藏友元的限制,仅通过 ADL 搜索才能找到匹配项,因此成为重载解析的候选者。

WG21指定隐藏好友的更多建议中,注意到隐藏好友是完全内联定义的,就像在这个片段中一样:

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

隐藏的朋友可以被定义为不合时宜,但他们不会隐藏在那个 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 自定义点依赖于其他大型头文件的实现时,这样做很有用。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM