Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

friend transitive to nested classes?

6 views
Skip to first unread message

Ulrich Eckhardt

unread,
Jul 23, 2009, 6:06:06 PM7/23/09
to
Hi!

I have a problem where I'm not sure whether it is my code or one of my
compilers. The design involves two classes, one of which is registered
inside the other, so in the destructor it has to unregister. Further, that
class is just a handle to a ref-counted body, so it is actually the body
that has to unregister when destroyed.

Now, unregistering is a private function, so the handle has to be a friend
in order to access that function. However, different compilers disagree
whether the nested body class also has access to the private function.

I have boiled the code down to these lines here.

class X;
class Y {
friend class X;
static void private_function();
};
class X {
class nested {
nested() {
Y::private_function();
}
};
};


Currently, I have the following opinions:

GCC 4.2 for x86 - okay
MSVC8 for x86 - okay
MSVC8 for ARM - not okay
MSVC8 for MIPS - not okay


So, where is the bug?

Thanks!

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Francis Glassborow

unread,
Jul 23, 2009, 9:58:56 PM7/23/09
to

It depends whether your compiler implements C++98 or C++03. As of the
later date a nested class is a full member of the enclosing class and so
has full access rights to the private parts of the enclosing class. The
problem you touch on is one of the reasons for the change. Friendship is
NOT transitive but member access is.

--

Alf P. Steinbach

unread,
Jul 24, 2009, 6:55:45 PM7/24/09
to
* Ulrich Eckhardt:

>
> I have boiled the code down to these lines here.
>
> class X;
> class Y {
> friend class X;
> static void private_function();
> };
> class X {
> class nested {
> nested() {
> Y::private_function();
> }
> };
> };

To my utter surprise this compiled with Comeau Online, which indicates that it's
formally correct (I never thought of C++ friendship working in this way).


> Currently, I have the following opinions:
>
> GCC 4.2 for x86 - okay
> MSVC8 for x86 - okay
> MSVC8 for ARM - not okay
> MSVC8 for MIPS - not okay
>
>
> So, where is the bug?

Apparently with MSVC8.

A practical solution is to let X::nested::nested call X::private_function which
then forwards to Y::private_function.


Cheers & hth.,

- Alf

--

litb

unread,
Jul 25, 2009, 2:06:13 PM7/25/09
to
On 25 Jul., 00:55, "Alf P. Steinbach" <al...@start.no> wrote:
> * Ulrich Eckhardt:
>
> > I have boiled the code down to these lines here.
>
> > class X;
> > class Y {
> > friend class X;
> > static void private_function();
> > };
> > class X {
> > class nested {
> > nested() {
> > Y::private_function();
> > }
> > };
> > };
>
> To my utter surprise this compiled with Comeau Online, which indicates that it's
> formally correct (I never thought of C++ friendship working in this way).
>
In C++03, that code really is formally incorrect, but rules were added
in resolving defect reports that make the above code valid. Comeau
apparently includes those resolutions. In C++03, the following fairly
explicitly marks the above ill-formed

11.4/2: [...]. However, the declarations of members of classes nested
within the friend class cannot access the names of private and
protected members from the class granting friendship. [...]

In the current draft, the whole paragraph reads as

11.4/2: Declaring a class to be a friend implies that the names of
private and protected members from the class granting friendship can
be accessed in the base-specifiers and member declarations of the
befriended class.

Greg Herlihy

unread,
Jul 25, 2009, 2:07:06 PM7/25/09
to
On Jul 24, 3:55 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * Ulrich Eckhardt:
>
> > class X;
> > class Y {
> > friend class X;
> > static void private_function();
> > };
> > class X {
> > class nested {
> > nested() {
> > Y::private_function();
> > }
> > };
> > };
>
> To my utter surprise this compiled with Comeau Online, which indicates that it's
> formally correct (I never thought of C++ friendship working in this way).

It doesn't - at least not in C++2003.

> > So, where is the bug?
>
> Apparently with MSVC8.

No. The change that grants nested classes access to the enclosing
class's friends never made it into the 2003 C++ Standard (although it
is present in the current C++ draft). Therefore, according to the
current C++ Standard:

"The members of a nested class have no special access to members of an
enclosing class, nor to classes or functions that have granted
friendship to an enclosing class; the usual access rules shall be
obeyed." [�11.8/1]

So the "nested" class should not have access to Y::private_function().

Greg

Francis Glassborow

unread,
Jul 26, 2009, 4:05:41 PM7/26/09
to

I am absolutely certain we changed that as the Standard also prohibits
an outer class from granting friendship to an inner class. That was
clearly a defect and the response was to grant nested classes full
membership rights.

0 new messages