#pragma once #include #include "Test.hpp" namespace smart_pointer { class exception : std::exception { using base_class = std::exception; using base_class::base_class; }; template< typename T, typename Allocator > class SmartPointer { ENABLE_CLASS_TESTS; public: using value_type = T; explicit SmartPointer(value_type* p = nullptr) { if (p == nullptr) { core = nullptr; } else { core = new Core(p); } } SmartPointer(const SmartPointer& other) : core(other.core) { if (other.core != nullptr) core->count++; } SmartPointer(SmartPointer&& other) : core(other.core) { other = nullptr; } SmartPointer& operator=(const SmartPointer& other) { if (core != nullptr) { core->count -= 1; if (core->count == 0) { delete core; } } core = other.core; if (other.core != nullptr) { core->count++; } return *this; } SmartPointer& operator=(SmartPointer&& other) { if (core != nullptr) { core->count -= 1; if (core->count == 0) { delete core; } } core = other.core; other.core = nullptr; return *this; } SmartPointer& operator=(value_type* p) { if (core != nullptr) { core->count -= 1; if (core->count == 0) { delete core; } } if (p != nullptr) { core = new Core(p); } else { core = nullptr; } return *this; } ~SmartPointer() { if (core != nullptr) { core->count -= 1; if (core->count == 0) { delete core; } } } value_type& operator*() { if (core != nullptr) return *(core->p); throw smart_pointer::exception(); } const value_type& operator*() const { if (core != nullptr) return *(core->p); throw smart_pointer::exception(); } value_type* operator->() const { if (core != nullptr) return core->p; return nullptr; } value_type* get() const { if (core != nullptr) return core->p; return nullptr; } operator bool() const { return core != nullptr; } template bool operator==(const SmartPointer& other) const { return (reinterpret_cast(this->get()) == reinterpret_cast(other.get())); } template bool operator!=(const SmartPointer& other) const { return !(reinterpret_cast(this->get()) == reinterpret_cast(other.get())); } std::size_t count_owners() const { if (core == nullptr) return 0; return core->count; } private: class Core { public: value_type* p; std::size_t count; explicit Core(value_type* ptr) : p(ptr), count(1) {} ~Core() { Allocator a; a.deallocate(p, sizeof(value_type)); p = nullptr; } }; Core* core; }; } // namespace smart_pointer