#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* value = nullptr) { if (value == nullptr) { this->core = nullptr; } else { this->core = new Core(); this->core->pointer = value; this->core->count = 1; } } SmartPointer(const SmartPointer & obj) { this->core = obj.core; if (obj.core != nullptr) { this->core->count++; } } SmartPointer(SmartPointer && obj) { this->core = obj.core; obj.core = nullptr; } SmartPointer &operator=(const SmartPointer & obj) { if (this->core != nullptr) { this->core->count--; if(this->core->count == 0) { delete this->core; } } this->core = obj.core; if (obj.core != nullptr) { this->core->count++; } return *this; } SmartPointer &operator=(SmartPointer && obj) { if (this->core != nullptr) { this->core->count--; if(this->core->count == 0) { delete this->core; } } this->core = obj.core; obj.core = nullptr; return *this; } SmartPointer &operator=(value_type *obj) { if (this->core != nullptr) { this->core->count--; if(this->core->count == 0) { delete this->core; } } if (obj != nullptr) { this->core = new Core(); this->core->pointer = obj; this->core->count = 1; } else { this->core = nullptr; } return *this; } } ~SmartPointer() { if (this->core != nullptr) { this->core->count--; if(this->core->count == 0) { delete this->core; } } } value_type &operator*() { if(this->core == nullptr) { throw smart_pointer::exception(); } else { return *(this->core->pointer); } } const value_type &operator*() const { if(this->core == nullptr) { throw smart_pointer::exception(); } else { return *(this->core->pointer); } } value_type *operator->() const { if (this->core == nullptr) { return nullptr; } else { return this->core->pointer; } } value_type *get() const { if (this->core == nullptr) { return nullptr; } else { return this->core->pointer; } } operator bool() const { if(this->core->pointer == nullptr) { return false; } else { return true; } } template bool operator==(const SmartPointer & ptr) const { return static_cast(this->get()) == static_cast(ptr.get()); } template bool operator!=(const SmartPointer & ptr) const { return static_cast(this->get()) == static_cast(ptr.get()); } std::size_t count_owners() const { if (this->core != nullptr) { return this->core->count; } else { return 0; } } private: class Core { public: size_t count; value_type* pointer; ~Core() { Allocator allocator; allocator.deallocate(pointer, sizeof(value_type)); this->pointer = nullptr; } }; Core *core; }; // namespace smart_pointer }