I do it in a generalized way.
Definition:
template <class Class>
class CloneInterface {
public:
Class* copy() const { return new Class{static_cast<Class const&>(*this)}; }
virtual Class* clone() const { return this->copy(); }
};
template <class Derived, class Base>
class CloneCRTP : public Base {
public:
Derived* copy() const { return new Derived{static_cast<Derived const&>(*this)}; }
Base* clone() const override { return this->copy(); }
};
Usage:
class Base : public CloneInterface<Base> {
private:
int a = 0;
public:
virtual ~Base() {}
void print() { std::cout << "Base: a = " << a << '\n'; }
};
class A : public CloneCRTP<A, Base> {
private:
int b = 1;
public:
void print() { std::cout << "A: b = " << b << '\n'; }
};
Example:
int main() {
auto b = new Base();
auto b_clone = b->clone();
auto b_copy = b->copy();
b->print(); // Base print()
b_clone->print(); // Base print()
b_copy->print(); // Base print()
std::cout << "=========================\n";
auto a = new A();
auto a_clone = a->clone(); // returns Base*
auto a_copy = a->copy(); // returns A*
a->print(); // A print()
a_clone->print(); // Base print(), because clone returns pointer to the base class
a_copy->print(); // A print()
std::cout << "=========================\n";
auto c = static_cast<Base*>(a);
auto c_clone = c->clone(); // returns Base*, but A* inside
auto c_copy = c->copy(); // returns Base*, that is really Base
c->print(); // Base print()
c_clone->print(); // Base print()
c_copy->print(); // Base print()
std::cout << "=========================\n";
auto a_clone_restored = static_cast<A*>(c_clone);
auto a_copy_restored = static_cast<A*>(c_copy); // Invalid
a_clone_restored->print(); // A print()
a_copy_restored->print(); // A print()
delete b;
delete b_clone;
delete b_copy;
delete a;
delete a_clone;
delete a_copy;
return 0;
}
This approach allows to reuse crtp definition in all hierarchies that require clone functionality.
Code: https://coliru.stacked-crooked.com/a/269a2427fd2f919b