#pragma once #include #include "Test.hpp" namespace smart_pointer { class exception : std::exception { using base_class = std::exception; using base_class::base_class; }; template class SmartPointer { ENABLE_CLASS_TESTS; public: using value_type = T; explicit SmartPointer(value_type* value = nullptr) { if (value != nullptr) { core = new Core(value); core->countRefer++; } else { core = nullptr; } } SmartPointer(const SmartPointer& other) { core = other.core; if (core != nullptr) { core->countRefer++; } } SmartPointer(SmartPointer&& other) noexcept(false) { core = other.core; other.core = nullptr; } SmartPointer& operator=(const SmartPointer& other) { if (core != nullptr) { if (core->countRefer > 1) { core->countRefer--; } else { delete (core); } } core = other.core; if (core != nullptr) { core->countRefer++; } return *this; } SmartPointer& operator=(SmartPointer&& other) noexcept(false) { core = other.core; delete other.core->value; other.core = nullptr; return *this; } SmartPointer& operator=(value_type*other) { if (core != nullptr) { if (core->countRefer > 1) { core->countRefer--; } else { delete (core); } } if (other != nullptr) { core = new Core(other); } else { core = nullptr; } return *this; } ~SmartPointer() { if (core != nullptr) { core = nullptr; } } value_type& operator*() { if (core == nullptr) { throw smart_pointer::exception(); } return *core->value; } const value_type& operator*() const { if (core == nullptr) { throw smart_pointer::exception(); } return *core->value; } value_type* operator->() const { if (core == nullptr) { return nullptr; } return core->value; } value_type* get() const { if (core == nullptr) { return nullptr; } return core->value; } operator bool() const { return (core != nullptr); } template bool operator==(const SmartPointer& other) const { if (core != nullptr) { return (core->value == reinterpret_cast(other.get())); } else { return (other.core == nullptr); } } template bool operator!=(const SmartPointer&other) const { return !(*this == other); } std::size_t count_owners() const { if (core == nullptr) return 0; return core->countRefer; } class Core { public: explicit Core(value_type* value) : value(value) {} size_t countRefer = 0; value_type* value; }; Core* core; }; } // namespace smart_pointer