Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does an in-class friend of a nested class have access to outer class members?

clang++, g++, and MSVC disagree on this code:

class A {
private:
    enum class E { NO, YES };
    class B {
    private:
        friend E f1() { return E::YES; }
        // friend E f2();
    };
};

// A::E f2() { return A::E::YES; }

int main() {}

clang++ accepts the code as shown. g++ and MSVC complain in f1 that A::E is inaccessible. If function f2 is uncommented, all three compilers complain at its definition that A::E is inaccessible.

Is f1 in fact valid?

The relevant Standard pieces I found are:

[class.access.nest]:

A nested class is a member and as such has the same access rights as any other member.

Though this alone doesn't mean friends of the nested class have all the same rights as the nested class.

[class.access.base]/5:

The access to a member is affected by the class in which the member is named. This naming class is the class in which the member name was looked up and found. A member m is accessible at the point R when named in class N if

  • m as a member of N is public, or

  • m as a member of N is private, and R occurs in a member or friend of class N, or

  • m as a member of N is protected, and..., or

  • there exists a base class B of N that is accessible at R, and m is accessible at R when named in class B.

So f2 is invalid, because there the naming class for A::E is definitely A, there are no base classes involved, and the definition of f2 is not a member or friend of A and does not "occur in" a member or friend of A.

In f1 the naming class for unqualified E is also A. ([basic.lookup.unqual] says a lookup for the name E in class A::B is done first, but it's not "found" there, so then a lookup in class A is done, and the member is found.) But I guess the big question then is, does the definition of f1 "occur in" a member of A? That member, if so, would have to be class A::B.

like image 785
aschepler Avatar asked Apr 04 '19 14:04

aschepler


People also ask

Can inner classes access outer class members?

Can inner class access members of outer class? Yes, including the ones declared private , just as any instance method can.

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 inner classes access outer class members C++?

So, yes; an object of type Outer::Inner can access the member variable var of an object of type Outer .

Can nested classes access private members in Java?

Not only does the nested class have access to the private fields of the outer class, but the same fields can be accessed by any other class within the package when the nested class is declared public or if it contains public methods or constructors.


1 Answers

I think gcc and msvc are right.

From [class.friend]/1, emphasis mine:

A friend of a class is a function or class that is given permission to use the private and protected member names from the class. A class specifies its friends, if any, by way of friend declarations. Such declarations give special access rights to the friends, but they do not make the nominated friends members of the befriending class.

When you have friend E f1(), that gives f1 permission to use the private and protected names of B, specifically. E is not a private or protected name of B, it's a name that B simply has access too.


This is conceptually similar to [class.friend]/10:

Friendship is neither inherited nor transitive.

Since it would imply that the rule is that f1 can access B's stuff, and B can access A's stuff, therefore f1 can access A's stuff.

like image 197
Barry Avatar answered Sep 19 '22 13:09

Barry