我有一个类,它在类中声明和定义了一个友元函数,我从类中的另一个函数调用这个函数.Clang编译器(3.3)抱怨友元函数的未声明标识符.我用MSVC和gcc编译了这个代码,它适用于两个编译器,但现在使用Clang端口我遇到了这个问题.以下是该问题的简化示例:
class foo
{
friend void bar() {}
void asd() {bar();}
};
Run Code Online (Sandbox Code Playgroud)
在Clang我得到:error : use of undeclared identifier 'bar'.如果我在类之外声明/定义pla(),它工作正常,但我有一些宏迫使我在类中定义函数.这是Clang中的一些已知问题,还是Clang对C++名称查找更加迂腐,同时仍符合C++标准?在定义/声明类中的函数时,是否有一些已知的解决方法?
相关规则可在§7.3.1.2[namespace.memdef]/p3中找到:
首先在名称空间中声明的每个名称都是该名称空间的成员.如果非本地类中的友元声明首先声明一个类或函数,那么友元类或函数是最内层封闭命名空间的成员.在非命名查找(3.4.1)或限定查找(3.4.3)之前找不到朋友的名称,直到在该命名空间范围内提供匹配声明(在授予友谊的类定义之前或之后).如果调用了友元函数,则可以通过名称查找找到其名称,该名称查找考虑名称空间中的函数和与函数参数类型相关联的类(3.4.2).
换句话说,当一个friend函数只在一个类内部定义并且从不在它之外声明时,它唯一可以找到的方法是通过ADL,这里不适用于不bar()带参数的ADL .在通过非ADL名称查找找到函数之前,必须在最里面的封闭命名空间中存在该函数的匹配声明.