type-erased-unique_ptr.cpp (1511B)
1 #include <utility> 2 #include <iostream> 3 4 template <typename T = void> 5 struct unique_ptr 6 { 7 unique_ptr() = default; 8 explicit unique_ptr(T* p) 9 : p(p) 10 {} 11 ~unique_ptr() { if (p) delete p; } 12 unique_ptr(unique_ptr&& old) 13 : p{std::exchange(old.p, nullptr)} 14 {} 15 unique_ptr& operator =(unique_ptr&& old) 16 { 17 if (p) 18 delete p; 19 p = std::exchange(old.p, nullptr); 20 return *this; 21 } 22 private: 23 T* p = nullptr; 24 25 friend struct unique_ptr<void>; 26 }; 27 28 template<> 29 struct unique_ptr<void> 30 { 31 unique_ptr() = default; 32 33 ~unique_ptr() 34 { 35 if (p) 36 d(p); 37 } 38 39 unique_ptr(unique_ptr&& old) 40 : p{std::exchange(old.p, nullptr)} 41 , d{std::exchange(old.d, nullptr)} 42 {} 43 44 unique_ptr& operator =(unique_ptr&& old) 45 { 46 if (p) 47 d(p); 48 p = std::exchange(old.p, nullptr); 49 d = std::exchange(old.d, nullptr); 50 return *this; 51 } 52 53 template <typename T> 54 unique_ptr(unique_ptr<T>&& old) 55 : p{std::exchange(old.p, nullptr)} 56 , d{[](void* x) { delete (T*)x; }} 57 {} 58 59 private: 60 void* p = nullptr; 61 void (*d)(void*) = nullptr; 62 }; 63 64 struct sentry 65 { 66 sentry() { std::cout << __PRETTY_FUNCTION__ << std::endl; } 67 ~sentry() { std::cout << __PRETTY_FUNCTION__ << std::endl; } 68 }; 69 70 int main() 71 { 72 unique_ptr<> s2; 73 { 74 unique_ptr<sentry> s1{new sentry}; 75 s2 = std::move(s1); 76 std::cout << "~s1\n"; 77 } 78 std::cout << "~s2\n"; 79 }