#include <cstdio>
#include <memory>
class B {
private:
virtual B *clone_impl( ){ return new B( *this ); }
protected:
int b;
public:
explicit B( int x ): b( x ){ }
B( const B &that ): b( that.b ){ }
virtual ~B( ){ }
std::shared_ptr<B> clone( ){ return std::shared_ptr<B>( clone_impl( )); }
virtual void print( ) const { std::printf( "B: %d\n", b ); };
};
class D: public B {
private:
D *clone_impl( ) { return new D( *this ); }
protected:
int d;
public:
D( int x ): B(x), d( x*2 ){ }
D( const D &that ): B( that.b ), d( that.d ){ }
~D( ){ }
std::shared_ptr<D> clone( ){ return std::shared_ptr<D>( clone_impl( )); }
void print( ) const { std::printf( "D: %d, %d\n", b, d ); };
};
int main(){
B b(6);
D d(42);
b.print( );
d.print( );
B *bp = &d;
bp->print( );
std::shared_ptr<B> bfromb = b.clone( );
std::shared_ptr<B> bfromd = d.clone( );
std::shared_ptr<D> dfromd = d.clone( );
// std::shared_ptr<D> dfromb = b.clone( ); // ERR
std::shared_ptr<B> bfrombp = bp->clone( );
// std::shared_ptr<D> dfrombp = bp->clone( ); // ERR
bfromb->print( );
bfromd->print( );
dfromd->print( );
bfrombp->print( );
}
I2luY2x1ZGUgPGNzdGRpbz4KI2luY2x1ZGUgPG1lbW9yeT4KCmNsYXNzIEIgewpwcml2YXRlOgogIHZpcnR1YWwgQiAqY2xvbmVfaW1wbCggKXsgcmV0dXJuIG5ldyBCKCAqdGhpcyApOyB9CnByb3RlY3RlZDoKICBpbnQgYjsKcHVibGljOgogIGV4cGxpY2l0IEIoIGludCB4ICk6IGIoIHggKXsgfQogIEIoIGNvbnN0IEIgJnRoYXQgKTogYiggdGhhdC5iICl7IH0KICB2aXJ0dWFsIH5CKCApeyB9CiAgc3RkOjpzaGFyZWRfcHRyPEI+IGNsb25lKCApeyByZXR1cm4gc3RkOjpzaGFyZWRfcHRyPEI+KCBjbG9uZV9pbXBsKCApKTsgfQogIHZpcnR1YWwgdm9pZCBwcmludCggKSBjb25zdCB7IHN0ZDo6cHJpbnRmKCAiQjogJWRcbiIsIGIgKTsgfTsKfTsKCmNsYXNzIEQ6IHB1YmxpYyBCIHsKcHJpdmF0ZToKICBEICpjbG9uZV9pbXBsKCApIHsgcmV0dXJuIG5ldyBEKCAqdGhpcyApOyB9CnByb3RlY3RlZDoKICBpbnQgZDsKcHVibGljOgogIEQoIGludCB4ICk6IEIoeCksIGQoIHgqMiApeyB9CiAgRCggY29uc3QgRCAmdGhhdCApOiBCKCB0aGF0LmIgKSwgZCggdGhhdC5kICl7IH0KICB+RCggKXsgfQogIHN0ZDo6c2hhcmVkX3B0cjxEPiBjbG9uZSggKXsgcmV0dXJuIHN0ZDo6c2hhcmVkX3B0cjxEPiggY2xvbmVfaW1wbCggKSk7IH0KICB2b2lkIHByaW50KCApIGNvbnN0IHsgc3RkOjpwcmludGYoICJEOiAlZCwgJWRcbiIsIGIsIGQgKTsgfTsKfTsKCmludCBtYWluKCl7CiAgQiBiKDYpOwogIEQgZCg0Mik7CgogIGIucHJpbnQoICk7CiAgZC5wcmludCggKTsKCiAgQiAqYnAgPSAmZDsKICBicC0+cHJpbnQoICk7CgogIHN0ZDo6c2hhcmVkX3B0cjxCPiBiZnJvbWIgPSBiLmNsb25lKCApOwogIHN0ZDo6c2hhcmVkX3B0cjxCPiBiZnJvbWQgPSBkLmNsb25lKCApOwogIHN0ZDo6c2hhcmVkX3B0cjxEPiBkZnJvbWQgPSBkLmNsb25lKCApOwovLyAgc3RkOjpzaGFyZWRfcHRyPEQ+IGRmcm9tYiA9IGIuY2xvbmUoICk7IC8vIEVSUgogIHN0ZDo6c2hhcmVkX3B0cjxCPiBiZnJvbWJwID0gYnAtPmNsb25lKCApOwovLyAgc3RkOjpzaGFyZWRfcHRyPEQ+IGRmcm9tYnAgPSBicC0+Y2xvbmUoICk7IC8vIEVSUgoKICBiZnJvbWItPnByaW50KCApOwogIGJmcm9tZC0+cHJpbnQoICk7CiAgZGZyb21kLT5wcmludCggKTsKICBiZnJvbWJwLT5wcmludCggKTsKfQ==