#include #ifndef _POWELLCS440 #include #include #define todo(msg) \ std::cerr << msg << std::endl; \ assert(false); namespace cs440 { using counter = std::atomic; template struct Base { template friend struct Base; T *ptr; Base(T *ptr) : ptr{ptr} {} template Base(Base &ptr) : ptr{ptr.ptr} {} template Base(Base &&ptr) : ptr{ptr.ptr} { ptr.ptr = nullptr; } public: virtual T &operator*() { return *ptr; } virtual T *operator->() { return ptr; } virtual ~Base() = default; }; template class MyDerived : public Base { U *ptr; public: MyDerived(U *ptr) : Base{ptr} { this->ptr = ptr; } MyDerived(Base &ptr) : Base{ptr.ptr} { this->ptr = ptr.ptr; } U &operator*() { return *ptr; } U *operator->() { return ptr; } virtual ~MyDerived() { delete this->ptr; } }; template class SharedPtr { public: Base *ptr; counter *count; SharedPtr() : ptr{nullptr}, count{new std::atomic{0}} {} template explicit SharedPtr(U *ptr) : ptr{static_cast *>(new MyDerived{ptr})}, count{new std::atomic{ static_cast(ptr ? 1 : 0)}} {} SharedPtr(const SharedPtr &p) : ptr{p.ptr}, count{p.count} {} template SharedPtr(const SharedPtr &p) : ptr(MyDerived(const_cast &>(*p.ptr))), count{p.count} { (*count)++; } SharedPtr(SharedPtr &&p) : ptr{p.ptr} { p.ptr = nullptr; } template SharedPtr(SharedPtr &&p) : ptr{p.ptr} { p.ptr = nullptr; this->count = p.count; p->count = nullptr; } SharedPtr &operator=(const SharedPtr &ptr) { this->ptr = ptr.ptr; (*count)++; return *this; } template SharedPtr &operator=(const SharedPtr &ptr) { this->ptr = ptr.ptr; (*count)++; return *this; } SharedPtr &operator=(SharedPtr &&p) { ptr = p.ptr; p.ptr = nullptr; this->count = p.count; p->count = nullptr; return *this; } template SharedPtr &operator=(SharedPtr &&p) { ptr = p.ptr; p.ptr = nullptr; } ~SharedPtr() { if (this->count == nullptr) { if (this->ptr != nullptr) { delete this->ptr; this->ptr = nullptr; } return; } if (--(*this->count) == 0) { delete this->count; this->count = nullptr; delete this->ptr; this->ptr = nullptr; } } void reset() { this->ptr = nullptr; --(*this->count); } template void reset(U *p) { this->ptr = new MyDerived{p}; --(*this->count); this->count = new counter{0}; } T *get() const { return this->ptr ? this->ptr->ptr : nullptr; } T &operator*() const { return this->ptr->operator*(); } T *operator->() const { return this->ptr->operator->(); } explicit operator bool() const { return this->ptr != nullptr && this->ptr->ptr != nullptr; } }; // template // SharedPtr static_pointer_cast(const SharedPtr &sp) { // todo(""); // } // template // SharedPtr dynamic_pointer_cast(const SharedPtr &sp) { // todo(""); // } template bool operator==(const SharedPtr &lhs, const SharedPtr &rhs) { return lhs.get() == rhs.get(); } template bool operator==(const SharedPtr &lhs, std::nullptr_t rhs) { return lhs.get() == rhs; } template bool operator==(std::nullptr_t lhs, const SharedPtr &rhs) { return lhs == rhs.get(); } template bool operator!=(const SharedPtr &lhs, const SharedPtr &rhs) { return !(lhs == rhs); } template bool operator!=(const SharedPtr &lhs, std::nullptr_t rhs) { return !(lhs == rhs); } template bool operator!=(std::nullptr_t lhs, const SharedPtr &rhs) { return !(lhs == rhs); } } // namespace cs440 #endif