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 ) const {}
00065 virtual void unref_to( unsigned ) 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 ) : Rep( 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 ) : PtrBase<_Bt>( 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
00542 _Tp & operator*() const { return *_ptr; }
00543
00544 public:
00545
00549 static Ptr cast_away_const( constPtr<_Tp,_Bt> rhs ) {
00550 return const_cast<_Tp*>(rhs.operator->());
00551 }
00552 };
00553
00555
00557
00558
00562 template<typename _Tp, typename _Bt = _Tp>
00563 class constPtr : public constPtrBase<_Bt> {
00564
00565 private:
00566
00570 RepPtrStore<const _Tp,const _Bt> _ptr;
00571
00572 protected:
00573
00577 virtual const Rep * refbase() const { return _ptr.refbase(); }
00581 virtual const _Bt * base() const { return _ptr.base(); }
00582
00583 public:
00584
00588 constPtr( const _Tp * ptr = 0 ) : _ptr( ptr ) {}
00592 constPtr( const constPtr & rhs ) : constPtrBase<_Bt>( rhs ), _ptr( rhs._ptr ) {}
00596 constPtr( const constPtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00597
00598 public:
00599
00603 constPtr & operator=( const _Tp * ptr ) { _ptr = ptr; return *this; }
00607 constPtr & operator=( const constPtr & rhs ) { _ptr = rhs._ptr; return *this; }
00611 constPtr & operator=( const constPtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00612
00613 public:
00614
00618 constPtr( const Ptr<_Tp,_Bt> & rhs ) : _ptr( rhs.operator->() ) {}
00622 constPtr( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); }
00623
00624 public:
00625
00629 constPtr & operator=( const Ptr<_Tp,_Bt> & rhs ) { _ptr = rhs.operator->(); return *this; }
00633 constPtr & operator=( const PtrBase<_Bt> & rhs ) { _ptr.tryAssign( getBase( rhs ) ); return *this; }
00634
00635 public:
00636
00640 const _Tp * operator->() const { return _ptr; }
00644 const _Tp & operator*() const { return *_ptr; }
00645 };
00646
00648
00650
00651
00652
00654
00656
00657
00668 class BasicRepPtr
00669 {
00673 friend std::ostream &
00674 operator<<( std::ostream & str, const BasicRepPtr & obj )
00675 { return str << obj._ptr; }
00676
00677 public:
00681 operator const void *() const
00682 { return _ptr; }
00683
00684 protected:
00688 BasicRepPtr()
00689 : _ptr( NULL )
00690 {}
00691
00692 explicit
00693 BasicRepPtr( Rep * ptr )
00694 : _ptr( NULL )
00695 { _assign( ptr ); }
00696
00697 BasicRepPtr( const BasicRepPtr & rhs )
00698 : _ptr( NULL )
00699 { _assign( rhs._ptr ); }
00700
00701 BasicRepPtr &
00702 operator=( const BasicRepPtr & rhs )
00703 { _assign( rhs._ptr ); return *this; }
00704
00705 ~BasicRepPtr()
00706 { _assign( NULL ); }
00707
00711 Rep *
00712 repPtr() const
00713 { return _ptr; }
00714
00715 private:
00719 Rep * _ptr;
00720
00725 void
00726 _assign( Rep * new_r )
00727 {
00728
00729 if ( new_r != _ptr )
00730 {
00731 Rep::unref( _ptr );
00732 _ptr = new_r;
00733 Rep::ref( _ptr );
00734 }
00735 }
00736 };
00738
00739
00741
00743
00744
00768 template<typename _Rep>
00769 class VarPtr : public BasicRepPtr
00770 {
00771 public:
00772
00776 VarPtr()
00777 : BasicRepPtr()
00778 {}
00779
00783 explicit
00784 VarPtr( _Rep * ptr_r )
00785 : BasicRepPtr( ptr_r )
00786 {}
00787
00788 public:
00789
00790 _Rep *
00791 operator->()
00792 { return ptr(); }
00793
00794 const _Rep *
00795 operator->() const
00796 { return ptr(); }
00797
00798 _Rep &
00799 operator*()
00800 { return *ptr(); }
00801
00802 const _Rep &
00803 operator*() const
00804 { return *ptr(); }
00805
00806 private:
00807
00808 _Rep *
00809 ptr() const
00810 { return static_cast<_Rep *>( BasicRepPtr::repPtr() ); }
00811 };
00813
00815
00819 template<typename _Rep>
00820 inline VarPtr<_Rep>
00821 makeVarPtr( _Rep * ptr )
00822 { return VarPtr<_Rep>( ptr ); }
00823
00825
00826 #endif // Rep_h