diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76758b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..00f2c31 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +CXX=clang++ +test: SharedPtr_test.cpp SharedPtr.hpp + $(CXX) SharedPtr_test.cpp -o test diff --git a/README.md b/README.md index 3e9fce8..46a715c 100644 --- a/README.md +++ b/README.md @@ -1 +1,19 @@ -[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/nYZgPGGq) +# `std::shared_ptr` impl for CS440 + +This repo contains code derived from the results of an assignment I completed as a part of my CS 440 class. + +You will find the original CS 440 code at commit hash `74a843720e` the code now is rewritten. + +There are two files in this repo `SharedPtr.hpp` and `SharedPtr_test.cpp` the former is the implementation and the latter is a test file originally provided by the class + +## Building + +The test executable can be build via `make` the only compiler which has been tested is `clang version 21.1.6` + +## What is implemented + +- Default and Raw pointer constructors +- Copy and Move Constructors and assignment operators (incrementing counter on copy) +- Destructor (decrementing counter if non-null) +- Static and Dynamic pointer casts +- Miscellaneous Pointer and Equality operations one would expect from a pointer diff --git a/SharedPtr.hpp b/SharedPtr.hpp index cd2825b..abf9cd2 100644 --- a/SharedPtr.hpp +++ b/SharedPtr.hpp @@ -9,139 +9,51 @@ 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 { + counter count; + (???) underlying; + public: - Base *ptr; - counter *count; + // typename U meaning a type which inherits from T + SharedPtr(); + + template explicit SharedPtr(U *); + + SharedPtr(const SharedPtr &p); + template SharedPtr(const SharedPtr &p); + + SharedPtr(SharedPtr &&p); + template SharedPtr(SharedPtr &&p); + + // needs to handle self assignment + SharedPtr &operator=(const SharedPtr &); + template SharedPtr &operator=(const SharedPtr &); + + SharedPtr &operator=(SharedPtr &&p); + template SharedPtr &operator=(SharedPtr &&p); + ~SharedPtr(); - 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; + this->count = 0; + this->underlying = nullptr; } + template void reset(U *p); + T *get() const; + T &operator*() const { return *this->get(); } + T *operator->() const { return this->get(); } + explicit operator bool() const; + template + friend bool operator==(const SharedPtr &, const SharedPtr &); + friend bool operator==(const SharedPtr &, std::nullptr_t); + friend bool operator==(std::nullptr_t, const SharedPtr &); + template + friend bool operator!=(const SharedPtr &, const SharedPtr &); + friend bool operator!=(const SharedPtr &, std::nullptr_t); + friend bool operator!=(std::nullptr_t, const SharedPtr &); + template + friend SharedPtr static_pointer_cast(const SharedPtr &sp); + template + friend SharedPtr dynamic_pointer_cast(const SharedPtr &sp); }; -// 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