CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc

Copy assignment operator in CRTP - gcc vs clang and msvc

本文关键字:vs clang msvc gcc 复制 赋值运算符 CRTP      更新时间:2023-10-16

以下代码(请参阅此问题(在由 gcc 8.2 编译时会导致错误,但被 clang 7.0.0 和 msvc 15.9.0 预览版 3 接受:

template<typename T>
struct B
{
void operator=(const T&) { }
void foo() { }
};
struct D : public B<D>
{
using B<D>::operator=;
using B<D>::foo;       // hidden by D::foo
void foo() { }
};
int main()
{
D d1, d2;
d1 = d2;
d1.foo();
return 0;
}

gcc 生成的错误消息是:

<source>: In function 'int main()':
<source>:8:8: error: 'constexpr D& D::operator=(const D&)' cannot be overloaded with 'void B<T>::operator=(const T&) [with T = D]'
struct D : public B<D>
^
<source>:4:8: note: previous declaration 'void B<T>::operator=(const T&) [with T = D]'
void operator=(const T&) { }
^~~~~~~~

我们在D中有两个赋值运算符,第一个是默认生成的,第二个是用using引入的。它们具有相同的签名,因此重载失败。但是,为什么基类中的operator=根本不像foo()成员函数那样被派生类中的基类隐藏呢?

这是怎么回事?为什么只有海湾合作委员会抱怨?它应该抱怨吗?

GCC 在这里是错误的:这被特别称为没有发生过载的情况。 (当然,正如您所说,其他成员功能也不会发生这种情况。