CRTP & copy/move assignment/constructor 继承
CRTP & copy/move assignment/constructor inheritance
我正在尝试使用 CRTP 在派生的 classes 的基础 class 中实现 move/copy 赋值运算符和构造函数。
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=
被隐式定义,然后通过 using
声明引入 base<derived>::operator=
我可能会再次尝试重新定义它?这看起来与意外定义方法两次时出现的错误非常相似。
我用 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
class 中定义 operators/constructors 然后将它们的功能委托给 base
class里面的定义?
更新
OK,可能是看清楚了,还是觉得太复杂了。我可以执行以下操作:
Derived& base<Derived>::operator= (const base& other) {
this->foo_ = other.foo_;
return this->self();
}
因此返回的类型对于每个派生 class 都是正确的,并且复制是从基础 class 执行的 - 仅复制基础属性,这是我默认需要的。如果我需要更多,那么它特定于每个派生 class:
// 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_;
}
但这仍然是一个有趣的练习,关于编译器错误的问题仍未得到解答。
您无法在基 class 中使用通常的签名有效地声明“派生 operator=
”,因为即使使用 using-declaration ,就是 always hidden by the implicitly-declared copy assignment operator。 (您可以为它们中的一个或两个使用其他签名,但是重载解析可能会……很有趣。)
同时,您发现了一个 GCC 错误,它错误地得出两个运算符冲突而不是一个隐藏另一个的结论。
我正在尝试使用 CRTP 在派生的 classes 的基础 class 中实现 move/copy 赋值运算符和构造函数。
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=
被隐式定义,然后通过 using
声明引入 base<derived>::operator=
我可能会再次尝试重新定义它?这看起来与意外定义方法两次时出现的错误非常相似。
我用 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
class 中定义 operators/constructors 然后将它们的功能委托给 base
class里面的定义?
更新
OK,可能是看清楚了,还是觉得太复杂了。我可以执行以下操作:
Derived& base<Derived>::operator= (const base& other) {
this->foo_ = other.foo_;
return this->self();
}
因此返回的类型对于每个派生 class 都是正确的,并且复制是从基础 class 执行的 - 仅复制基础属性,这是我默认需要的。如果我需要更多,那么它特定于每个派生 class:
// 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_;
}
但这仍然是一个有趣的练习,关于编译器错误的问题仍未得到解答。
您无法在基 class 中使用通常的签名有效地声明“派生 operator=
”,因为即使使用 using-declaration ,就是 always hidden by the implicitly-declared copy assignment operator。 (您可以为它们中的一个或两个使用其他签名,但是重载解析可能会……很有趣。)
同时,您发现了一个 GCC 错误,它错误地得出两个运算符冲突而不是一个隐藏另一个的结论。