【问题标题】:Hidden friends: declarations and definitions隐藏的朋友:声明和定义
【发布时间】:2019-06-27 16:57:47
【问题描述】:

在他最近的blog postAnthony Williams 中谈到了隐藏的朋友。如果我理解正确的话,主要思想是在某些情况下,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
}

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

【问题讨论】:

  • 如你所说。它们必须在类范围内或在另一个编译单元中,因此您可以将它们放在源文件中,但是在该源文件中您无法享受隐藏朋友功能的好处,只有其他源文件可以。这就是为什么总是内联更好。整个技巧围绕着唯一可用的声明是在类范围内的声明,外部定义将是在类范围之外破坏效果的第二个声明。
  • 如果你想隐藏一个隐藏朋友的实现,那么只需将它转发给一个私有成员函数,然后将那个实现放在你想要的任何地方。

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


【解决方案1】:

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

WG21 recommendations 中的更多内容用于指定隐藏的朋友, 注意到隐藏的朋友是完全内联定义的,就像在这个 sn-p 中一样:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-02
      • 1970-01-01
      • 2011-02-04
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多