#include <memory>
#include <iostream>
struct base
{
using ptr = std::shared_ptr<base> ;
base( int i ) : a(i) {}
virtual ~base() {}
virtual ptr plus( int i ) const { return std::make_shared<base>( a+i ) ; }
virtual std::ostream& print( std::ostream& stm ) const
{ return stm << "base{" << a << '}' ; }
int a ;
};
struct derived : base
{
derived( int i, int j ) : base(i), b(j) {}
virtual ptr plus( int i ) const override
{ return std::make_shared<derived>( a+i, b+i ) ; }
virtual std::ostream& print( std::ostream& stm ) const
{ return stm << "derived{" << a << ',' << b << '}' ; }
int b ;
};
struct surrogate
{
// in real life, we may need to colour constructors
surrogate( int i ) : p( std::make_shared<base>(i) ) {}
surrogate( int i, int j ) : p( std::make_shared<derived>(i,j) ) {}
surrogate( base::ptr pp ) : p(pp) {}
base::ptr p ;
};
surrogate operator+ ( const surrogate& s, int i ) { return s.p->plus(i) ; }
surrogate operator+ ( int i, const surrogate& s ) { return s + i ; }
std::ostream& operator<< ( std::ostream& stm, const surrogate& s )
{ return s.p->print(stm) ; }
int main()
{
surrogate a(100), b(200,300) ;
std::cout << "a: " << a << " a+1234: " << a+1234 << '\n' ;
std::cout << "b: " << b << " 5678+b: " << 5678+b << '\n' ;
}
I2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKc3RydWN0IGJhc2UKewogICAgdXNpbmcgcHRyID0gc3RkOjpzaGFyZWRfcHRyPGJhc2U+IDsKCiAgICBiYXNlKCBpbnQgaSApIDogYShpKSB7fQogICAgdmlydHVhbCB+YmFzZSgpIHt9CgogICAgdmlydHVhbCBwdHIgcGx1cyggaW50IGkgKSBjb25zdCB7IHJldHVybiBzdGQ6Om1ha2Vfc2hhcmVkPGJhc2U+KCBhK2kgKSA7IH0KCiAgICB2aXJ0dWFsICBzdGQ6Om9zdHJlYW0mIHByaW50KCBzdGQ6Om9zdHJlYW0mIHN0bSApIGNvbnN0CiAgICB7IHJldHVybiBzdG0gPDwgImJhc2V7IiA8PCBhIDw8ICd9JyA7IH0KCiAgICBpbnQgYSA7Cn07CgpzdHJ1Y3QgZGVyaXZlZCA6IGJhc2UKewogICAgZGVyaXZlZCggaW50IGksIGludCBqICkgOiBiYXNlKGkpLCBiKGopIHt9CgogICAgdmlydHVhbCAgcHRyIHBsdXMoIGludCBpICkgY29uc3Qgb3ZlcnJpZGUKICAgIHsgcmV0dXJuIHN0ZDo6bWFrZV9zaGFyZWQ8ZGVyaXZlZD4oIGEraSwgYitpICkgOyB9CgogICAgdmlydHVhbCAgc3RkOjpvc3RyZWFtJiBwcmludCggc3RkOjpvc3RyZWFtJiBzdG0gKSBjb25zdAogICAgeyByZXR1cm4gc3RtIDw8ICJkZXJpdmVkeyIgPDwgYSA8PCAnLCcgPDwgYiA8PCAnfScgOyB9CgogICAgaW50IGIgOwp9OwoKc3RydWN0IHN1cnJvZ2F0ZQp7CiAgICAvLyBpbiByZWFsIGxpZmUsIHdlIG1heSBuZWVkIHRvIGNvbG91ciBjb25zdHJ1Y3RvcnMKICAgIHN1cnJvZ2F0ZSggaW50IGkgKSA6IHAoIHN0ZDo6bWFrZV9zaGFyZWQ8YmFzZT4oaSkgKSB7fQogICAgc3Vycm9nYXRlKCBpbnQgaSwgaW50IGogKSA6IHAoIHN0ZDo6bWFrZV9zaGFyZWQ8ZGVyaXZlZD4oaSxqKSApIHt9CgogICAgc3Vycm9nYXRlKCBiYXNlOjpwdHIgcHAgKSA6IHAocHApIHt9CgogICAgYmFzZTo6cHRyIHAgOwp9OwoKc3Vycm9nYXRlIG9wZXJhdG9yKyAoIGNvbnN0IHN1cnJvZ2F0ZSYgcywgaW50IGkgKSB7IHJldHVybiBzLnAtPnBsdXMoaSkgOyB9CnN1cnJvZ2F0ZSBvcGVyYXRvcisgKCBpbnQgaSwgY29uc3Qgc3Vycm9nYXRlJiBzICkgeyByZXR1cm4gcyArIGkgOyB9CnN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PCAoIHN0ZDo6b3N0cmVhbSYgc3RtLCBjb25zdCBzdXJyb2dhdGUmIHMgKQp7IHJldHVybiBzLnAtPnByaW50KHN0bSkgOyB9CgppbnQgbWFpbigpCnsKICAgIHN1cnJvZ2F0ZSBhKDEwMCksIGIoMjAwLDMwMCkgOwogICAgc3RkOjpjb3V0IDw8ICJhOiAiIDw8IGEgPDwgIiAgYSsxMjM0OiAiIDw8IGErMTIzNCA8PCAnXG4nIDsKICAgIHN0ZDo6Y291dCA8PCAiYjogIiA8PCBiIDw8ICIgIDU2NzgrYjogIiA8PCA1Njc4K2IgPDwgJ1xuJyA7Cn0K