CRTP中的复制分配运算符-GCC与Clang和MSVC

时间:2018-10-14 17:07:26

标签: c++ using crtp

以下代码(请参见this question)在由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;
}

错误消息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=成员函数中的基类中的foo()根本不会被派生类中的那个隐藏呢?

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

1 个答案:

答案 0 :(得分:1)

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