@profezzorn I think its interesting… not too long ago I was introduced to the CRTP via your menu system, and I find myself now using it (albeit in a much less complicated way) for something quite convenient.
Basically the solution is pulled from this Stackoverflow answer:
template <class BASE>
struct RequireClone {
virtual BASE *clone() = 0;
};
template <class BASE, class DERIVED>
struct Clonable : BASE {
virtual BASE *clone() const {
return new DERIVED(static_cast<const DERIVED&>(*this));
}
};
While building ProffieConfig V2’s components system, I find myself using a rather complex hierarchy for managing things, laced with hash lookup maps and shared pointers galore, and I got to the point where I needed to do a proper deep copy. It is now I realize why wxWidgets’ wxObject
has that Clone()
method that’s required of everything… it didn’t even occur to me prior why they had a Clone method at all and why it was needed.
In case it’s not clear, it ends up being used like this:
struct CONFIG_EXPORT Component : RequireClone<Component> {
... fiddly bits, mostly pure virtuals ...
};
struct CONFIG_EXPORT AnActualComponent : Clonable<Component, AnActualComponent> {
... implementation specification and other things ...
};
Anyways, thought it was interesting because of the timing. And now I’ve learned (in an application I can understand better ) a use-case for CRTP and a neat little bit of knowledge about a particular implementation detail via firsthand experience.
EDIT: I also setup Cloneable
to have a forwarding ctor for the base type to be used in the ctor for the derived, if applicable.