Search code examples
c++gccvisual-c++language-lawyer

GCC can access private members of outer class from friend function, MSVC cannot?


This builds in GCC, but not MSVC. It seems that GCC can access private members of outer class from a friend function in a nested class, but MSVC cannot. Why is this?

template <typename T>
class Outer
{
public:
  struct Inner {
    friend bool operator==(const Inner& a, const Inner& b) {
      return a.outer_.private_member_ == b.outer_.private_member_;
    }
    // Both compilers are happy this if uncommented
//    bool operator==(const Inner& other) {
//      return outer_.private_member_ == other.outer_.private_member_;
//    }
   private:
    Outer<T>& outer_;
  };
  friend struct Iterator;

  private:
  int private_member_;
};

bool test(Outer<int>::Inner A, Outer<int>::Inner B)
{
    return A == B;
}

Demo


Solution

  • The program is ill-formed as per class.nest#4 which states:

    Like a member function, a friend function ([class.friend]) defined within a nested class is in the lexical scope of that class; it obeys the same rules for name binding as a static member function of that class ([class.static]), but it has no special access rights to members of an enclosing class.

    (emphasis mine)

    This means that the overloaded operator== in your example is not allowed to access the private data member named private_member_ of the enclosing class Outer<T>.


    To make this well-formed you can make operator==(const Inner&, const Inner&) a friend of Outer<T>. Demo

    Here is the gcc bug:

    GCC accepts private member access of enclosing class through friend function of inner class