#pragma once #include #include "Test.hpp" namespace smart_pointer { // `exception` class definition 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 *pointer = nullptr) { if (pointer) { // this->core = new Core; this->core = std::make_shared(); this->core->smart_pointer = this; // this->core->scratch = this->core; this->core->pointer = pointer; this->core->sum_pointers = 1; } else { this->core = nullptr; } } // copy constructor SmartPointer(const SmartPointer &smart_p) { if (smart_p.core) { ++(smart_p.core->sum_pointers); this->core = smart_p.core; // this->core->scratch = this->core; } else { this->core = nullptr; } } // move constructor SmartPointer(SmartPointer &&smart_p) noexcept { if (smart_p.core) { this->core = smart_p.core; // this->core->scratch = this->core; smart_p.core = nullptr; } else { this->core = nullptr; } } // copy assigment SmartPointer &operator=(const SmartPointer &smart_p) { if (smart_p.core) { ++(smart_p.core->sum_pointers); this->core = smart_p.core; // this->core->scratch = this->core; } else { this->core = nullptr; } return *this; } // move assigment SmartPointer &operator=(SmartPointer &&smart_p) noexcept { if (smart_p.core) { // this->core = new Core; this->core = std::make_shared(); this->core->smart_pointer = this; // this->core->scratch = this->core; this->core->pointer = smart_p.core->pointer; this->core->sum_pointers = smart_p.core->sum_pointers; } else { this->core = nullptr; } smart_p.core = nullptr; return *this; } SmartPointer &operator=(value_type *pointer) { if (pointer) { // this->core = new Core; this->core = std::make_shared(); this->core->smart_pointer = this; // this->core->scratch = this->core; this->core->sum_pointers = 1; this->core->pointer = pointer; } else { this->core = nullptr; } return *this; } ~SmartPointer() { /* if (core) { core->sum_pointers--; // delete core; } */ // delete this; } // return reference to the object of class/type T // if SmartPointer contains nullptr throw `SmartPointer::exception` value_type &operator*() { if (!this->core) { throw smart_pointer::exception(); } return *this->core->pointer; } const value_type &operator*() const { if (!this->core) { throw smart_pointer::exception(); } return *this->core->pointer; } // return pointer to the object of class/type T value_type *operator->() const { return (this->core) ? this->core->pointer : nullptr; } value_type *get() const { if (this->core) { return this->core->pointer; } return nullptr; } // if pointer == nullptr => return false explicit operator bool() const { return this->core != nullptr; } // if pointers points to the same address or both null => true template bool operator==(const SmartPointer &smart_p) const { if (!smart_p.get() && !this->get()) { return true; } return static_cast(smart_p.get()) == static_cast(this->get()); } // if pointers points to the same address or both null => false template bool operator!=(const SmartPointer &smart_p) const { if (!smart_p.get() && !this->get()) { return false; } return static_cast(smart_p.get()) != static_cast(this->get()); } // if smart pointer contains non-nullptr => return count owners // if smart pointer contains nullptr => return 0 [[nodiscard]] std::size_t count_owners() const { return (this->core) ? this->core->sum_pointers : 0; } private: class Core { public: value_type *pointer; size_t sum_pointers; SmartPointer *smart_pointer; // Core *scratch; ~Core() { // delete pointer; // delete scratch; } }; std::shared_ptr core; // Core *core; }; } // namespace smart_pointer