I have a code where class A and B are defined in global namespace. Same thing is repeated in a nested namespace. However in nested namespace when it sees friend declaration of Class B in Class A, it considers it to be global class B with msvc cl compiler whereas with nested::B in gcc.
class A{
friend class B;
protected:
int i;
A(){
i=0;
}
}; //end of class A
class B{
A* create(){
return new A();
}
}; //end of class B
int main() {
B object;
return 0;
}
namespace nested{
// This forward declaration fixed the error.
//class B;
class A{
friend class B;
protected:
int i;
A(){
i=0;
}
}; //end of class A
class B{
A* create(){
return new A();
}
}; //end of class B
int main() {
B object;
return 0;
}
} //end of nested
It compiles fine with gcc-7.2 but gives below errors with Visual-Studio 17.
[ on line - return new A;] error C2248: 'nested::A::A' cannot access protected member declared in class 'nested::A'
[ on line - A() in nested namespace]note: see declaration of 'nested::A::A'
[ on class A in nested namespace]note: see declaration of 'nested::A'
I found the above commented forward declaration fixes the error. Reference
My understanding is in nested namespace in class A, it is considering it to be friend with global class B, as it has not seen nested::B yet. But, when we declare a class as friend, shouldn't it first lookup in local namespace (over another pass of compiler or something).
My question is - is there a c++ standard defined and which is the buggy compiler here (if any). I would like it to work with Visual Studio without or with minimal code changes.
Edit 1: I found some free version of C++ standard on github. Sorry, I got tex files only. Link
\indextext{local class!friend}%
\indextext{friend!local class and}%
If a friend declaration appears in a local class\iref{class.local} and the
name specified is an unqualified name, a prior declaration is looked
up without considering scopes that are outside the innermost enclosing
non-class scope.
For a friend function declaration, if there is no
prior declaration, the program is ill-formed.
For a friend class
declaration, if there is no prior declaration, the class that is
specified belongs to the innermost enclosing non-class scope, but if it is
subsequently referenced, its name is not found by name lookup
until a matching declaration is provided in the innermost enclosing
non-class scope.
\begin{example}
\begin{codeblock}
class X;
void a();
void f() {
class Y;
extern void b();
class A {
friend class X; // OK, but \tcode{X} is a local class, not \tcode{::X}
friend class Y; // OK
friend class Z; // OK, introduces local class \tcode{Z}
friend void a(); // error, \tcode{::a} is not considered
friend void b(); // OK
friend void c(); // error
};
X* px; // OK, but \tcode{::X} is found
Z* pz; // error: no \tcode{Z} is found
}
\end{codeblock}
\end{example}
I am trying to understand the language
a prior declaration is looked up without considering scopes that are outside the innermost enclosing non-class scope.
This feels like msvc cl is doing right thing and my understanding is "look for last declaration" without worrying about scope. But, in code example
friend class X; // OK, but \tcode{X} is a local class, not \tcode{::X}
Doesn't this suggest it refers to a local class and not global class, but since there was no local definition of X, on name lookup it referred to global X. Since in my case, there is a local definition of friend class, that should be referred? Any help would be appreciated.