Re: covariant return types with CRTP
iwongu wrote:
template <class T, class U>
struct clonable : U
{
T* clone() const { // (8)
T const* d = static_cast<T const*>(this);
return new T(*d);
}
};
struct B
{
virtual ~B() {}
virtual B* clone() const = 0; // (17)
};
struct D : clonable<D, B>
{ // (21)
};
But this change does not help. The compile error message is,
: In instantiation of `clonable<D, B>':
:21: instantiated from here
:8: conflicting return type specified for `T* clonable<T, U>::clone()
const [with T = D, U = B]'
:17: overriding `virtual B* B::clone() const'
I think that this should be treated as a covariance return type case
according to the 10.3.5 of the C++98.
Unfortunately, during the instantiation of clonable<D,B> the class D
is still an incomplete type, so the the compiler can't tell that the
return types are covariant.
There have been numerous discussions about this, just try to seach
clc++m. The best solution seems to be
template <typename Derived,typename Base>
class Clonable : Base{
public:
Derived* clone() const{
return static_cast<Derived*>(this->do_clone());
}
private:
virtual Clonable* do_clone() const{
return new Derived(static_cast<const Derived&>(*this));
}
};
class ClonableBase{
public:
ClonableBase* clone() const{
return do_clone();
}
private:
virtual ClonableBase* do_clone() const=0;
};
You get pretty much everything you need including
pseudo-covariant returns. This is, however, as good as it gets.
Extension to multiple inheritance is simply impossible, the
showstopper being a virtual function declared in two or more
base classes. The "MIClonable" template class must declare
such functions (we want to override do_clone in all bases, so
a single instantiation of MIClonable must inherit from all of
them) but it has no way of knowing their names.
Regards,
Vladimir Marko
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]