// handle_ref_extended.C
// ----------------------------------------------------------------
// COMP 290-001: Algorithm Library Design, Lutz Kettner, 01/11/2000
// Example for a more involved reference counted class.

#include <assert.h>

class Rep {
    int  _count;    
public:
    Rep() : _count( 1) {}
    friend class Handle_base;
};

class Handle_base {
    // Invariant:  PTR is always != 0.
protected:
    Rep* PTR;

    // Note: NO default constructor.
    Handle_base( Rep* rep) : PTR( rep) {
	assert( PTR != 0);
    }

    int&               count() const { 
	assert( PTR != 0);
	return PTR->_count;
    }
};

template < class REP >
class Handle : private Handle_base {
    // Invariant:  PTR is always != 0.

protected:
    // Objects managed with Handle are non-modifiable, thus "const REP*".
    const REP*         ptr() const {
	assert( PTR != 0);
	return (const REP*)PTR;
    }

public:
    Handle() : Handle_base( new REP) {}
    
    Handle( const REP& rep) : Handle_base( new REP(rep)) {}
    
    Handle( const Handle<REP>& x) : Handle_base(x.PTR) {
	++count();
    }
    
    ~Handle() {
	assert( PTR != 0);
	if ( --count() == 0) 
	    delete (REP*)PTR;
    }
    
    Handle<REP>&  operator=( const Handle<REP>& x) {
	assert( x.PTR != 0);
	++( x.count());
	if ( --count() == 0) 
	    delete (REP*)PTR;	
	PTR = x.PTR;
	return *this;
    }
};

struct Integer_rep : public Rep {
    int i;
    Integer_rep() {}
    Integer_rep( int j) : i(j) {}
};

class Integer : public Handle<Integer_rep> {
public:
    Integer() {}
    Integer( int i) : Handle<Integer_rep>(i) {}    
    int value() const  { return ptr()->i; }
};

int main() {
    Integer a(5);
    Integer b(a);
    a = b;
    assert( b.value() == 5);
}

// EOF //

