#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 *val = nullptr): core(val == nullptr ? nullptr :new Core(val, 1)) {} SmartPointer(const SmartPointer &val) { core = val.core; if (core != nullptr) core->ptr_count++; } SmartPointer(SmartPointer &&val) { core = val.core; val.core = nullptr; } SmartPointer &operator=(const SmartPointer &val) { if (core != nullptr) { core->ptr_count--; if (core->ptr_count == 0) { delete core->ptr; delete core; } } core = val.core; if (core != nullptr) core->ptr_count++; return *this; } SmartPointer &operator=(SmartPointer &&val) { if (core != nullptr) { core->ptr_count--; if (core->ptr_count == 0) { delete core->ptr; delete core; } } core = val.core; val.core = nullptr; return *this; } SmartPointer &operator=(value_type *val) { if (core != nullptr) { core->ptr_count--; if (core->ptr_count == 0) { delete core->ptr; delete core; } } if (val == nullptr) { core = nullptr; return *this; } core = new Core(val, 1); return *this; } ~SmartPointer() { if (core != nullptr) { core->ptr_count--; if (core->ptr_count == 0) { delete core->ptr; delete core; } } } value_type &operator*() { if (core == nullptr || core->ptr == nullptr) throw smart_pointer::exception(); return *(core->ptr); } const value_type &operator*() const { if (core == nullptr || core->ptr == nullptr) throw smart_pointer::exception(); return *(core->ptr); } value_type *operator->() const { if (core != nullptr) return core->ptr; return nullptr; } value_type *get() const { if (core != nullptr) return core->ptr; return nullptr; } operator bool() const { if (core == nullptr) return false; return core->ptr != nullptr; } template bool operator==(const SmartPointer &val) const { bool exp1, exp2; exp1 = get() == nullptr && val.get() == nullptr; exp2 = static_cast(get()) == static_cast(val.get()); return exp1 || exp2; } template bool operator!=(const SmartPointer &val) const { bool exp1, exp2; exp1 = get() == nullptr && val.get() == nullptr; exp2 = static_cast(get()) == static_cast(val.get()); return !(exp1 || exp2); } std::size_t count_owners() const { if (core != nullptr) return core->ptr_count; return 0; } private: class Core { public: Core(value_type *val, size_t count) : ptr(val), ptr_count(count) {} value_type *ptr; size_t ptr_count; }; Core *core; }; } // namespace smart_pointer