Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Friend access to protected nested class

Tags:

c++

friend

I have the following C++ code:

class A {
 protected:
  struct Nested {
    int x;
  };
};

class B: public A {
  friend class C;
};

class C {
  void m1() {
    B::Nested n; // or A::Nested
  }
};

Compiling this snippet with g++ 4.4, it does not make a difference whether I use B::Nested or A::Nested in m1. Clang accepts B::Nested, but does not compile if I A::Nested. Is that a bug in g++ or in clang?

like image 509
Torsten Marek Avatar asked Aug 27 '10 13:08

Torsten Marek


People also ask

Can nested classes access private members?

A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private.

Is a nested class a friend class?

If the declaration of a nested class is followed by the declaration of a friend class with the same name, the nested class is a friend of the enclosing class.

Can nested classes access private members C#?

A nested type has access to all of the members that are accessible to its containing type. It can access private and protected members of the containing type, including any inherited protected members.

Can member inner classes have static members in them?

Instance variables and methods in the non-static inner class are relative to an instance of the enclosing class, so being related to an object, static won't hold true for them (ie inner class), 4.


2 Answers

According to the Standard, GCC is correct and Clang is wrong. It says at 11.2/4

A member m is accessible when named in class N if

  • m as a member of N is protected, and the reference occurs in a member or friend of class N, or in a member or friend of a class P derived from N, where m as a member of P is private or protected

This is subject of this Clang bugreport, which prevents Clang from building Qt: http://llvm.org/bugs/show_bug.cgi?id=6840 . One Clang guy says

Actually, I intentionally haven't implemented this rule yet. It is either a drafting error or a horrible mistake. It neuters the entire 'protected' specifier, it makes the well-formedness of code dependent on the existence of completely unrelated classes, it imposes high costs on the implementation, and it's formally undecidable in the presence of templates.

like image 93
Johannes Schaub - litb Avatar answered Oct 18 '22 06:10

Johannes Schaub - litb


In C++ friends are not-transitive. Friends of your friends are not necessarily my friends.

By making Nested protected in A, you indicate that all subclasses may use this element, but nobody else is allowed to use it. You could consider this is a kind of friend. A makes all subclasses friend regarding access to the Nested struct.

Now B makes C a friend, but this does not mean that C is also a friend of A. So C should have no access to Nested.

BUT: the behavior is changed from C++03. In C++03, a nested class is a full member of the enclosing class and so has full access rights. Friendship is still NOT transitive, but now member access is.

You may want to look at http://www.rhinocerus.net/forum/language-c-moderated/578874-friend-transitive-nested-classes.html, which explains a similar problem.

like image 38
Patrick Avatar answered Oct 18 '22 06:10

Patrick