#ifndef BIDI_SMART_POINTER_H #define BIDI_SMART_POINTER_H #include template class bidi_ptr { typedef bidi_ptr this_type; typedef bidi_ptr complement_type; // not default-constructible bidi_ptr(); public: /** you always have to init a bidi-pointer with the owning object, i.e. this. */ bidi_ptr(ThisType* owner):m_owner(owner),m_peer(0) { assert(m_owner);} /** connect two pointers Note: - 'p1 = p2' as the same postcondition as 'p2 = p1' - return-type is void because expressions like 'p1=p2=p3' make no sense - the other pointer is taken by non-const reference */ void operator=(bidi_ptr& other) { if(m_peer!=&other) { other.reset(); reset(); m_peer = &other; other.m_peer = this; } } // friend class bidi_ptr; ~bidi_ptr() { reset(); } void reset() { if(m_peer) m_peer->m_peer = 0; m_peer = 0; } typedef bool (this_type::*safe_bool)() const; operator safe_bool() const { return m_peer?&this_type::operator!:0; } bool operator!()const { return m_peer == 0; } OtherType* get() const { assert_valid(); return m_peer?m_peer->m_owner:0; } OtherType* operator->() const { return get(); } OtherType& operator*() const { return *get(); } // private: // - must have owner // - if connected, peer must be connected to this void assert_valid() const { assert(m_owner); if(m_peer) assert(this == m_peer->m_peer); } ThisType*const m_owner; bidi_ptr* m_peer; }; template void connect(bidi_ptr& p1, bidi_ptr& p2) { p1 = p2; } #endif