友元函数名在类模板中可见
friend function name visible in class template
考虑以下示例:
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中,它传递。
f
只能通过参数相关的名称查找(ADL)找到。第二个调用会编译,因为作为参数传递的p
的指针是C<int>
类型——这导致ADL跳入并检查其他不可见的函数。事实上,f
的第一个重载根本找不到,因为没有办法将关联传递到C
的任何专门化。
请看你的后面的引语,[temp.inject]/2:
与非模板类一样,类的命名空间作用域友元函数的名称也是模板特化的are 在普通查找期间是不可见的,除非在命名空间作用域(11.3)中显式声明。这样的名字可以在相关类的规则(3.4.2)中找到。<一口> 141 一口>
141) 友元声明不会将新名称引入任何作用域,无论是在声明模板时还是在声明模板时实例化。
对f()
的调用与C
类没有任何关联,因此它的友类不用于重载解析。
在另一个调用f(*p)
中,参数是类类型的,因此要检查类和类的名称空间以寻找可能的候选对象。这样,编译器将找到两个f
函数,并使用重载解析来选择合适的一个。
相关文章:
- C++模板来检查友元函数的存在
- 如何使用单独文件中的派生类访问友元函数对象
- 模板化的类和友元函数
- 友元函数无法访问私有数据成员 (c++)
- 继承和友元函数,从基类访问受保护的成员
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- 在将函数声明为友元时,尖括号的含义是什么?
- 在模板类之外定义友元函数的正确方法是什么?
- 2个模板化类的非模板友元函数未定义引用错误
- C++ 友元函数和私有构造函数
- 使第二个类的构造函数成为第一个类中的友元函数
- 未定义的类模板不会实例化以检查友元函数
- C++类中的友元函数有问题?
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 模板类中的模板友元函数
- C++ 17 个友元函数声明和内联命名空间
- 将派生类的构造函数声明为父类的友元
- 友元函数需要一个帮助程序函数
- 在基/派生类的成员函数/友元函数中派生* 到 Base* 的转换
- 模板类的非模板函数友元