友元函数访问友元类的私有成员

9

跟随2019年在特拉维夫举办的欧洲歌唱大赛中捷克的歌曲

众所周知,在C ++中,朋友的朋友不是(自动)朋友。

然而,Clang在以下代码上与GCC和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
        }
    };
};

代码: https://godbolt.org/z/rn48PTe1Y

哪一个是正确的? 如果Clang过于宽松,那么允许访问的最佳方法是什么(除了提供公共getter之外)?


注意:如果友元函数只是在类中声明并在外部实现,则Clang和GCC都会拒绝该代码


clang是错误的,因为它允许operator!=()(不是Inner1的友元)访问Inner1的私有成员。一种正确提供访问权限的方法(不依赖于所有编译器都像clang一样存在缺陷)是将operator!=()作为Inner2的成员而不是friend - 因为Inner2已经是一个friend,它的成员将正确地访问Inner1实例的成员。 - Peter
1个回答

6

看起来这是clang的已知缺陷,错误编号#11515,早在2011年就已经报告,但显然尚未修复。

甚至还有一个更简单的例子可以编译却不应该(来自上面的错误报告):

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接