A friend function accessing a private member of a friend class
Asked Answered
S

1

9

Following the Czech song from Eurovision 2019 in Tel-Aviv

It is known that in C++ a friend of a friend is not (automatically) a friend.

Clang however differs on the following code with GCC and MSVC:

class A {
public:    
    // forward declaration
    class Inner2;

private:
    class Inner1 {
        char foo;
        friend class Inner2;
    };
public:
    class Inner2 {
        Inner1 i;
    public:
        bool operator==(Inner2 other) {
            return i.foo == other.i.foo; // OK by GCC, Clang and MSVC++
        }
        friend bool operator!=(Inner2 a, Inner2 b) {
            return a.i.foo != b.i.foo; // Clang accepts, GCC and MSVC++ reject
        }
    };
};

Code: https://godbolt.org/z/rn48PTe1Y

Which one is correct? If Clang is wrong by being too permissive, what is the best way to allow access (other than providing a public getter?)


A note: if the friend function is just declared in the class and implemented outside, both Clang and GCC reject the code.

Swashbuckling answered 28/5, 2021 at 15:26 Comment(1)
clang is wrong, since it is allowing operator!=() - which is not a friend of Inner1 to access private members of Inner1. A way to correctly provide access (which doesn't rely on all compilers having a bug like clang does) would be to make the operator!=() a member of Inner2 rather than a friend - since Inner2 is a friend already, its members will correctly have access to members of instances of Inner1.Pola
S
6

It seems to be a known defect in clang, bug id #11515, reported already in 2011, but still not fixed, apparently.

An even simpler example that compiles, and shouldn't (from the bug report above):

class A {
  int n;
  friend struct B;
};

struct B {
  friend int get(A &a) {
    return a.n; // clang accepts, and should reject
  }
};

https://godbolt.org/z/r78Pazoqj

Swashbuckling answered 31/5, 2021 at 12:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.