#include <memory>
#include "Test.hpp"
class exception : std::exception {
using base_class = std::exception;
using base_class::base_class;
};
template<typename T, typename Allocator>
class SmartPointer {
public:
ENABLE_CLASS_TESTS;
using value_type = T;
explicit SmartPointer(value_type *p = nullptr) {
if (p == nullptr) { core = nullptr; }
else {
core = &Core(p);
core->AddRef();
}
}
SmartPointer(const SmartPointer &optr)
: core(optr.core) { core->AddRef(); }
SmartPointer(SmartPointer &&) = default;
SmartPointer &operator=(const SmartPointer &) = default;
SmartPointer &operator=(SmartPointer &&sp) {
if (this != &sp) {
if (core->Release() == 0) {
delete core;
}
core = sp.core;
core->AddRef();
}
return *this;
}
SmartPointer &operator=(value_type *other) {
core->p = other;
core->AddRef();
return *this;
}
~SmartPointer() {
if (core->Release() == 0) delete core;
}
value_type &operator*() {
if (core->p == nullptr) throw exception();
return *core->p;
}
const value_type &operator*() const {
if (core->p == nullptr) throw exception();
auto const f = *core->p;
return f;
}
value_type *operator->() const { return core->p; }
value_type *get() const { return core->p; }
operator bool() const { return core->p != nullptr; }
template<typename U, typename AnotherAllocator>
bool operator == (const SmartPointer<U, AnotherAllocator> &pp) const {
return static_cast<void *>(core->p)
== static_cast<void *>(pp.core->p);
}
template<typename U, typename AnotherAllocator>
bool operator != (const SmartPointer<U, AnotherAllocator> &other) const {
return static_cast<void *>(other.core->p)
!= static_cast<void *>(core->p);
}
std::size_t count_owners() const {
if (core->p == nullptr) return 0;
return core->c;
}
public:
class Core {
public:
value_type *p;
size_t c;
explicit Core(value_type *_p = nullptr) : p(_p), c(0) {}
void AddRef() { ++c; }
int Release() { return --c; }
~Core() {
if (p != nullptr) delete p;
}
};
Core *core;
};