简体   繁体   English

隐藏的朋友:声明和定义

[英]Hidden friends: declarations and definitions

In his recent blog post Anthony Williams talks about hidden friends.在他最近的博客文章中,安东尼威廉姆斯谈到了隐藏的朋友。 The main idea, if I understood it correctly, is that functions declared as friends cannot be found by ADL in certain situations.如果我理解正确的话,主要思想是在某些情况下 ADL 无法找到声明为友元的函数。 Simple example:简单的例子:

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
}

In all examples in the blog post, the friend functions are defined inside classes.在博客文章中的所有示例中,友元函数都是在类中定义的。 Is it possible to declare a friend function and then define it later at the point (*) , so that it remains hidden?是否可以声明一个友元函数,然后稍后在(*)点定义它,使其保持隐藏状态? It looks like hidden friends can only be defined in the class scope (or in another compilation unit).看起来隐藏的朋友只能在类范围内(或在另一个编译单元中)定义。

Hidden friends need to be fully defined inline, ie, inside of the definition of class.隐藏的朋友需要完全内联定义,即在类定义的内部。 Yes, if you define friends somewhere else, where definition can cause namespace visibility, it would break restrictions based on hidden friends to be found as match by ADL search only, and as such be candidate for overload resolution.是的,如果您在其他地方定义友元,其中定义会导致命名空间可见性,它会打破基于隐藏友元的限制,仅通过 ADL 搜索才能找到匹配项,因此成为重载解析的候选者。

Further more in WG21 recommendations for specifying hidden friends, is noted that hidden friends are fully defined inline, like in this snippet:WG21指定隐藏好友的更多建议中,注意到隐藏好友是完全内联定义的,就像在这个片段中一样:

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

Hidden friends can be defined out of line, but then they are not hidden in that TU.隐藏的朋友可以被定义为不合时宜,但他们不会隐藏在那个 TU 中。 As an example, consider this header:例如,请考虑以下标头:

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

and then a separate cpp file:然后是一个单独的 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;
}

Doing this is useful when you have operators/ADL customization points that depend on other large headers for their implementation.当您的操作符/ADL 自定义点依赖于其他大型头文件的实现时,这样做很有用。

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

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