#include #include "Test.hpp" #ifndef SMARTPOINTER_HPP #define SMARTPOINTER_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) { core->count++; } } SmartPointer(SmartPointer&& other) { core = other.core; other.core = nullptr; } SmartPointer& operator=(const SmartPointer& other) { if (core != nullptr) { core->count--; if (core->count == 0) { delete (core); } } core = other.core; if (other.core) { core->count++; } return *this; } SmartPointer& operator=(SmartPointer&& other) { if (core != nullptr) { core->count--; if (core->count == 0) { delete (core); } } this->core = other.core; other.core = nullptr; return *this; } SmartPointer& operator=(value_type* p) { if (core != nullptr) { core->count--; if (core->count == 0) { delete (core); } } if (p != nullptr) { core = new Core(p); } else { core = nullptr; } return *this; } ~SmartPointer() { if (core != nullptr) { core->count--; if (core->count == 0) { delete (core); } } } value_type& operator*() { if (core != nullptr) return *(core->ptr); throw smart_pointer::exception(); } const value_type& operator*() const { if (core != nullptr) return *(core->ptr); throw smart_pointer::exception(); } 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 { 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* ptr; size_t count; explicit Core(value_type* p) : ptr(p), count(1) {} ~Core() { Allocator a; a.deallocate(ptr, sizeof(value_type)); ptr = nullptr; } }; Core* core; }; } // namespace smart_pointer #endif