00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef Rep_h
00022 #define Rep_h
00023
00024 #include <iosfwd>
00025
00027
00028
00046 class Rep {
00047 private:
00048
00052 mutable unsigned _counter;
00053
00054 protected:
00055
00059 virtual void ref_to( unsigned rep_cnt_r ) const {}
00065 virtual void unref_to( unsigned rep_cnt_r ) const {}
00066
00067 public:
00068
00072 Rep() : _counter( 0 ) {}
00076 Rep( const Rep & rhs ) : _counter( 0 ) {}
00080 Rep & operator=( const Rep & rhs ) { return *this; }
00084 virtual ~Rep() { if ( _counter ) throw( this ); }
00085
00086 public:
00087
00091 void ref() const {
00092 ref_to( ++_counter );
00093 }
00099 void unref() const {
00100 if ( ! _counter )
00101 throw( this );
00102 if ( --_counter )
00103 unref_to( _counter );
00104 else
00105 delete this;
00106 }
00107
00112 static void ref( const Rep * obj_r ) {
00113 if ( obj_r )
00114 obj_r->ref();
00115 }
00120 static void unref( const Rep * obj_r ) {
00121 if ( obj_r )
00122 obj_r->unref();
00123 }
00124
00125 public:
00126
00130 unsigned refCount() const { return _counter; }
00131
00132 public:
00133
00137 virtual const char * repName() const { return "Rep"; }
00143 virtual std::ostream & dumpOn( std::ostream & str ) const;
00144 };
00145
00149 std::ostream & operator<<( std::ostream & str, const Rep & obj );
00153 std::ostream & operator<<( std::ostream & str, const Rep * obj );
00154
00156
00158
00159
00167 class CountedRep : public Rep {
00168
00169 private:
00170
00174 static unsigned _objectCount;
00178 static unsigned _objectIds;
00179
00183 const unsigned _objectId;
00184
00185 public:
00186
00190 CountedRep() : _objectId( ++_objectIds ) { ++_objectCount; }
00194 CountedRep( const CountedRep & rhs ) : _objectId( ++_objectIds ) { ++_objectCount; }
00198 CountedRep & operator=( const CountedRep & rhs ) {
00199 Rep::operator=( rhs );
00200 return *this;
00201 }
00205 virtual ~CountedRep() { --_objectCount; }
00206
00207 public:
00208
00212 unsigned objectId() const { return _objectId; }
00213
00217 static unsigned objectCount() { return _objectCount; }
00218
00219 public:
00220
00224 virtual std::ostream & dumpOn( std::ostream & str ) const;
00225 };
00226
00228
00230
00231
00232
00234
00236
00237
00269 template<typename _Tp, typename _Bt = _Tp>
00270 class RepPtrStore {
00271
00272 private:
00273
00277 _Tp * _obj;
00278
00279 private:
00280
00285 void _assign( _Tp * new_r );
00286
00287 public:
00288
00292 RepPtrStore() : _obj( 0 ) {}
00296 RepPtrStore( _Tp * ptr ) : _obj( 0 ) { _assign( ptr ); }
00300 RepPtrStore( const RepPtrStore & rhs ) : _obj( 0 ) { _assign( rhs._obj ); }
00301
00305 RepPtrStore & operator=( _Tp * ptr ) { _assign( ptr ); return *this; }
00309 RepPtrStore & operator=( const RepPtrStore & rhs ) { _assign( rhs._obj ); return *this; }
00310
00314 ~RepPtrStore() { _assign( 0 ); }
00315
00319 operator _Tp *() const { return _obj; }
00320
00321 public:
00322
00326 void tryAssign( _Bt * ptr );
00327
00328 public:
00329
00333 _Bt * base() const;
00337 const Rep * refbase() const;
00338 };
00339
00340 template<typename _Tp,typename _Bt>
00341 void RepPtrStore<_Tp,_Bt>::_assign( _Tp * new_r ) {
00342 if ( new_r != _obj ) {
00343 Rep::unref( _obj );
00344 _obj = new_r;
00345 Rep::ref( _obj );
00346 }
00347 }
00348
00349 template<typename _Tp,typename _Bt>
00350 void RepPtrStore<_Tp,_Bt>::tryAssign( _Bt * ptr ) {
00351 _assign( dynamic_cast<_Tp*>(ptr) );
00352 if ( !_obj && ptr && ! ptr->refCount() ) {
00353 Rep::ref( ptr );
00354 Rep::unref( ptr );
00355 }
00356 }
00357
00358 template<typename _Tp,typename _Bt>
00359 _Bt * RepPtrStore<_Tp,_Bt>::base() const { return _obj; }
00360
00361 template<typename _Tp,typename _Bt>
00362 const Rep * RepPtrStore<_Tp,_Bt>::refbase() const { return _obj; }
00363
00365
00367
00368
00377 class RepPtrBase {
00381 friend std::ostream & operator<<( std::ostream & str, const RepPtrBase & obj );
00382
00383 protected:
00384
00388 virtual ~RepPtrBase() {}
00392 virtual const Rep * refbase() const = 0;
00393
00394 public:
00395
00400 operator const void *() const { return refbase(); }
00401 };
00402
00404
00405 template<typename _Bt> class constPtrBase;
00406
00408
00409
00415 template<typename _Bt>
00416 class PtrBase : public RepPtrBase {
00417
00418 protected:
00419
00420 friend class constPtrBase<_Bt>;
00421
00425 virtual _Bt * base() const = 0;
00426
00430 _Bt * getBase( const PtrBase & rhs ) const {
00431 return rhs.base();
00432 }
00433 };
00434
00436
00438
00439
00445 template<typename _Bt>
00446 class constPtrBase : public RepPtrBase {
00447
00448 protected:
00449
00453 virtual const _Bt * base() const = 0;
00454
00458 const _Bt * getBase( const constPtrBase & rhs ) const {
00459 return rhs.base();
00460 }
00461
00466 const _Bt * getBase( const PtrBase<_Bt> & rhs ) const {
00467 return rhs.base();
00468 }
00469 };
00470
00472
00473 template<typename _Tp,typename _Bt> class constPtr;
00474
00476
00477
00481 template<typename _Tp, typename _Bt = _Tp>
00482 class Ptr : public PtrBase<_Bt> {
00483
00484 private:
00485
00489 RepPtrStore<_Tp,_Bt> _ptr;
00490
00491 protected:
00492
00496 virtual const Rep * refbase() const { return _ptr.refbase(); }
00500 virtual _Bt * base() const { return _ptr.base(); }
00501
00502 public:
00503
00507 Ptr( _Tp * ptr = 0 ) : _ptr( ptr ) {}
00511 Ptr( const Ptr & rhs ) : _ptr( rhs._ptr ) {}
00515 Ptr( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00516
00517 public:
00518
00522 Ptr & operator=( _Tp * ptr ) { _ptr = ptr; return *this; }
00526 Ptr & operator=( const Ptr & rhs ) { _ptr = rhs._ptr; return *this; }
00530 Ptr & operator=( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00531
00532 public:
00533
00537 _Tp * operator->() const { return _ptr; }
00538
00539 public:
00540
00544 static Ptr cast_away_const( constPtr<_Tp,_Bt> rhs ) {
00545 return const_cast<_Tp*>(rhs.operator->());
00546 }
00547 };
00548
00550
00552
00553
00557 template<typename _Tp, typename _Bt = _Tp>
00558 class constPtr : public constPtrBase<_Bt> {
00559
00560 private:
00561
00565 RepPtrStore<const _Tp,const _Bt> _ptr;
00566
00567 protected:
00568
00572 virtual const Rep * refbase() const { return _ptr.refbase(); }
00576 virtual const _Bt * base() const { return _ptr.base(); }
00577
00578 public:
00579
00583 constPtr( const _Tp * ptr = 0 ) : _ptr( ptr ) {}
00587 constPtr( const constPtr & rhs ) : _ptr( rhs._ptr ) {}
00591 constPtr( const constPtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00592
00593 public:
00594
00598 constPtr & operator=( const _Tp * ptr ) { _ptr = ptr; return *this; }
00602 constPtr & operator=( const constPtr & rhs ) { _ptr = rhs._ptr; return *this; }
00606 constPtr & operator=( const constPtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00607
00608 public:
00609
00613 constPtr( const Ptr<_Tp,_Bt> & rhs ) : _ptr( rhs.operator->() ) {}
00617 constPtr( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00618
00619 public:
00620
00624 constPtr & operator=( const Ptr<_Tp,_Bt> & rhs ) { _ptr = rhs.operator->(); return *this; }
00628 constPtr & operator=( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00629
00630 public:
00631
00635 const _Tp * operator->() const { return _ptr; }
00636 };
00637
00639
00640 #endif // Rep_h