I have a need to clone a derived class given only a reference or pointer to the base class. The following code does the job, but doesn\'t seem elegant, because I\'m putting
You could always stick all the cloning logic into its own class in the middle of the hierarchy:
template <class Derived, class Base>
class CloneCRTP : public Base {
public:
Derived* clone() const override {
return new Derived(static_cast<Derived const&>(*this));
}
};
And then:
class B : public CloneCRTP<B, A>
{
int i;
public:
virtual ~B() { cout << "destroyed b" << endl; }
};
No more boilerplate.
To achieve clone that works as with covariant return type, there is a need for some more complicated CRTP:
class Shape {
// virtual
virtual Shape* do_clone() const = 0;
public:
virtual ~Shape() {}
// non-virtual
Shape* clone() const {
return do_clone();
}
// ...
};
template <class Derived, class Base>
class CloneCRTP : public Base {
// virtual
Shape* do_clone() const override {
return new Derived(static_cast<Derived const&>(*this));
}
public:
// non-virtual
Derived* clone() const {
return static_cast<Derived*>(do_clone());
}
};
Usage:
class Rectangle: public CloneCRTP<Rectangle, Shape> { /*...*/ };
class Triangle: public CloneCRTP<Triangle, Shape> { /*...*/ };
int main() {
Rectangle* r1 = new Rectangle{};
// getting the proper type from clone:
Rectangle* rcopy = r1->clone();
delete rcopy;
delete r1;
Triangle t1{};
// getting the proper type from clone:
Triangle* tcopy = t1.clone();
delete tcopy;
}
Code: http://coliru.stacked-crooked.com/a/d8781deee5f7f6ea
You can rely on the CRTP idiom.
It follows a minimal, working example:
struct B {
~virtual ~B() { }
virtual B* clone() = 0;
};
template<class C>
struct D: public B {
B* clone() {
return new C{*static_cast<C*>(this)};
}
};
struct S: public D<S> { };
int main() {
B *b1 = new S;
B *b2 = b1->clone();
delete b1;
delete b2;
}