Re: Automatically create a clone() function for derived classes
blargg wrote:
In article <l3znl.97$zj6.74@read4.inet.fi>, Juha Nieminen
<nospam@thanks.invalid> wrote:
[...]
class Base
{
public:
virtual Base* clone() const { return new Base(*this); }
// other stuff here
};
The problem is that this clone() function must be replicated in all
the derived classes as well, and their implementation is always the
same, except for the type which is being allocated. For example:
class Derived: public Base
{
public:
virtual Base* clone() const { return new Derived(*this); }
};
It's not only tedious to have to write this line in each of the
derived classes, but it's also error-prone: If you ever forget to add
that line to some derived class, no compiler error will happen, and the
program will even run, but when cloning a derived object using a base
type pointer, you get a crippled copy, so the whole thing malfunctions,
and it might malfunction in a very non-obvious way which is hard to
track and debug.
Isn't there any way of automating this process?
[...]
Odd-ball approach that comes to mind, if compile-time checking is
insisted on:
class Clonable {
protected:
template<class T>
Clonable( T const* t )
{
// ensure that T implements covariant clone
if ( false )
t = t->clone();
Calling virtual function from within constructor == very bad. Besides
that it looks like a rather interesting solution. I think you could
improve it through something similar to boost::any:
class Clonable {
protected:
template < typename T >
Clonable( T const* t) : pimpl(new impl<T>(t))
{}
Clonable * clone() const { return pimpl->clone(); }
private:
struct impl_base
{
virtual Clonable* clone() const = 0;
};
template < typename T >
struct impl : impl_base
{
impl(T const* t) : var(t) {}
Clonable * clone() const { return new T(var); }
T const* var;
};
scoped_ptr<impl_base> pimpl;
};
Leave your virtual inheritance and turn Base::clone into:
Base * Base::clone() const { return static_cast<Base*>(Clonable::clone()); }
Wouldn't even need to be virtual as the polymorphism is taken care of by
Clonable's pimpl.
This is untested but I'm pretty confident it, or something like it,
would work. The only thing lost is the ability to construct Derived
pointers without casts even when you know the Derived type. Some sort
of policy based programming might do the trick there.