Я пытаюсь реализовать операторы и конструкторы назначения перемещения / копирования в базовом классе для производных классов с использованием 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_;
}
Но, тем не менее, это интересное упражнение, и вопрос об ошибке компилятора остается без ответа.