#pragma once #include #include #include "Test.hpp" namespace smart_pointer { class exception : std::exception { using base_class = std::exception; using base_class::base_class; }; // `SmartPointer` class declaration template class SmartPointer { // don't remove this macro ENABLE_CLASS_TESTS; public: using value_type = T; explicit SmartPointer(value_type *value = nullptr) { if (value) core = new Core(value); else core = nullptr; } // copy constructor SmartPointer(const SmartPointer &test) { core = test.core; if (*this){ core->count++; } } // move constructor SmartPointer(SmartPointer &&test) { core = test.core; test.core = nullptr; } // copy assigment SmartPointer &operator=(const SmartPointer &test) { core = test.core; if (*this) { core->count++; } return *this; } // move assigment SmartPointer &operator=(SmartPointer &&test) { core = test.core; test.core = nullptr; return *this; } // SmartPointer &operator=(value_type *test) { if (test){ core = new Core(test); } else{ core = nullptr; } return *this; } ~SmartPointer() { if (*this) { core->count--; if (core->count == 0) delete core; } } // return reference to the object of class/type T // if SmartPointer contains nullptr throw `SmartPointer::exception` value_type &operator*() { if (!*this){ throw smart_pointer::exception(); } return *(core->ptr); } const value_type &operator*() const { if (!*this) { throw smart_pointer::exception(); } return *(core->ptr); } // return pointer to the object of class/type T value_type *operator->() const { if (*this){ return core->ptr; } return nullptr; } value_type *get() const { if (*this) return core->ptr; return nullptr; } // if pointer == nullptr => return false operator bool() const { if(core == nullptr || core->ptr == nullptr) { return false; } else { return true; } } // if pointers points to the same address or both null => true template bool operator==(const SmartPointer &test) const { if (!*this && !test) return true; if (!std::is_same::value) return false; return reinterpret_cast(get()) == reinterpret_cast(test.get()); } // if pointers points to the same address or both null => false template bool operator!=(const SmartPointer &test) const { if (!*this && !test) return false; if (!std::is_same::value) return true; return reinterpret_cast(get()) != reinterpret_cast(test.get()); } // if smart pointer contains non-nullptr => return count owners // if smart pointer contains nullptr => return 0 std::size_t count_owners() const { if (*this) return core->count; return 0; } private: class Core { public: explicit Core(value_type *value) { this->ptr = value; this->count = 1; } value_type *ptr; std::size_t count; }; Core *core; }; }