#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< typename T, typename Allocator > class SmartPointer { // don't remove this macro ENABLE_CLASS_TESTS; public: using value_type = T; explicit SmartPointer(value_type *ptr = nullptr) { if (ptr != nullptr) { core = new Core(ptr); } else { core = nullptr; } } // copy constructor SmartPointer(const SmartPointer &other) { core = other.core; if (core != nullptr) { core->count_++; } } // move constructor SmartPointer(SmartPointer &&other) { core = other.core; other.core = nullptr; } // copy assigment SmartPointer &operator=(const SmartPointer &other) { if (this != &other) { this->~SmartPointer(); core = other.core; if (core != nullptr) { core->count_++; } } return *this; } // move assigment SmartPointer &operator=(SmartPointer &&other) { if (this != &other) { this->~SmartPointer(); core = other.core; other.core = nullptr; } return *this; } // SmartPointer &operator=(value_type *ptr) { this->~SmartPointer(); if (ptr != nullptr) { core = new Core(ptr); } else { core = nullptr; } return *this; } ~SmartPointer() { if (core != nullptr) { 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 (core != nullptr) { return *(core->ptr_); } else { throw smart_pointer::exception(); } } const value_type &operator*() const { if (core != nullptr) { return *(core->ptr_); } else { throw smart_pointer::exception(); } } // return pointer to the object of class/type T value_type *operator->() const { if (core != nullptr) { return core->ptr_; } else { return nullptr; } } value_type *get() const { if (core != nullptr) { return core->ptr_; } else { return nullptr; } } // if pointer == nullptr => return false operator bool() const { if (core == nullptr) { return false; } return true; } // if pointers points to the same address or both null => true template friend class SmartPointer; template bool operator==(const SmartPointer &other) const { if (static_cast(core) == static_cast(other.core)) { return true; } return false; } // if pointers points to the same address or both null => false template bool operator!=(const SmartPointer &other) const { if (static_cast(core) == static_cast(other.core)) { return false; } return true; } // if smart pointer contains non-nullptr => return count owners // if smart pointer contains nullptr => return 0 std::size_t count_owners() const { if (core != nullptr) { return core->count_; } else { return 0; } } private: class Core { public: explicit Core(T *ptr = 0) { ptr_ = ptr; if (ptr != 0) { count_ = 1; } else { count_ = 0; } } ~Core() { delete ptr_; } size_t count_; T *ptr_; }; Core *core; }; } // namespace smart_pointer