I have this program with a friend function defined inside the class, that compiles with gcc and clang but is rejected by 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();
}
Which compiler is right here according to the standard?
MSVC says:
<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 and Clang are wrong in accepting the program because a friend function defined within a nested class has no special access rights to members of the enclosing class. This can be seen from class.nest:
In other words,
bar
has no access to the private fieldInner
ofOuter<T>
and so the program is ill-formed.