started on rewrite
This commit is contained in:
parent
74a843720e
commit
2df44b29a2
4 changed files with 64 additions and 129 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
*.o
|
||||
test
|
||||
3
Makefile
Normal file
3
Makefile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
CXX=clang++
|
||||
test: SharedPtr_test.cpp SharedPtr.hpp
|
||||
$(CXX) SharedPtr_test.cpp -o test
|
||||
20
README.md
20
README.md
|
|
@ -1 +1,19 @@
|
|||
[](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
|
||||
|
|
|
|||
168
SharedPtr.hpp
168
SharedPtr.hpp
|
|
@ -9,139 +9,51 @@
|
|||
|
||||
namespace cs440 {
|
||||
using counter = std::atomic<std::size_t>;
|
||||
template <typename T> struct Base {
|
||||
template <typename U> friend struct Base;
|
||||
|
||||
T *ptr;
|
||||
Base(T *ptr) : ptr{ptr} {}
|
||||
template <typename U> Base(Base<U> &ptr) : ptr{ptr.ptr} {}
|
||||
template <typename U> Base(Base<U> &&ptr) : ptr{ptr.ptr} {
|
||||
ptr.ptr = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual T &operator*() { return *ptr; }
|
||||
virtual T *operator->() { return ptr; }
|
||||
virtual ~Base() = default;
|
||||
};
|
||||
template <typename T, typename U> class MyDerived : public Base<T> {
|
||||
U *ptr;
|
||||
|
||||
public:
|
||||
MyDerived(U *ptr) : Base<T>{ptr} { this->ptr = ptr; }
|
||||
MyDerived(Base<U> &ptr) : Base<T>{ptr.ptr} { this->ptr = ptr.ptr; }
|
||||
U &operator*() { return *ptr; }
|
||||
U *operator->() { return ptr; }
|
||||
virtual ~MyDerived() { delete this->ptr; }
|
||||
};
|
||||
template <typename T> class SharedPtr {
|
||||
counter count;
|
||||
(???) underlying;
|
||||
|
||||
public:
|
||||
Base<T> *ptr;
|
||||
counter *count;
|
||||
// typename U meaning a type which inherits from T
|
||||
SharedPtr();
|
||||
|
||||
template <typename U> explicit SharedPtr(U *);
|
||||
|
||||
SharedPtr(const SharedPtr &p);
|
||||
template <typename U> SharedPtr(const SharedPtr<U> &p);
|
||||
|
||||
SharedPtr(SharedPtr &&p);
|
||||
template <typename U> SharedPtr(SharedPtr<U> &&p);
|
||||
|
||||
// needs to handle self assignment
|
||||
SharedPtr &operator=(const SharedPtr &);
|
||||
template <typename U> SharedPtr<T> &operator=(const SharedPtr<U> &);
|
||||
|
||||
SharedPtr &operator=(SharedPtr &&p);
|
||||
template <typename U> SharedPtr &operator=(SharedPtr<U> &&p);
|
||||
~SharedPtr();
|
||||
|
||||
SharedPtr() : ptr{nullptr}, count{new std::atomic<std::size_t>{0}} {}
|
||||
template <typename U>
|
||||
explicit SharedPtr(U *ptr)
|
||||
: ptr{static_cast<Base<T> *>(new MyDerived<T, U>{ptr})},
|
||||
count{new std::atomic<std::size_t>{
|
||||
static_cast<std::size_t>(ptr ? 1 : 0)}} {}
|
||||
SharedPtr(const SharedPtr &p) : ptr{p.ptr}, count{p.count} {}
|
||||
template <typename U>
|
||||
SharedPtr(const SharedPtr<U> &p)
|
||||
: ptr(MyDerived<U, T>(const_cast<cs440::Base<U> &>(*p.ptr))),
|
||||
count{p.count} {
|
||||
(*count)++;
|
||||
}
|
||||
SharedPtr(SharedPtr &&p) : ptr{p.ptr} { p.ptr = nullptr; }
|
||||
template <typename U> SharedPtr(SharedPtr<U> &&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 <typename U> SharedPtr<T> &operator=(const SharedPtr<U> &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 <typename U> SharedPtr &operator=(SharedPtr<U> &&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 <typename U> void reset(U *p) {
|
||||
this->ptr = new MyDerived<T, U>{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 <typename U> void reset(U *p);
|
||||
T *get() const;
|
||||
T &operator*() const { return *this->get(); }
|
||||
T *operator->() const { return this->get(); }
|
||||
explicit operator bool() const;
|
||||
template <typename T1, typename T2>
|
||||
friend bool operator==(const SharedPtr<T1> &, const SharedPtr<T2> &);
|
||||
friend bool operator==(const SharedPtr<T> &, std::nullptr_t);
|
||||
friend bool operator==(std::nullptr_t, const SharedPtr<T> &);
|
||||
template <typename T1, typename T2>
|
||||
friend bool operator!=(const SharedPtr<T1> &, const SharedPtr<T2> &);
|
||||
friend bool operator!=(const SharedPtr<T> &, std::nullptr_t);
|
||||
friend bool operator!=(std::nullptr_t, const SharedPtr<T> &);
|
||||
template <typename U>
|
||||
friend SharedPtr<T> static_pointer_cast(const SharedPtr<U> &sp);
|
||||
template <typename U>
|
||||
friend SharedPtr<T> dynamic_pointer_cast(const SharedPtr<U> &sp);
|
||||
};
|
||||
// template <typename T, typename U>
|
||||
// SharedPtr<T> static_pointer_cast(const SharedPtr<U> &sp) {
|
||||
// todo("");
|
||||
// }
|
||||
// template <typename T, typename U>
|
||||
// SharedPtr<T> dynamic_pointer_cast(const SharedPtr<U> &sp) {
|
||||
// todo("");
|
||||
// }
|
||||
template <typename T1, typename T2>
|
||||
bool operator==(const SharedPtr<T1> &lhs, const SharedPtr<T2> &rhs) {
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
template <typename T>
|
||||
bool operator==(const SharedPtr<T> &lhs, std::nullptr_t rhs) {
|
||||
|
||||
return lhs.get() == rhs;
|
||||
}
|
||||
template <typename T>
|
||||
bool operator==(std::nullptr_t lhs, const SharedPtr<T> &rhs) {
|
||||
return lhs == rhs.get();
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
bool operator!=(const SharedPtr<T1> &lhs, const SharedPtr<T2> &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
template <typename T>
|
||||
bool operator!=(const SharedPtr<T> &lhs, std::nullptr_t rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
template <typename T>
|
||||
bool operator!=(std::nullptr_t lhs, const SharedPtr<T> &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
} // namespace cs440
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue