#include #ifndef _POWELLCS440 #include #include #define todo(msg) \ std::cerr << msg << std::endl; \ assert(false); namespace cs440 { using counter = std::atomic; template class SharedPtr; class Key { Key() {} public: template friend class SharedPtr; template void increment(SharedPtr const &ptr) { const_cast &>(*ptr.count)++; } template counter *get_counter(SharedPtr const &ptr) { return const_cast *>(ptr.count); } template U *get_ptr(SharedPtr const &ptr) { return const_cast(ptr.ptr); } template void nullify(SharedPtr &&ptr) { ptr.ptr = nullptr; ptr.count = nullptr; } }; template class SharedPtr { T *ptr; std::atomic *count; public: friend class Key; SharedPtr() : ptr{nullptr}, count{new std::atomic{1}} {} template explicit SharedPtr(U *ptr) : ptr{ptr}, count{new std::atomic{1}} {} SharedPtr(const SharedPtr &p) : ptr{p.ptr} { Key().increment(p); this->count = Key().get_counter(p); } template SharedPtr(const SharedPtr &p) : ptr{Key().get_ptr(p)} { Key().increment(p); this->count = Key().get_counter(p); } SharedPtr(SharedPtr &&p) : count{Key().get_counter(p)}, ptr{Key().get_ptr(p)} { Key().nullify(p); } template SharedPtr(SharedPtr &&p) : count{Key().get_counter(p)}, ptr{Key().get_ptr(p)} { Key().nullify(p); } SharedPtr &operator=(const SharedPtr &ptr) { Key().increment(ptr); this->count = Key().get_counter(ptr); this->ptr = Key().get_ptr(ptr); return *this; } template SharedPtr &operator=(const SharedPtr &ptr) { Key().increment(ptr); this->count = Key().get_counter(ptr); this->ptr = Key().get_ptr(ptr); return *this; } SharedPtr &operator=(SharedPtr &&p) { this->count = Key().get_counter(ptr); this->ptr = Key().get_ptr(ptr); Key().nullify(p); } template SharedPtr &operator=(SharedPtr &&p) { this->count = Key().get_counter(ptr); this->ptr = Key().get_ptr(ptr); Key().nullify(p); } ~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() { if (this->count != nullptr) { if (--(*this->count) == 0) { delete this->count; delete this->ptr; return; } } this->ptr = nullptr; this->count = nullptr; } template void reset(U *p) { this->reset(); this->count = new counter{1}; this->ptr = p; } T *get() const { return this->ptr; } T &operator*() const { return *this->ptr; } T *operator->() const { return this->ptr; } explicit operator bool() const { return this->ptr != nullptr; } template 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