#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 < typename T, typename Allocator > class SmartPointer { // don't remove this macro ENABLE_CLASS_TESTS; public: using value_type = T; explicit SmartPointer(value_type* x = nullptr) { if (x != nullptr) { core = new Core(x); core->c++; } else { core = nullptr; } } // copy constructor SmartPointer(const SmartPointer& other) { core = other.core; if (core != nullptr) { core->c++; } } // move constructor SmartPointer(SmartPointer&& other) noexcept { core = other.core; other.core = nullptr; } // copy assigment SmartPointer &operator=(const SmartPointer& other) { if (core != nullptr) { if (core->c > 1) { core->c--; } else { delete (core); } } core = other.core; if (core != nullptr) { other.core->c++; } return *this; } // move assigment SmartPointer &operator=(SmartPointer&& other) { core = other.core; delete other.core->p; other.core = nullptr; return *this; } // SmartPointer &operator=(value_type* other) { if (core != nullptr) { if (core->c > 1) { core->c--; } else { delete (core); } } if (other != nullptr) { core = new Core(other); } else { core = nullptr; } return *this; } ~SmartPointer() { if (core != nullptr) { core = nullptr; } } // return reference to the object of class/type T // if SmartPointer contains nullptr throw `SmartPointer::exception` value_type& operator*() { if (core == nullptr) { throw smart_pointer::exception(); } return *core->p; } const value_type& operator*() const { if (core == nullptr) { throw smart_pointer::exception(); } return *core->p; } // return pointer to the object of class/type T value_type* operator->() const { if (core != nullptr) { return core->p; } return nullptr; } value_type* get() const { if (core != nullptr) { return core->p; } return nullptr; } // if pointer == nullptr => return false explicit operator bool() const { return (core != nullptr); } // if pointers points to the same address or both null => true template bool operator==(const SmartPointer& other) const { if (core != nullptr) { return (core->p == reinterpret_cast(other.get())); } else { return (other.get() == nullptr); } } // if pointers points to the same address or both null => false template bool operator!=(const SmartPointer& other) const { return !(*this == other); } // if smart pointer contains non-nullptr => return count owners // if smart pointer contains nullptr => return 0 std::size_t count_owners() const { if (core == nullptr) { return 0; } return core->c; } private: class Core { public: explicit Core(value_type* x) : p(x) {} size_t c = 0; value_type* p; }; Core* core; }; }