#include <memory>
#include <string>
#include <iostream>
struct Base{
protected:
virtual std::shared_ptr<Base> clone_impl() const{
return std::make_shared<Base>(*this);
};
public:
std::shared_ptr<Base> clone()const{
return clone_impl();
}
std::string DoBase(){ return "Base"; }
virtual std::string Name(){ return DoBase(); }
};
template<class D, class B>
struct clonable:public B{
virtual std::shared_ptr<B> clone_impl() const override{
return std::make_shared<D>(static_cast<const D&>(*this));
}
std::shared_ptr<D> clone()const{
return std::static_pointer_cast<D>(clone_impl());
}
};
struct Derived : public clonable<Derived,Base>{
std::string DoDerived(){ return "Derived"; }
virtual std::string Name()override{ return DoDerived(); }
};
struct Derived2 : public clonable<Derived2, Base>{
std::string DoDerived2(){ return "Derived2"; }
virtual std::string Name() override{ return DoDerived2(); }
};
int main(){
{
auto spD = std::make_shared<Derived>();
std::shared_ptr<Base> spB = spD;
auto clonedB = spB->clone();
auto clonedD = spD->clone();
std::cout << clonedB->DoBase() << "\n";
std::cout << clonedD->DoDerived() << "\n";
std::cout << clonedB->Name() << "\n";
}
{
auto spD = std::make_shared<Derived2>();
std::shared_ptr<Base> spB = spD;
auto clonedB = spB->clone();
auto clonedD = spD->clone();
std::cout << clonedB->DoBase() << "\n";
std::cout << clonedD->DoDerived2() << "\n";
std::cout << clonedB->Name() << "\n";
}
}