CRTP和默认赋值运算符

3
在接下来的内容中:
template<typename Derived>
class Base:
{
    inline Derived& operator=(const Base<Derived>& x);
}

这个声明是否会删除默认的复制赋值操作符,还是说我将拥有两个操作符:

inline Derived& operator=(const Base<Derived>& x); 
// (declared by me)

AND

inline Base<Derived>& operator=(const Base<Derived>& x); 
// (declared by the compiler)

在这种情况下,当我调用函数时,编译器如何获取正确的运算符?
2个回答

3
如果您声明了可以通过赋值运算符的任何方法:
XXX Foo::operator=(Foo&);
XXX Foo::operator=(Foo const&);
XXX Foo::operator=(Foo volatile&);
XXX Foo::operator=(Foo const volatile&);

如果这样做,编译器就不会生成默认版本的Foo& operator=(Foo const&);
请注意,返回类型完全自由,就像其他方法一样。您可以使用voidbool或任何其他类型。只是为了允许赋值链式调用,通常(但不是必须)返回一个对自身的引用: a = b = c = 0; 这源于重载运算符应该遵循其内置对应项语义的指导方针。

1

你试过了吗?仅按返回类型进行重载将导致编译错误,因此我的猜测是定义的那个替换了默认的那个。


只有在模板实例化于代码中时,才会出现编译器错误。否则,它将可以很好地编译。 - SomeWittyUsername
@icepack 这是正确的,我假设模板已经实例化了。 - Karthik T
1
@icepack 这不是真的。如果一个模板无论你传递什么模板参数都是格式错误的,那么这个模板也可以在实例化之前被拒绝。如果默认赋值运算符也会被实例化,那么这也适用于他的类模板。 - Johannes Schaub - litb
@JohannesSchaub-litb 很好的观点。然而,这是特定于编译器的,不是吗?编译器能够这样做,并不意味着它会这样做。就生成的二进制代码而言,它是可以的。 - SomeWittyUsername
@icepack 对的,它基本上就是未定义行为。即 https://dev59.com/fGbWa4cB1Zd3GeqPWF9Q - Johannes Schaub - litb
@JohannesSchaub-litb:你对验证过的答案满意吗?还是你认为提供的代码存在未定义行为? - Vincent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接