#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* ptr = nullptr) { if (ptr == nullptr) { this->core = nullptr; } else { this->core = new Core(); this->core->ptr = ptr; this->core->count = 1; } } ~SmartPointer() { if (this->core != nullptr && this->core->count == 1) { delete this->core; } } SmartPointer(const SmartPointer& obj) { this->core = obj.core; if (obj.core != nullptr) { this->core->count++; } } SmartPointer(SmartPointer&& dyingObj) { this->core = dyingObj.core; dyingObj.core = nullptr; } SmartPointer& operator=(const SmartPointer& other) { if (this->core != nullptr && this->core->count == 1) { delete this->core; } this->core = other.core; if (other.core != nullptr) { this->core->count++; } return *this; } SmartPointer& operator=(SmartPointer&& dyingObj) { if (this->core != nullptr) { delete this->core; } this->core = dyingObj.core; dyingObj.core = nullptr; return *this; } SmartPointer& operator=(value_type* other) { if (this->core != nullptr && this->core->count == 1) { delete this->core; } if (other != nullptr) { this->core = new Core(); this->core->ptr = other; this->core->count = 1; } else { this->core = nullptr; } return *this; } value_type& operator*() { if (this->core == nullptr) { throw smart_pointer::exception(); } else { return *this->core->ptr; } } const value_type& operator*() const { if (this->core == nullptr) { throw smart_pointer::exception(); } else { return *this->core->ptr; } } value_type* operator->() const { if (this->core != nullptr) { return this->core->ptr; } else { return nullptr; } } value_type* get() const { if (this->core != nullptr) { return this->core->ptr; } else { return nullptr; } } operator bool() const { return this->core != nullptr; } 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* ptr; ~Core() { Allocator del; del.deallocate(ptr, sizeof(value_type)); this->ptr = nullptr; } }; Core* core; }; } // namespace smart_pointer