#pragma once #include #include "Test.hpp" namespace smart_pointer { // `exception` class definition class exception : std::exception { using base_class = std::exception; using base_class::base_class; }; // `SmartPointer` class declaration template class SmartPointer { // don't remove this macro ENABLE_CLASS_TESTS; public: using value_type = T; // constructor explicit SmartPointer(value_type* p = nullptr) : core(new Core(p)) { core->AddRef(); } // copy constructor SmartPointer(const SmartPointer& optr) : core(optr.core) { core->AddRef(); } // move constructor SmartPointer(SmartPointer&&) = default; // copy assigment SmartPointer& operator=(const SmartPointer&) = default; // move assigment 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; } // return reference to the object of class/type T // if SmartPointer contains nullptr throw `SmartPointer::exception` value_type& operator*() { if (core->p == nullptr) throw exception(); return *core->p; } const value_type& operator*() const { if (core->p == nullptr) throw exception(); return *core->p; } // return pointer to the object of class/type T value_type* operator->() const { return core->p; } value_type* get() const { return core->p; } // if pointer == nullptr => return false operator bool() const { return core->p != nullptr; } // if pointers points to the same address or both null => true template bool operator==(const SmartPointer& pp) const { return static_cast(core->p) == static_cast(pp.core->p); } // if pointers points to the same address or both null => false template bool operator!=(const SmartPointer& other) const { return static_cast(other.core->p) != static_cast(core->p); } // if smart pointer contains non-nullptr => return count owners // if smart pointer contains nullptr => return 0 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; }; } // namespace smart_pointer