提问人:bitmask 提问时间:9/7/2023 更新时间:9/8/2023 访问量:67
gcc 和 clang 接受好友函数访问好友类的私人成员是错误的吗?
Are gcc and clang wrong to accept a friend function accessing a befriended class's private members?
问:
在类模板中,另一个实例是 的好友。具体来说,彼此交朋友(见下文)。这不应该意味着朋友应该能够访问私人成员,反之亦然。但显然 gcc 和 clang 接受了这一点。A
A
A<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
}
};
他们接受这一点是错误的吗?
答:
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>;
评论
friend A<InvT>
A<InvT>