owning_ptr.cpp (1493B)
1 #include <memory> 2 #include <cassert> 3 #include <iostream> 4 #include <set> 5 6 using namespace std; 7 8 template <typename T> 9 struct owning_ptr : shared_ptr<T> 10 { 11 owning_ptr() = default; 12 explicit owning_ptr(shared_ptr<T> p) 13 : shared_ptr<T>(move(p)) 14 { 15 assert(this->use_count() <= 1); 16 } 17 ~owning_ptr() 18 { 19 if (*this) 20 (*this)->pre_destroy(); 21 if (auto n = this->use_count(); n > 1) 22 { 23 cerr << "owning_ptr not outliving " << n - 1 << " references\n"; 24 terminate(); 25 } 26 } 27 owning_ptr(owning_ptr const&) = delete; 28 owning_ptr& operator =(owning_ptr const&) = delete; 29 owning_ptr(owning_ptr&&) = default; 30 owning_ptr& operator =(owning_ptr&&) = default; 31 }; 32 33 struct node : enable_shared_from_this<node> 34 { 35 set<shared_ptr<node>> others = {}; 36 37 void pre_destroy() 38 { 39 for (auto& o : others) 40 o->others.erase(shared_from_this()); 41 } 42 43 [[nodiscard]] static owning_ptr<node> construct() 44 { 45 return owning_ptr{shared_ptr<node>{new node{}}}; 46 } 47 48 ~node() 49 { 50 cout << "~node(): " << others.size() << endl; 51 } 52 53 private: 54 node() = default; 55 }; 56 57 void join(node& a, node& b) 58 { 59 a.others.insert(b.shared_from_this()); 60 b.others.insert(a.shared_from_this()); 61 } 62 63 set<owning_ptr<node>> nodes; 64 65 int main() 66 { 67 nodes.insert(node::construct()); 68 auto p1 = node::construct(); 69 auto q1 = node::construct(); 70 auto r1 = node::construct(); 71 join(*p1, *q1); 72 join(*p1, *r1); 73 join(*q1, *r1); 74 75 join(*p1, *p1); 76 77 shared_ptr<node> p2 = p1; 78 weak_ptr<node> p3 = p1; 79 80 owning_ptr<node> p4 = move(p1); 81 p2.reset(); 82 }