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 没有发生重载的情况。 (当然,如您所说,其他成员函数也不会发生。)
以下代码(参见
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 没有发生重载的情况。 (当然,如您所说,其他成员函数也不会发生。)