#pragma once #include "shared_ptr.hpp" #include "common/memory.hpp" #include namespace common { template SharedPtr::SharedPtr() noexcept : _reference_cnt(malloc_s(sizeof(unsigned int))) { (*_reference_cnt) = 0; } template SharedPtr::SharedPtr(nullptr_t) noexcept : _reference_cnt(malloc_s(sizeof(unsigned int))) { (*_reference_cnt) = 0; } template SharedPtr::SharedPtr(Target *target) noexcept : _target(target), _reference_cnt(malloc_s(sizeof(unsigned int))) { (*_reference_cnt) = 0; } /** * Copy constructor */ template SharedPtr::SharedPtr(const SharedPtr &shared_ptr) noexcept : _target(shared_ptr._target), _reference_cnt(shared_ptr._reference_cnt) { (*_reference_cnt)++; } /** * Move constructor */ template SharedPtr::SharedPtr(SharedPtr &&shared_ptr) noexcept : _target(shared_ptr._target), _reference_cnt(shared_ptr._reference_cnt) { shared_ptr._target = nullptr; } template SharedPtr::~SharedPtr() noexcept { if ((*_reference_cnt) != 0U) { (*_reference_cnt)--; } if ((*_reference_cnt) == 0U) { delete _target; free(_reference_cnt); _reference_cnt = nullptr; } } template unsigned int SharedPtr::reference_cnt() const noexcept { if (_reference_cnt == nullptr) { return 0; } return *_reference_cnt; } template bool SharedPtr::is_disposable() const noexcept { return _reference_cnt == nullptr || (*_reference_cnt) == 0U; } /** * Copy assignment operator */ template SharedPtr &SharedPtr::operator=(const SharedPtr &rhs) noexcept { if (&rhs != this) { if (is_disposable()) { delete _target; free(_reference_cnt); } _target = nullptr; _target = rhs._target; _reference_cnt = nullptr; _reference_cnt = rhs._reference_cnt; (*_reference_cnt)++; } return *this; } /** * Move assignment operator */ template SharedPtr &SharedPtr::operator=(SharedPtr &&rhs) noexcept { if (&rhs != this) { if (is_disposable()) { delete _target; free(_reference_cnt); } _target = rhs._target; rhs._target = nullptr; _reference_cnt = rhs._reference_cnt; rhs._reference_cnt = nullptr; } return *this; } template Target &SharedPtr::operator*() const noexcept { return *(_target); } template Target *SharedPtr::operator->() const noexcept { return _target; } template SharedPtr make_shared(Args &&...args) noexcept { return SharedPtr(new Target(args...)); } } // namespace common