#pragma once
#include <memory>
#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;
SmartPointer(value_type *new_core = nullptr)
: Core(new_core) {}
// copy constructor
SmartPointer(const SmartPointer &other_core)
: Core(other_core) {}
// move constructor
SmartPointer(SmartPointer &&other_core)
: Core(other_core) {}
// copy assigment
SmartPointer &operator=(const SmartPointer &other_core) {
core = other_core;
return *core;
}
// move assigment
SmartPointer &operator=(SmartPointer &&other_core) {
core = other_core;
return *core;
}
//
SmartPointer &operator=(value_type *other_core) {
core = other_core;
return *core;
}
~SmartPointer();
// return reference to the object of class/type T
// if SmartPointer contains nullptr throw `SmartPointer::exception`
value_type &operator*() {
if (core == nullptr) {
throw;
}
return *core;
}
const value_type &operator*() const {
if (core == nullptr) {
throw;
}
return *core;
}
// return pointer to the object of class/type T
value_type *operator->() const {
return core;
}
value_type *get() const {
return *core;
}
// if pointer == nullptr => return false
operator bool() const {
return core == nullptr;
}
// if pointers points to the same address or both null => true
template<typename U, typename AnotherAllocator>
bool operator==(const SmartPointer<U, AnotherAllocator> &rhs) const {
return (core == rhs) || ((core == nullptr) && (rhs == nullptr));
}
// if pointers points to the same address or both null => false
template<typename U, typename AnotherAllocator>
bool operator!=(const SmartPointer<U, AnotherAllocator> &rhs) const {
return (core != rhs) || ((core != nullptr) && (rhs != nullptr));
}
// if smart pointer contains non-nullptr => return count owners
// if smart pointer contains nullptr => return 0
std::size_t count_owners() const {
return core->count_owners();
}
private:
class Core {
public:
Core(value_type *new_value) {
if (new_value == nullptr) {
count_owners_ = 0;
} else {
value = *new_value;
++count_owners_;
}
}
size_t count_owners() const {
return count_owners_;
}
private:
size_t count_owners_;
value_type value;
};
Core *core;
};
}