我正在尝试在使用 CRTP 的派生类的基类中实现移动/复制赋值运算符和构造函数。
template <typename Derived>
class base {
public:
Derived& operator= (const Derived& other) {
// Copy the base properties:
this->foo_ = other.foo_;
// ...
// Continue as the derived class demands it:
this->derived().copy(other);
return this->derived();
}
// etc. for copy/move assignment/construction...
private:
// To act as the derived class:
Derived& derived () { return *static_cast<Derived*>(this); }
const Derived& derived () const { return *static_cast<const Derived*>(this); }
protected:
// Some base properties:
int foo_;
// ...
};
class derived: public base<derived> {
friend base<derived>;
public:
// Inheriting the constructors and assignment operators:
using base<derived>::base;
using base<derived>::operator=;
private:
void copy (const derived& other) {
// Copy all the needed derived properties:
this->bar_ = other.bar_;
// ...
}
// Some derived properties:
int bar_;
// ...
};
// To test it:
int main () {
derived d, t;
d = t;
}
编译器给我一个错误,说derived& derived::operator=(const derived&)
不能用derived& base<derived>::operator=(const derived&)
. 我的理论是,它以某种方式derived::operator=
被隐式定义,然后通过声明引入base<derived>::operator=
我using
试图重新定义它可能吗?这看起来与意外定义方法两次时出现的错误非常相似。
我用 GCC 编译了这个,完整的日志是:
test.cpp: In function 'int main()':
test.cpp:25:7: error: 'constexpr derived& derived::operator=(const derived&)' cannot be overloaded
class derived: public base<derived> {
^~~~~~~
test.cpp:4:14: error: with 'Derived& base<Derived>::operator=(const Derived&) [with Derived = derived]'
Derived& operator= (const Derived& other) {
^~~~~~~~
这甚至可以实现,还是我必须在derived
类中定义运算符/构造函数,然后将它们的功能委托给base
定义中的类?
更新
好吧,也许在用更清晰的头脑看这个之后,它似乎过于复杂。我可以做到以下几点:
Derived& base<Derived>::operator= (const base& other) {
this->foo_ = other.foo_;
return this->self();
}
所以返回的类型对于每个派生类都是正确的,并且复制是从基类执行的——只复制基本属性,这是我默认需要的。如果我需要更多,那么它特定于每个派生类:
// Adding this to the base class - for any derived class to act as the base one:
template <Derived>
base<Derived>& base<Derived>::base () { *return static_cast<base<Derived>*>(this); }
derived& derived::operator= (const derived& other) {
this->base() = other.base();
this->bar_ = other.bar_;
}
但是,这是一个有趣的练习,关于编译器错误的问题仍未得到解答。