是否可以有一个只能通过 ADL 找到的非友元函数?

Is it possible to have a non-friend function which can only be found by ADL?

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

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

是否可以为非友元函数实现相同的功能?我问这个,因为有时候,我想要这个 "only found by ADL" 功能,但我实际上不需要朋友访问 class 内部。

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

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

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

该功能被设置为被删除,但它是 Barton-Nackman trick 的 backbone,因此提出了一个解决方案,最终成为我们所知道的内联友元函数被查找仅限日常活动。它是为促进编程惯用语而量身定制的。

由于没有其他广泛传播的习惯用法需要这种行为,因此这种行为没有扩展到非友元函数。

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

这是一个演示程序

#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 中,因为如果友元函数仅在 class 中声明(并相应定义),其名称在名称空间中是不可见的,在该名称空间中引入的声明与声明的函数相反名称空间。因此,例如非友元函数可以使用限定名称调用,而仅在 classes 中声明的友元函数不能使用限定名称调用,因为它们是不可见的。

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