我有一个在类中定义了一个朋友函数的程序,它用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();
}
字符串
Working demo
根据标准,哪个编译器是正确的?
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
型
1条答案
按热度按时间kmynzznz1#
GCC和Clang在接受程序时是错误的,因为在嵌套类中定义的友元函数对封闭类的成员没有特殊的访问权限。这可以从class.nest中看出:
与成员函数一样,在嵌套类中定义的友元函数([class.friend])也在该类的词法作用域中;它遵守与该类的静态成员函数([class.static])相同的名称绑定规则,但是它对封闭类的成员没有特殊的访问权限。
换句话说,
bar
无法访问Outer<T>
的私有字段Inner
,因此程序是病态的**。