// -*- mode: c++; c-basic-offset: 4 -*- #pragma rvalue_refs on // must turn language feature on #include #include struct RefCounter { RefCounter() : m_refcount(0) {} void ref() { ++m_refcount; } void deref() { if (!--m_refcount) delete this; } int m_refcount; }; template class PassRefPtr; template class PassRefPtr_ref; template class SharedPtr { public: SharedPtr() : m_ptr(0) {} SharedPtr(T *ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); } SharedPtr(const SharedPtr& o) : m_ptr(o.get()) { if (m_ptr) m_ptr->ref(); } SharedPtr(SharedPtr&& o) : m_ptr(o.get()) { o.m_ptr = 0; } SharedPtr(PassRefPtr& o) : m_ptr(o.release()) {} ~SharedPtr() { if (m_ptr) m_ptr->deref(); } template SharedPtr(const SharedPtr &o) : m_ptr(o.get()) { if (T *ptr = m_ptr) ptr->ref(); } template SharedPtr(PassRefPtr &o) : m_ptr(o.release()) { } // FIXME: Deprecate in favor of operators below, then remove? bool isNull() const { return m_ptr == 0; } bool notNull() const { return m_ptr != 0; } // FIXME: Deprecate in favor of operator=, then remove? void reset() { if (T *ptr = m_ptr) ptr->deref(); m_ptr = NULL; } void reset(T *o) { if (o) o->ref(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = o; } T *get() const { return m_ptr; } T &operator*() const { return *m_ptr; } T *operator->() const { return m_ptr; } bool operator!() const { return m_ptr == 0; } operator bool() const { return m_ptr != 0; } SharedPtr &operator=(const SharedPtr &); SharedPtr &operator=(T *); SharedPtr &operator=(SharedPtr&& o) { std::swap(m_ptr, o.m_ptr); return *this; } SharedPtr &operator=(PassRefPtr &o); SharedPtr(PassRefPtr_ref ref) : m_ptr(ref.m_ptr) { } SharedPtr& operator=(PassRefPtr_ref ref) { if (m_ptr) m_ptr->deref(); m_ptr = ref.m_ptr; return *this; } private: T *m_ptr; operator int() const; // deliberately not implemented; helps prevent operator bool from converting to int accidentally }; template inline SharedPtr &SharedPtr::operator=(const SharedPtr &o) { T *optr = o.m_ptr; if (optr) optr->ref(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = optr; return *this; } template inline SharedPtr &SharedPtr::operator=(PassRefPtr &o) { T *optr = o.release(); if (optr) optr->ref(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = optr; return *this; } template inline SharedPtr &SharedPtr::operator=(T *optr) { if (optr) optr->ref(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = optr; return *this; } template inline bool operator==(const SharedPtr &a, const SharedPtr &b) { return a.get() == b.get(); } template inline bool operator==(const SharedPtr &a, const T *b) { return a.get() == b; } template inline bool operator==(const T *a, const SharedPtr &b) { return a == b.get(); } template inline bool operator!=(const SharedPtr &a, const SharedPtr &b) { return a.get() != b.get(); } template inline bool operator!=(const SharedPtr &a, const T *b) { return a.get() != b; } template inline bool operator!=(const T *a, const SharedPtr &b) { return a != b.get(); } template inline SharedPtr static_pointer_cast(const SharedPtr &p) { return SharedPtr(static_cast(p.get())); } template inline SharedPtr const_pointer_cast(const SharedPtr &p) { return SharedPtr(const_cast(p.get())); } template struct PassRefPtr_ref { T* m_ptr; explicit PassRefPtr_ref(T* p) : m_ptr(p) {} }; template class PassRefPtr { public: PassRefPtr() : m_ptr(0) {} PassRefPtr(T *ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); } PassRefPtr(const SharedPtr &o) : m_ptr(o.get()) { if (T *ptr = m_ptr) ptr->ref(); } ~PassRefPtr() { if (T *ptr = m_ptr) ptr->deref(); } template PassRefPtr(const SharedPtr &o) : m_ptr(o.get()) { if (T *ptr = m_ptr) ptr->ref(); } template PassRefPtr(PassRefPtr &o) : m_ptr(o.release()) { } // FIXME: Deprecate in favor of operator=, then remove? void reset() { if (T *ptr = m_ptr) ptr->deref(); m_ptr = NULL; } void reset(T *o) { if (o) o->ref(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = o; } T *get() const { return m_ptr; } T *release() { T *tmp = m_ptr; m_ptr = 0; return tmp; } T &operator*() const { return *m_ptr; } T *operator->() const { return m_ptr; } bool operator!() const { return m_ptr == NULL; } operator bool() const { return m_ptr != NULL; } PassRefPtr &operator=(const SharedPtr &); PassRefPtr &operator=(PassRefPtr &); PassRefPtr &operator=(T *); PassRefPtr(PassRefPtr_ref ref) : m_ptr(ref.m_ptr) { } PassRefPtr& operator=(PassRefPtr_ref ref) { if (m_ptr) m_ptr->deref(); m_ptr = ref.m_ptr; return *this; } template operator PassRefPtr_ref() { return PassRefPtr_ref(release()); } template operator PassRefPtr() { return PassRefPtr(this->release()); } private: T *m_ptr; operator int() const; // deliberately not implemented; helps prevent operator bool from converting to int accidentally }; template inline PassRefPtr &PassRefPtr::operator=(const SharedPtr &o) { T *optr = o.get(); if (optr) optr->ref(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = optr; return *this; } template inline PassRefPtr &PassRefPtr::operator=(PassRefPtr &o) { T *optr = o.release(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = optr; return *this; } template inline PassRefPtr &PassRefPtr::operator=(T *optr) { if (optr) optr->ref(); if (T *ptr = m_ptr) ptr->deref(); m_ptr = optr; return *this; } class Acceptor { public: Acceptor(SharedPtr &&s) : m_s(std::move(s)){} SharedPtr m_s; }; SharedPtr getRefCounter(); inline SharedPtr getRefCounter() { return SharedPtr(new RefCounter); } int main() { for (int i = 0; i < 10000000; i++) { Acceptor a(getRefCounter()); } }