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

问题描述 投票:0回答:1

在类模板

A
中,
A
的不同实例已成为好友。具体来说,
A<T>
A<T const>
彼此成为朋友(见下文)。这并不意味着
A<T>
的朋友应该能够访问
A<T const>
的私有成员,反之亦然。但显然 gcc 和 clang 接受了这一点

#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
1个回答
0
投票

operator==
移动到类定义之外时,所有三个主要编译器(GCC、CLANG、MSVC)都接受此代码,即使
friend A<InvT>
声明被删除!请参阅https://godbolt.org/z/YP1sKKh1f

#include <type_traits>

template <typename T>  
struct A;
template <typename T, typename InvT>
bool operator==(A<T> const& a, A<InvT> const& b) noexcept {
    return a.value == b.value;
}

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 bool operator==(A<T> const& a, A<InvT> const& b) noexcept;
};


int main() {
  A<int> a;
  A<int const> b;
  (void)(a == b);
}

对于上面的代码,GCC 警告说,

friend operator==
声明实际上是错误的,因为它不是声明模板,而是声明一个自由函数/运算符。更正的是在
<>
之后添加一个空模板规范
operator==
:

  friend bool operator==<>(A<T> const& a, A<InvT> const& b) noexcept;

通过此更新,所有编译器都正确拒绝编译代码,因为禁止访问私有

b.value
https://godbolt.org/z/7j1zGeEs9

© www.soinside.com 2019 - 2024. All rights reserved.