#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) { this->core = nullptr; } else { this->core = new Core(); core->p = p; core->count = 1; } } SmartPointer(const SmartPointer& other) { this->core = other.core; if (other.core) core->count++; } SmartPointer(SmartPointer&& other) { this->core = other.core; other = nullptr; } SmartPointer& operator=(const SmartPointer& other) { if (core != nullptr) { core->count--; if (core->count == 0) { delete (core); } } this->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) { this->core = new Core(); core->p = p; core->count = 1; } else { this->core = nullptr; } return *this; } ~SmartPointer() { if (core != nullptr) { core->count--; 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; size_t count; ~Core() { Allocator a; a.deallocate(p, sizeof(value_type)); p = nullptr; } }; Core* core; }; } // namespace smart_pointer #endif