#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include "Test.cpp"
namespace smart_pointer {
class exception : std::exception {
using base_class = std::exception;
using base_class::base_class;
};
template<
typename T,
typename Allocator
>
class SmartPointer {
ENABLE_CLASS_TESTS;
public:
using value_type = T;
explicit SmartPointer(value_type *core = nullptr) {
this->core = core != nullptr ? new Core(core) : nullptr;
}
SmartPointer(const SmartPointer &core) {
this->core = core.core;
if (this->core != nullptr)
this->core->count_copy++;
}
SmartPointer(SmartPointer &&core) {
this->core = core.core;
core.core = nullptr;
}
SmartPointer &operator=(const SmartPointer &core) {
if (this->core != nullptr) {
this->core->count_copy--;
if (this->core->count_copy == 0)
delete this->core;
}
this->core = core.core;
if (this->core != nullptr)
this->core->count_copy++;
return *this;
}
SmartPointer &operator=(SmartPointer &&core) {
if (this->core != nullptr) {
this->core->count_copy--;
if (this->core->count_copy == 0)
delete this->core;
}
this->core = core.core;
core.core = nullptr;
return *this;
}
SmartPointer &operator=(value_type *core) {
if (this->core != nullptr) {
this->core->count_copy--;
if (this->core->count_copy == 0) {
delete this->core;
this->core = nullptr;
}
}
if (this->core == nullptr && core != nullptr)
this->core = new Core(core);
else if (this->core != nullptr && core == nullptr)
this->core = nullptr;
else if (this->core != nullptr && core != nullptr) {
this->core->TEMP = core;
this->core->count_copy++;
}
return *this;
}
~SmartPointer() {
if (this->core != nullptr) {
this->core->count_copy--;
if (this->core->count_copy == 0)
delete this->core;
}
}
value_type &operator*() {
if (this->core == nullptr || this->core->TEMP == nullptr)
throw smart_pointer::exception();
return *this->core->TEMP;
}
const value_type &operator*() const {
if (this->core == nullptr || this->core->TEMP == nullptr)
throw smart_pointer::exception();
return *this->core->TEMP;
}
value_type *operator->() const {
return this->core == nullptr ? nullptr : this->core->TEMP;
}
value_type *get() const {
return this->core == nullptr ? nullptr : this->core->TEMP;
}
operator bool() const {
return this->core != nullptr ?
this->core->TEMP != nullptr : false;
}
template<typename U, typename AnotherAllocator>
bool operator==(const SmartPointer<U, AnotherAllocator> &core) const {
auto obj_core = core.get();
if ((obj_core == nullptr) &&
(this->core == nullptr || this->core->TEMP == nullptr))
return true;
if (this->core == nullptr) return false;
if (typeid(obj_core) != typeid(this->core->TEMP)) return false;
return (reinterpret_cast<value_type *>(obj_core) == this->core->TEMP);
}
template<typename U, typename AnotherAllocator>
bool operator!=(const SmartPointer<U, AnotherAllocator> &core) const {
auto obj_core = core.get();
if ((obj_core == nullptr) &&
(this->core == nullptr || this->core->TEMP == nullptr))
return false;
if (this->core == nullptr) return true;
if (typeid(obj_core) != typeid(this->core->TEMP)) return true;
return (reinterpret_cast<value_type *>(obj_core) != this->core->TEMP);
}
std::size_t count_owners() const {
if (this->core == nullptr || this->core->TEMP == nullptr) return 0;
return this->core->count_copy;
}
private:
class Core {
public:
value_type *TEMP;
int count_copy;
explicit Core(value_type *TEMP = nullptr) {
this->TEMP = TEMP;
this->count_copy = 1;
}
~Core() {
if (count_copy == 0)
delete TEMP;
}
};
Core *core;
};
};