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 {
|
namespace cs440 {
|
||||||
using counter = std::atomic<std::size_t>;
|
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 {
|
template <typename T> class SharedPtr {
|
||||||
|
counter count;
|
||||||
|
(???) underlying;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Base<T> *ptr;
|
// typename U meaning a type which inherits from T
|
||||||
counter *count;
|
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() {
|
void reset() {
|
||||||
this->ptr = nullptr;
|
this->count = 0;
|
||||||
--(*this->count);
|
this->underlying = nullptr;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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
|
} // namespace cs440
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue