I just ran into an unexpected compiler diagnostic involving friend classes. Turns out that both the Gnu compiler and the Comeau compiler also generate diagnostics. Does anyone want to give a stab at understanding why this code should be illegal, and what the workaround would be other than to make the constructor and destructor public. (In my case, the nested classes are internal use only except for a few public methods exposed to the clients.)
Thanks,
Brian
class
X{
class A // first nested class
{
friend class B;
private:
A() { }
~A() { }
}; class B // second nested class
{
public:
B()
{
a = new A(); // can't access private member X::A::A
}
~B()
{
}
private:
A* a;
};
}; // class X

C++ Standard issue on nested friend classes
MSTony
Here is the answer: this is 3.3/8 in the C++ Standard:
[ Note: friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace (7.3.1.2). Function declarations at block scope and object declarations with the extern specifier at block scope refer to delarations that are members of an enclosing namespace, but they do not introduce new names into that scope. —end note ]
The workaround, as you have already discovered, is to forward declaration the class being befriened before it is made a friend.
DrFlick
a workaround would be doing a forward declaration of class B before class A, like:
class X
{
class B;
class A // first nested class
{
friend class B;
private:
A() { }
~A() { }
};
class B // second nested class
{
public:
B()
{
a = new A();
}
~B()
{
delete a;
}
private:
A* a;
};
};
Why it is needed, I didn't figure that part yet. Supposedly the "friend class B;" would do the forward declaration itself.
Sergey Averchenkov
Thanks.
I am using the workaround you suggest and can go back to hiding the state-heavy constructor from the client. You're right, it's curious a forward declaration was needed to make this work. I think it has to do with the fact that friend class B refers to B at global scope, so a forward declaration of B within the scope of X informs the compiler that B is nested in X.
I tried friend class X::B (within X), but X is not defined (because it is being defined).
Brian