gcc 和 clang 接受好友函数访问好友类的私人成员是错误的吗?

Are gcc and clang wrong to accept a friend function accessing a befriended class's private members?

提问人:bitmask 提问时间:9/7/2023 更新时间:9/8/2023 访问量:67

问:

在类模板中,另一个实例是 的好友。具体来说,彼此交朋友(见下文)。这不应该意味着朋友应该能够访问私人成员,反之亦然。但显然 gcc 和 clang 接受了这一点AAA<T>A<T const>A<T>A<T const>

#include <type_traits>

template <typename T>  
struct A { 
 private:
  T value{};

 public:
  using InvT = std::conditional_t<std::is_const_v<T>, std::remove_const_t<T>, std::add_const_t<T>>;
  friend A<InvT>;

  friend bool operator==(A const& a, A<InvT> const& b) noexcept {
    return a.value == b.value;
    //                  ^^^^^ private. should not be accessible
  }
};

他们接受这一点是错误的吗?

C++ GCC Clang Friend

评论

0赞 Alan Birtles 9/7/2023
我相当确定你是对的,clang 和 gcc 在这里是错误的,朋友不是传递的,所以不应该影响运算符的友好性friend A<InvT>A<InvT>
1赞 Alan Birtles 9/7/2023
如果您只想修复错误,那么使用成员运算符可以工作: godbolt.org/z/WYWjMG6hr

答:

3赞 Brian Bi 9/8/2023 #1

CWG 1699:如果一个友元函数在类定义中按词法定义,那么该友元是否可以访问该类有权访问的所有内容?Clang 和 GCC 目前认为答案是“是”。MSVC 认为答案是否定的。所有实现都同意,当友元函数的定义在类之外时,函数的主体不会自动访问该类有权访问的所有名称。

在您的示例中,因为 in 是在 的定义中定义的,所以 friend 函数可以访问所有有权访问的内容,其中包括所有 的私有成员,因为 已声明为其朋友。operator==A<const int>A<const int>A<int>A<int>A<const int>

如果将 的友元声明转换为正向声明,并且其定义是行外提供的,则所有三个编译器都会拒绝该代码,因为友元是不可传递的。operator==operator==

如果保留了内联友元定义,但删除了声明,则 Clang 会拒绝代码,但 GCC 会继续接受它。这可能是 GCC 中的一个错误。friend A<InvT>;