我有一个在类中定义了友元函数的程序,它使用 gcc 和 clang 进行编译,但被 msvc 拒绝。
#include <iostream>
template<typename T>
class Outer
{
struct Inner;
friend void foo();
};
template<typename T>
struct Outer<T>::Inner
{
friend void bar(Inner)
{
//gcc and clang accepts but msvc rejects this
typename Outer<int>::Inner k;
std::cout << "bar called";
}
};
void foo()
{
std::cout << "foo called";
Outer<int>::Inner i;
bar(i);
}
int main()
{
Outer<int> outer;
foo();
}
按照标准,这里的编译器是哪个?
MSVC 说:
<source>(14): error C2248: 'Outer<int>::Inner': cannot access private struct declared in class 'Outer<int>'
<source>(5): note: see declaration of 'Outer<int>::Inner'
<source>(14): note: see declaration of 'Outer<int>'
<source>(14): note: the template instantiation context (the oldest one first) is
<source>(17): note: see reference to class template instantiation 'Outer<T>::Inner' being compiled
<source>(14): note: see reference to class template instantiation 'Outer<int>::Inner' being compiled
<source>(12): note: while compiling class template member function 'void bar(Outer<int>::Inner)'
<source>(22): note: see the first reference to 'bar' in 'foo'
Compiler returned: 2
Gcc 和 Clang 在接受程序时是错误的,因为嵌套类中定义的友元函数对封闭类的成员没有特殊的访问权限。这一点从class.nest可以看出:
与成员函数一样,嵌套类中定义的友元函数 ([class.friend]) 位于该类的词法范围内;它遵循与该类的静态成员函数 ([class.static]) 相同的名称绑定规则,但是 它对封闭类的成员没有特殊的访问权限。
换句话说,
bar
无法访问Inner
的私有字段Outer<T>
,因此程序是格式错误。