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

Copy assignment operator in CRTP - gcc vs clang and msvc

以下代码(参见)在gcc 8.2编译时会出错,但被clang 7.0.0和msvc 15.9.0 preview 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;
}

错误信息generated by 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= 来自基 class 根本没有被派生中的那个隐藏,就像 foo() 成员函数一样?

这是怎么回事?为什么只有 gcc 抱怨?它应该抱怨吗?

GCC 在这里是错误的:这是 specially called out 没有发生重载的情况。 (当然,如您所说,其他成员函数也不会发生。)