// // Created by Lenovo on 16.11.2021. // #ifndef SMARTPOINTER_HPP #define SMARTPOINTER_HPP #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 *x = nullptr) { if (x == nullptr) { this->core = nullptr; } else { this->core = new Core(); core->info = x; core->cnt = 1; } } SmartPointer(const SmartPointer &x) { this->core = x.core; if (x.core != nullptr) { core->cnt++; } } SmartPointer(SmartPointer &&x) { this->core = x.core; x.core = nullptr; } SmartPointer &operator=(const SmartPointer &x) { remove(); this->core = x.core; if (x.core != nullptr) { core->cnt++; } return *this; } SmartPointer &operator=(SmartPointer &&x) { remove(); this->core = x.core; x.core = nullptr; return *this; } SmartPointer &operator=(value_type *x) { remove(); if (x != nullptr) { this->core = new Core(); core->info = x; core->cnt = 1; } else { this->core = nullptr; } return *this; } void remove() { if (core != nullptr) { core->cnt -= 1; if (core->cnt == 0) { delete (core); } } } ~SmartPointer() { remove(); } value_type &operator*() { if (core == nullptr) { throw smart_pointer::exception(); } else { return *(core->info); } } const value_type &operator*() const { if (core == nullptr) { throw smart_pointer::exception(); } else { return *(core->info); } } value_type *operator->() const { if (core == nullptr) { return nullptr; } else { return core->info; } } value_type *get() const { if (core == nullptr) { return nullptr; } else { return core->info; } } operator bool() const { return core != nullptr; } template bool operator==(const SmartPointer &pointer) const { return static_cast(this->get()) == static_cast(pointer.get()); } template bool operator!=(const SmartPointer &pointer) const { return static_cast(this->get()) != static_cast(pointer.get()); } std::size_t count_owners() const { if (core != nullptr) { return core->cnt; } else { return 0; } } private: class Core { public: size_t cnt; value_type *info; ~Core() { Allocator allocator; allocator.deallocate(info, sizeof(value_type)); info = nullptr; } }; Core *core; }; } #endif