#include using namespace std; template struct Rc { private: T* ptr{nullptr}; unsigned int* refcount{nullptr}; int* weakcount{nullptr}; Rc(T* n) : ptr{n} { refcount = new unsigned int(1); weakcount = new int(0); } void deallocate() { (*refcount)--; if (*refcount==0) { delete ptr; delete refcount; if (*weakcount == 0) delete weakcount; else *weakcount = -1 * *weakcount; } } public: Rc() {} ~Rc() { if (refcount) deallocate(); } void drop() { if (refcount) { deallocate(); refcount = nullptr; ptr = nullptr; weakcount = nullptr; } } T& operator *() { return *ptr; } T* operator ->() { return ptr; } template Rc(const Rc& other) { ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; if (refcount) (*refcount)++; } template const Rc& operator =(const Rc& other) { if (this == (Rc*)&other) return *this; if (refcount) deallocate(); ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; if (refcount) (*refcount)++; return *this; } template Rc(Rc&& other) { ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; other.ptr = nullptr; other.refcount = nullptr; other.weakcount = nullptr; } template void operator =(Rc&& other) { if (this == (Rc*)&other) return; if (refcount) deallocate(); ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; other.ptr = nullptr; other.refcount = nullptr; other.weakcount = nullptr; } unsigned int use_count() { if (refcount) return *refcount; else return 0; } template static Rc New(Args&&... args) { return Rc(new T(forward(args)...)); } template friend struct Weak; template friend struct Rc; }; // Rc template struct Weak { private: T* ptr{nullptr}; unsigned int* refcount{nullptr}; int* weakcount{nullptr}; void deallocate() { if (weakcount) { if (*weakcount>0) (*weakcount)--; else if (*weakcount < -1) (*weakcount)++; else delete weakcount; } } public: Weak() {} ~Weak() { deallocate(); } void drop() { deallocate(); weakcount=nullptr; } Weak(Rc& other) { if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Rc"; ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; } void operator =(Rc& other) { if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Rc"; deallocate(); ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; } Weak(const Weak& other) { if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Weak pointer"; ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; } const Weak& operator =(const Weak& other) { if (this == &other) return other; if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Weak pointer"; deallocate(); ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; return other; } Rc lock() { if (weakcount && *weakcount>0) { Rc rc; rc.ptr = ptr; rc.refcount = refcount; rc.weakcount = weakcount; (*refcount)++; return rc; } else throw "lock on invalidated Rc"; } int weak_count() { if (weakcount) return *weakcount; else return 0; } }; struct A { virtual int f() = 0; }; struct B : public A { int f() override { return 1; } }; struct C : public A { int f() override { return 2; } }; void doesitleak() { Rc a = Rc::New(3); Weak w1 = a; Weak w2 = a; Rc b = move(a); //b.drop(); //cout << w2.weak_count() << endl; //w2.drop(); //cout << w1.weak_count() << endl; //w1.drop(); //*w1.lock() = 5; //cout << *w2.lock() << endl; Weak w3 = w2; Rc n; n = Rc::New(); } int main() { doesitleak(); //while (true) doesitleak(); return 0; }