#include #include "Test.hpp" class exception : std::exception { using base_class = std::exception; using base_class::base_class; }; template class SmartPointer { public: ENABLE_CLASS_TESTS; using value_type = T; explicit SmartPointer(value_type *p = nullptr) { if (p == nullptr) core = nullptr; else { core = &Core(p); core->AddRef(); } } SmartPointer(const SmartPointer &optr) : core(optr.core) { core->AddRef(); } SmartPointer(SmartPointer &&) = default; SmartPointer &operator=(const SmartPointer &) = default; SmartPointer &operator=(SmartPointer &&sp) { if (this != &sp) { if (core->Release() == 0) { delete core; } core = sp.core; core->AddRef(); } return *this; } SmartPointer &operator=(value_type *other) { core->p = other; core->AddRef(); return *this; } ~SmartPointer() { if (core->Release() == 0) delete core; } value_type &operator*() { if (core->p == nullptr) throw exception(); return *core->p; } const value_type &operator*() const { if (core->p == nullptr) throw exception(); auto const f = *core->p; return f; } value_type *operator->() const { return core->p; } value_type *get() const { return core->p; } operator bool() const { return core->p != nullptr; } template bool operator == (const SmartPointer &pp) const { return static_cast(core->p) == static_cast(pp.core->p); } template bool operator != (const SmartPointer &other) const { return static_cast(other.core->p) != static_cast(core->p); } std::size_t count_owners() const { if (core->p == nullptr) return 0; return core->c; } public: class Core { public: value_type *p; size_t c; explicit Core(value_type *_p = nullptr) : p(_p), c(0) {} void AddRef() { ++c; } int Release() { return --c; } ~Core() { if (p != nullptr) delete p; } }; Core *core; };