#ifndef Handle_HH #define Handle_HH #include // // // Christopher L. Bladon // // Smart pointer "Handle" class. Implements reference counting // for zero-reference delete. // // Warnings: // 1) If you assign or construct a Handle to reference a // pointer make sure it can be grabbed and eventually deleted // by this Handle class. // // Example: // // Handle string = new String ("test"); // List< Handle > list; // // list.add (string); // string = new String ("another test"); // if (string) ... // if (string != 0) ... // template class Representation { protected: T *_data; int _flushed; int num_references; public: Representation (T *d = 0) : _data (d), _flushed (0), num_references (1) {} virtual ~Representation () { delete _data; } void increment_references () { ++num_references; } void decrement_references () { --num_references; } int references () const { return num_references; } virtual T *data () const { return _data; } int is_flushed () const { return _flushed; } virtual void flush () {} }; template class Handle { private: Representation *rep; void attach (const Handle &to); void detach (); protected: virtual Representation * create_representation (T *to = 0) { return new Representation (to); } public: Handle (); Handle (const Handle &to); Handle (T *to); ~Handle (); Handle & operator = (T *to); Handle & operator = (const Handle &to); operator const T * () const { return rep->data(); } int operator == (const Handle &that) const; int operator != (const Handle &that) const; int operator == (const T *that) const; int operator != (const T *that) const; int operator == (int that) const; int operator != (int that) const; T * operator -> (); const T * operator -> () const; T & operator * (); const T & operator * () const; // Bad Mojo, looses all control over the pointer T * data () const; virtual void flush () { rep->flush(); } }; // // The following classes allow casts up to one or two base handles. This // scheme only allows for single and double base classes. For the single // base class case Use it like this: // // // class Base {}; // class Derived : public Base {}; // ... // DHandle derived; // Handle base = derived; // // Note: the D2Handle can be used for mulitple inheritance or a single // inheritance tree of two base classes to which to cast. // template class DHandle : public Handle { public: DHandle () : Handle () {} DHandle (D *to) : Handle (to) {} DHandle (const Handle &to) : Handle (to) {} operator const Handle () const { return * (Handle *) this; } }; template class D2Handle : public DHandle { public: D2Handle () : DHandle () {} D2Handle (D *to) : DHandle (to) {} operator const Handle () const { return * (Handle *) this; } }; #endif