以下包含好友声明的代码失败并显示错误(请参阅http://ideone.com/Kq5dy):
template<class T> void foo() {}
template<typename T>
class A {
void foo();
friend void foo<T>(); // error: variable or field 'foo' declared void
};
int main()
{
foo<int>();
}
如果朋友声明和成员函数声明的顺序颠倒了,那么代码编译没有问题(参见http://ideone.com/y3hiK):
template<class T> void foo() {}
template<typename T>
class A {
friend void foo<T>();
void foo();
};
int main()
{
foo<int>();
}
如果朋友声明不包含模板专业化,则不会发生这种情况:非模板朋友可以,以及模板朋友。在模板专门化中使用限定名称也允许编译代码。 我的问题是为什么第一个例子失败了?似乎编译器在朋友声明点查找类范围中的名称,仅用于模板专业化?标准中的哪个行为被指定了?
答案 0 :(得分:7)
要明确表示它是你想要的那个函数 - friend
在函数名前加上::
来表示它在全局命名空间中。
编译并执行您想要的内容的代码段:
template<class T> void foo() {}
template<typename T>
class A {
void foo();
friend void ::foo<T>();
};
int main()
{
foo<int>();
}
3.4 / 9名称查询
查找朋友函数定义中使用的名称的名称 (11.4)在授予友谊的阶级内联定义应继续作为 描述了在成员函数定义中查找。如果是朋友 函数不是在授予友谊,名称查找的类中定义的 在友元函数定义中,应如查找所述进行 在命名空间成员函数定义中
您的代码段无法编译,原因与下面的代码无法编译的原因相同。
template<class T> void foo () {}
template<typename T>
struct A {
void foo ();
void func () {
foo<T> (); // when performing the name lookup A::foo is
// found before ::foo<T>
}
};
...
14.5.3朋友[temp.friend] 1
类或类模板的朋友可以是函数模板或类模板,是a的特化 函数模板或类模板,或普通(非模板) 功能或类。对于不是的朋友函数声明 模板声明:
- 如果朋友的姓名是合格的或 unquali fi ed template-id,朋友声明指的是a 功能模板的特化,否则
- 如果是的话 friend是quali fi ed-id,找到匹配的非模板函数 在指定的类或命名空间中,友元声明引用 那个功能,否则,
- 如果朋友的名字是quali fi ed-id 并且在。中找到了函数模板的匹配特化 特定的类或命名空间,朋友声明指的是那个 功能模板专业化,否则,
- 名称应为 声明(或重新声明)普通(非模板)的unquali fi ed-id 功能