loose_ptr<T> code
Page 1 of 1

Author:  AcidFaucet [ 08.11.2011, 01:37 ]
Post subject:  loose_ptr<T> code

In my opinion weak_ptr is one of the best parts about shared_ptr.

I didn't want to start adding shared_ptr's in but didn't want to have some insane management going on either so I whipped together this invasive guy so I could get loose_ptr<T> from anyone who inherits from enable_loose_ptr.

Then my manager just had to to periodically prune the ones that had gone bad while it was checking to see if it still cared about the good ones.

So I thought I'd share. If you read up on weak_ptr and enabled_shared_from_this<T> you should be able to get how it works pretty easily (unlike weak_ptr this will work with variables on the stack too).

#pragma once
// Copyright (C) 2011 - Jonathan Sandusky
// MIT License - read it here http://www.opensource.org/licenses/mit-license.php

// an invasive pointer that gets reset when the target object is destroyed
// (polymorphism is not supported here)
template<class TYPE> class loose_ptr {
    loose_ptr<TYPE>& operator=(int);  // prevent "obj=0;" because it doesn't work right
    TYPE* ptr_;
    loose_ptr* next_;
    // default constructor
    loose_ptr() : ptr_(0), next_(0) {}
    // construct from dumb pointer
    loose_ptr(TYPE* p) : ptr_(0), next_(0) {set(p);}
    // construct from derived class dumb pointer
    template<class T> loose_ptr(T* p) : ptr_(0), next_(0) {set(p);}
    // construct from smart_ptr, shared_ptr, etc.
    template<class T> loose_ptr(const T& t) : ptr_(0), next_(0) {set(t.get());}
    // copy constructor (specialization of above)
    loose_ptr(const loose_ptr& rhs) : ptr_(0), next_(0) {set(rhs.ptr_);}
    // destructor
    ~loose_ptr() {set(0);}

    TYPE* ptr() const {return ptr_;}
    TYPE* get() const {return ptr_;}
    TYPE* operator->() const {assert(ptr_); return ptr_;}
    TYPE& operator*() const {assert(ptr_); return *ptr_;}

    bool operator==(TYPE* p) const {return p == ptr_;}
    bool operator!=(TYPE* p) const {return p != ptr_;}

    bool expired() const {return !ptr_;}

    class incomplete_class;
    operator const incomplete_class*() const {return (const incomplete_class*)ptr_;}

    // assign from dumb pointer
    loose_ptr& operator=(TYPE* p) {set(p); return *this;}
    // assign from smart_ptr, shared_ptr, etc.
    template<class T> loose_ptr& operator=(const T& t) {set(t.get()); return *this;}
    // assignment operator (specialization of above)
    loose_ptr& operator=(const loose_ptr& rhs) {set(rhs.ptr_); return *this;}

    void reset(TYPE* aPtr = 0) {set(aPtr);}
    void set(TYPE* aPtr)
        if (aPtr != ptr_) {
            const enable_loose_ptr<TYPE>* ptr = ptr_;
            if (ptr != 0) {
                if (ptr->loose_ptr_head_ == this) {
                    ptr->loose_ptr_head_ = next_;
                } else {
                    loose_ptr* prev = 0;
                    for (loose_ptr* p = ptr->loose_ptr_head_; p && p != this; prev = p, p = p->next_);
                    assert(prev && prev->next_ == this);
                    if (prev && prev->next_ == this)
                        prev->next_ = next_;
                next_ = 0;
            ptr = ptr_ = aPtr;
            if (ptr_) {
                next_ = ptr->loose_ptr_head_;
                ptr->loose_ptr_head_ = this;

// required base class for objects that can have loose pointers to them
template<class TYPE> class enable_loose_ptr {
    // default constructor
    enable_loose_ptr() : loose_ptr_head_(0)
    // copy constructor
    enable_loose_ptr(const enable_loose_ptr&) : loose_ptr_head_(0)
    // destructor
        while (loose_ptr_head_)
    // assignment operator
    enable_loose_ptr& operator=(const enable_loose_ptr&)
    friend class loose_ptr<TYPE>;
    mutable loose_ptr<TYPE>* loose_ptr_head_;

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB® Forum Software © phpBB Group