#include <iostream>
using namespace std;
template < class T, class Pref, class Suf> class Wrap;
template < class T, class Suf>
class Call_proxy {
T* p;
mutable bool own;
Suf suffix;
Call_proxy( T* pp, Suf su) : p( pp) , own( true ) , suffix( su) { } // restrict creation
Call_proxy& operator= ( const Call_proxy& ) ; // prevent assignment
public :
template < class U, class P, class S> friend class Wrap;
Call_proxy( const Call_proxy& a) : p( a.p ) , own( true ) , suffix( a.suffix ) { a.own = false ; }
~Call_proxy( ) { if ( own) suffix( ) ; }
//T* operator->() const{ return p;}
T& operator- > ( ) const { return * p; }
} ;
template < class T, class Pref, class Suf>
class Wrap {
T* p;
int * owned;
void incr_owned( ) const { if ( owned) ++* owned; }
void decr_owned( ) const { if ( owned && --* owned == 0 ) { delete p; delete owned; } }
Pref prefix;
Suf suffix;
public :
Wrap( T& x, Pref pr, Suf su) : p( & x) , owned( 0 ) , prefix( pr) , suffix( su) { }
Wrap( T* pp, Pref pr, Suf su) : p( pp) , owned( new int ( 1 ) ) , prefix( pr) , suffix( su) { }
Wrap( const Wrap& a)
: p( a.p ) , owned( a.owned ) , prefix( a.prefix ) , suffix( a.suffix ) { incr_owned( ) ; }
Wrap& operator= ( const Wrap& a)
{
a.incr_owned ( ) ;
decr_owned( ) ;
p = a.p ;
owned = a.owned ;
prefix= a.prefix ;
suffix= a.suffix ;
return * this ;
}
~Wrap( ) { decr_owned( ) ; }
Call_proxy< T,Suf> operator- > ( ) const { prefix( ) ; return Call_proxy< T,Suf> ( p,suffix) ; }
T* direct( ) const { return p; } // extract pointer to wrapped object
} ;
class X { // one user class
public :
X( ) { cout << " make an X\n " ; }
~X( ) { cout << "destroy an X\n " ; }
int f( ) const { cout << "f()" ; return 1 ; }
void g( ) const { cout << "g()" ; }
} ;
class Y { // another user class
public :
Y( ) { cout << " make a Y\n " ; }
~Y( ) { cout << "destroy a Y\n " ; }
void h( ) const { cout << "h()" ; }
} ;
void prefix( ) { cout << "prefix " ; }
void suffix( ) { cout << " suffix\n " ; }
struct Pref { void operator( ) ( ) const { cout << " Pref " ; } } ;
struct Suf { void operator( ) ( ) const { cout << " Suf " ; } } ;
template < class T>
struct Shared : public Wrap< T,Pref, Suf>
{
Shared( T& obj) : Wrap< T,Pref, Suf> ( obj,Pref( ) , Suf( ) ) { }
} ;
template < class T>
struct Tracer : public Wrap< T,void ( * ) ( ) ,void ( * ) ( ) > {
Tracer( T& x) : Wrap< T,void ( * ) ( ) ,void ( * ) ( ) > ( x,:: prefix ,:: suffix ) { }
} ;
int main( ) // test program
{
X x;
Shared< X> xx( x) ;
Tracer< Shared< X>> xxx( xx) ;
xx- > g( ) ;
xxx- > g( ) ;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgIFByZWYsIGNsYXNzIFN1Zj4gY2xhc3MgIFdyYXA7CnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFN1Zj4KY2xhc3MgIENhbGxfcHJveHkgewoJVCogcDsKCW11dGFibGUgYm9vbCBvd247CglTdWYgc3VmZml4OwoJQ2FsbF9wcm94eShUKiBwcCwgU3VmIHN1KSA6cChwcCkgLCBvd24odHJ1ZSkgLCBzdWZmaXgoc3UpIHsgfSAgLy8gcmVzdHJpY3QgY3JlYXRpb24KCUNhbGxfcHJveHkmIG9wZXJhdG9yPShjb25zdCAgQ2FsbF9wcm94eSYpIDsgIC8vIHByZXZlbnQgYXNzaWdubWVudApwdWJsaWM6Cgl0ZW1wbGF0ZTxjbGFzcyAgVSwgY2xhc3MgIFAsIGNsYXNzIFM+IGZyaWVuZCBjbGFzcyAgV3JhcDsKCUNhbGxfcHJveHkoY29uc3QgIENhbGxfcHJveHkmIGEpIDogcChhLnApICwgb3duKHRydWUpICwgc3VmZml4KGEuc3VmZml4KSB7IGEub3duPWZhbHNlOyB9Cgl+Q2FsbF9wcm94eSgpIHsgaWYgKG93bikgc3VmZml4KCkgOyB9CgoJLy9UKiBvcGVyYXRvci0+KCkgY29uc3R7IHJldHVybiBwO30KCVQmIG9wZXJhdG9yLT4oKSBjb25zdHsgcmV0dXJuICpwO30KCQp9OwoKCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzICBQcmVmLCBjbGFzcyBTdWY+CmNsYXNzICBXcmFwIHsKCVQqIHA7CglpbnQqIG93bmVkOwoJdm9pZCBpbmNyX293bmVkKCkgY29uc3R7IGlmKG93bmVkKSArKypvd25lZDsgfQoJdm9pZCBkZWNyX293bmVkKCkgY29uc3R7IGlmKG93bmVkICYmIC0tKm93bmVkID09IDApIHsgZGVsZXRlIHA7IGRlbGV0ZSBvd25lZDsgfSB9CglQcmVmIHByZWZpeDsKCVN1ZiBzdWZmaXg7CnB1YmxpYzoKCVdyYXAoVCYgeCwgIFByZWYgcHIsIFN1ZiBzdSkgOnAoJngpICwgb3duZWQoMCkgLCBwcmVmaXgocHIpICwgc3VmZml4KHN1KSB7IH0KCVdyYXAoVCogcHAsICBQcmVmIHByLCBTdWYgc3UpIDpwKHBwKSAsIG93bmVkKG5ldyBpbnQoMSkpICwgcHJlZml4KHByKSAsIHN1ZmZpeChzdSkgeyB9CglXcmFwKGNvbnN0ICBXcmFwJiBhKQoJCTpwKGEucCkgLCBvd25lZChhLm93bmVkKSAsIHByZWZpeChhLnByZWZpeCkgLCBzdWZmaXgoYS5zdWZmaXgpIHsgaW5jcl9vd25lZCgpIDsgfQoJV3JhcCYgb3BlcmF0b3I9KGNvbnN0ICBXcmFwJiBhKQoJewoJCWEuaW5jcl9vd25lZCgpIDsKCQlkZWNyX293bmVkKCkgOwoJCXAgPSBhLnA7CgkJb3duZWQgPSBhLm93bmVkOwoJCXByZWZpeD0gYS5wcmVmaXg7CgkJc3VmZml4PSBhLnN1ZmZpeDsKCQlyZXR1cm4gKnRoaXM7Cgl9Cgl+V3JhcCgpIHsgZGVjcl9vd25lZCgpIDsgfQoJQ2FsbF9wcm94eTxULFN1Zj4gb3BlcmF0b3ItPigpIGNvbnN0eyBwcmVmaXgoKSA7IHJldHVybiAgQ2FsbF9wcm94eTxULFN1Zj4ocCxzdWZmaXgpIDsgfQoJVCogZGlyZWN0KCkgY29uc3R7IHJldHVybiBwOyB9IC8vIGV4dHJhY3QgcG9pbnRlciB0byB3cmFwcGVkIG9iamVjdAp9OwoKY2xhc3MgWCAgeyAvLyBvbmUgdXNlciBjbGFzcwpwdWJsaWM6CglYKCkgeyBjb3V0IDw8ICIgbWFrZSBhbiAgWFxuIjsgfQoJflgoKSB7IGNvdXQgPDwgImRlc3Ryb3kgYW4gIFhcbiI7IH0KCWludCBmKCkgY29uc3R7IGNvdXQgPDwgImYoKSI7IHJldHVybiAxOyB9Cgl2b2lkIGcoKSBjb25zdHsgY291dCA8PCAiZygpIjsgfQp9OwpjbGFzcyBZIHsgLy8gYW5vdGhlciB1c2VyIGNsYXNzCnB1YmxpYzoKCVkoKSB7IGNvdXQgPDwgIiBtYWtlIGEgWVxuIjsgfQoJflkoKSB7IGNvdXQgPDwgImRlc3Ryb3kgYSBZXG4iOyB9Cgl2b2lkIGgoKSBjb25zdHsgY291dCA8PCAiaCgpIjsgfQp9OwoKdm9pZCBwcmVmaXgoKSB7IGNvdXQgPDwgInByZWZpeCAiOyB9CnZvaWQgc3VmZml4KCkgeyBjb3V0IDw8ICIgc3VmZml4XG4iOyB9CgpzdHJ1Y3QgIFByZWYgeyB2b2lkIG9wZXJhdG9yKCkoKSBjb25zdHsgY291dDw8ICIgUHJlZiAiOyB9IH07CnN0cnVjdCBTdWYgeyB2b2lkIG9wZXJhdG9yKCkoKSBjb25zdHsgY291dDw8ICIgU3VmICI7IH0gfTsKCnRlbXBsYXRlPGNsYXNzIFQ+CnN0cnVjdCBTaGFyZWQgOiBwdWJsaWMgIFdyYXA8VCxQcmVmLCBTdWY+CnsKCVNoYXJlZChUJiBvYmopIDogIFdyYXA8VCxQcmVmLCBTdWY+KG9iaixQcmVmKCkgLCBTdWYoKSkgeyB9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPgpzdHJ1Y3QgVHJhY2VyIDogcHVibGljICBXcmFwPFQsdm9pZCgqKSgpICx2b2lkKCopKCk+IHsKCVRyYWNlcihUJiB4KSA6ICBXcmFwPFQsdm9pZCgqKSgpICx2b2lkKCopKCk+KHgsOjpwcmVmaXgsOjpzdWZmaXgpIHsgfQp9OwoKaW50ICBtYWluKCkgIC8vIHRlc3QgcHJvZ3JhbQp7CglYIHg7CglTaGFyZWQ8WD4geHgoeCkgOwoJVHJhY2VyPFNoYXJlZDxYPj4geHh4KHh4KTsKCgl4eC0+ZygpOwoJeHh4LT5nKCk7CglyZXR1cm4gMDsKfQ==