请考虑以下示例:
template <typename T>
class C
{
public:
friend void f() {}
friend void f(C<T>) {}
};
C<int> c;
void g(C<int>* p)
{
f();
f(*p);
}
使用GCC 5.2进行编译会引发以下编译错误:
no matching function for call to 'f()'
但标准在14.6.5中说:
可以在类模板中声明好友类或函数 . 实例化模板时,会将其朋友的名称视为在实例化时明确声明了特化 .
为什么这不能编译?在GCC 3.4中,它通过了 .
2 回答
f
只能通过参数依赖名称查找(ADL)找到 . 第二个调用编译,因为作为参数传递的p
的指针是C<int>
类型 - 这会导致ADL跳入并检查其他不可见的函数 . 实际上,根本无法找到f
的第一个重载,因为没有办法将关联传递给C
的任何特化 .只需看看你的报价,[temp.inject]/2:
对
f()
的调用与类C
无关,因此它的朋友不会在重载决策中使用 .在另一个调用
f(*p)
中,参数是类类型,因此检查类的类和命名空间以查找可能的候选项 . 这样编译器将找到f
函数并使用重载决策来选择合适的函数 .