Nested class friend function access works in gcc and clang but not in msvc

98 Views Asked by At

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();
}

Working demo

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
1

There are 1 best solutions below

0
On

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:

Like a member function, a friend function ([class.friend]) defined within a nested class is in the lexical scope of that class; it obeys the same rules for name binding as a static member function of that class ([class.static]), but it has no special access rights to members of an enclosing class.


In other words, bar has no access to the private field Inner of Outer<T> and so the program is ill-formed.