#include #include #ifndef _POWELLCS440 #include #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 const &ptr) : ptr{ptr.ptr} {} template operator U() { return U(*this); } public: virtual T &operator*() { return *ptr; } virtual T *operator->() { return ptr; } virtual ~Base() = default; }; template class Derived : public Base { static_assert(std::is_base_of_v); U *ptr; public: Derived(Base b) : Derived{*dynamic_cast *>(&b)} {} U &operator*() { return *ptr; } U *operator->() { return ptr; } virtual ~Derived() { delete this->ptr; } }; template class SharedPtr { public: Base *ptr; counter *count; // problem? SharedPtr() : ptr{nullptr}, count{new std::atomic{0}} {} template explicit SharedPtr(U *ptr) : ptr{static_cast *>(new Derived{ptr})}, count{new std::atomic{ptr ? 1 : 0}} {} SharedPtr(const SharedPtr &p) : ptr{p.ptr} {} template SharedPtr(const SharedPtr &p) : ptr(Base(*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; } SharedPtr &operator=(const SharedPtr &ptr) { this->ptr = ptr.ptr; (*count)++; return *this; } template SharedPtr &operator=(const SharedPtr &ptr) { this->ptr = new Derived{Base(ptr.ptr)}; return *this; } SharedPtr &operator=(SharedPtr &&p) { ptr = p.ptr; p.ptr = nullptr; } template SharedPtr &operator=(SharedPtr &&p) { ptr = p.ptr; p.ptr = nullptr; } ~SharedPtr() { if (this->count == nullptr) { if (this->ptr != nullptr) { delete this->ptr; } return; } if (--(*this->count) == 0) { delete this->count; delete this->ptr; } } void reset() { this->ptr = nullptr; } template void reset(U *p) { this->ptr = new Derived{p}; } T *get() const { return this->ptr->ptr; } T &operator*() const { return this->ptr->operator*(); } T *operator->() const { return this->ptr->operator->(); } explicit operator bool() const { return this->ptr->ptr != nullptr; } template friend SharedPtr static_pointer_cast(const SharedPtr &sp) { todo(""); } template friend 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