New -ffriend-injection behavior - is it really intended?

David Fang fang@csl.cornell.edu
Fri May 25 09:13:00 GMT 2007


> > The point is, that with the g++ 4.1 interpretation of the standard,
> > f() is not visible in *any* scope:
> >
> > lohmann@faui48a [~]>cat t.cc
> > class C {
> >    friend void f() {}
> >
> >    void g() { f(); }
> > };
> >
> > int main() {
> >    f();
> >   }

> > If g++ 4.1 interprets the standard in the way that f() is in the
> > lexical scope spanned by class C it should be found by g(). If (as
> > older versions did) the standard is interpreted in the way that f() is
> > the scope in which C is defined, it should be found by main(). But
> > neither scope? If this is really correct, it looks like a language
> > defect to me.
>
> Hmmm.  That does look strange.  I would have expected that f would be
> found in C::g, but I agree that gcc does not work that way at present.
> This may be a gcc bug.
>
> I'm confident that it's not a gcc bug that f is not found in main.

The change was documented here:
http://gcc.gnu.org/gcc-4.1/changes.html

Related bug reports contain some discussions: 1016, 16995 [meta]
(ton of invalid dupes too)

> > 4) And finally, do you know the *intention* behind all this? I am
> > trying to imagine a good reason for the g++ 4.1 interpretation, but
> > haven't been able to find one so far. I mean, it is just not a strong
> > point for some interpretation if it obviously does not make sense...
>
> I don't know.
>
> I recommend asking on a C++ language mailing list.

<opinion>
Name injection was always hideous and created really confusing situations
where a friend declaration was deep inside a nested class.  Unless you
*like* having to look things up in the standard, some answers just weren't
obvious (to me at least).  Consider:
	class A {
	class B {
	friend class C; // where does this go? A::C or ::C?
	};
	};
It also implied that parsing a class had *side-effects* (evil) to the
enclosing namespace.  (Such non-modularity could've impeded pre-compiled
class headers, or other syntax tree shortcuts.)  This also meant you
couldn't necessarily speed read over a class definition without looking at
its friends.

The best policy is to always forward declare the prototype/class that you
would normally expect to inject.

I'm all for comprehensibility and less ambiguity.
Good riddance to friend-injection!
(but thank goodness for backwards compatibility switches)
</opinion>


Fang



More information about the Gcc-help mailing list