3

C++ 有一个特性,即类内定义的友元函数只能通过 ADL(参数相关查找)找到:

struct Foo {
    friend void fn(Foo) { } // fn can only be called by ADL, it won't be found by other lookup methods
};

非朋友功能是否可以实现相同的功能?我问这个,因为有时,我想拥有这个“仅由 ADL 发现”的功能,但我实际上并不需要朋友访问课程内部。

(还有一个有点自以为是的问题:如果这不可能,这是什么原因?这个“只有 ADL 发现”规则是故意设计到语言中的吗?)

4

2 回答 2

5

只有友元函数才有可能,因为它们是唯一存在这种说法的函数。使函数对普通名称查找不可见的措辞以及在 ADL 期间考虑它们的措辞都仅适用于此类朋友。

引入此功能实际上是为了替换另一个被认为更成问题的功能。N0777是详细说明它的论文。模板用于在模板实例化时将其友元函数名称注入范围,以便通过常规名称查找找到。这并不理想,并导致过载解决问题。

该功能被设置为删除,但它是Barton-Nackman 技巧的支柱,因此提出了一个解决方案,最终成为我们所知的仅由 ADL 查找的内联友元函数。它是为方便编程习惯而量身定制的。

由于此后没有提出需要这种行为的其他广泛传播的习语,因此这种行为没有扩展到非朋友功能。

于 2020-02-20T10:15:51.420 回答
2

引入了参数相关查找,用于所有函数的非限定名称查找,而不仅仅是类的友元函数。

这是一个演示程序

#include <iostream>

namespace N1
{

struct A
{
    int a = 10;
    friend void f( A &a ) { std::cout << "friend f( A & ) : A::a = " <<  a.a << '\n'; }     
};

void f( const A &a ) { std::cout << "f( const A & ) : A::a = " <<  a.a << '\n'; }   

}            

int main()
{
    N1::A a1;
    f( a1 );

    const N1::A a2;
    f( a2 );

    N1::f( a1 );
}    

程序输出为

friend f( A & ) : A::a = 10
f( const A & ) : A::a = 10
f( const A & ) : A::a = 10

在这个程序中,当限定名称查找用于以名称 f 和非常量对象 a1 作为其参数的函数时,称为非友元函数 f,因为友元函数 f 的名称在其所在的命名空间中是不可见的。引入声明。

友元函数包含在 ADL 中,因为如果友元函数仅在类中声明(并相应地定义),则其名称在与在命名空间中声明的函数相反的位置引入声明的命名空间中是不可见的。因此,例如非友元函数可以使用限定名称调用,而仅在类中声明的友元函数不能使用限定名称调用,因为它们是不可见的。

要使用非友元函数实现相同的操作,您必须首先使它们在引入它们的声明的命名空间中不可见,并且限定名称查找不应找到它们。如果不在 C++ 标准中引入一些新概念,这是不可能的。

于 2020-02-20T10:26:42.630 回答