Skip to content

Instantly share code, notes, and snippets.

@timshen91
Last active September 3, 2016 09:37
Show Gist options
  • Save timshen91/e779d89f020557f6a208c61bace58698 to your computer and use it in GitHub Desktop.
Save timshen91/e779d89f020557f6a208c61bace58698 to your computer and use it in GitHub Desktop.
#include <type_traits>
#include <utility>
template<typename T>
class SharedPtr;
template<typename Base>
class RefCountMixin {
protected:
RefCountMixin() = default;
private:
int count = 1;
template<typename Tp>
friend class SharedPtr;
};
template<typename T>
class SharedPtr {
static_assert(std::is_base_of<RefCountMixin<T>, T>::value, "");
public:
SharedPtr() : ptr_(nullptr) {}
SharedPtr(T* ptr) : ptr_(ptr) {}
SharedPtr(const SharedPtr& rhs) : ptr_(rhs.ptr_) {
if (ptr_) {
ptr_->count++;
}
}
SharedPtr(SharedPtr&& rhs) : ptr_(rhs.ptr_) {
rhs.ptr_ = nullptr;
}
~SharedPtr() {
if (ptr_ && --ptr_->count == 0) {
delete static_cast<T*>(ptr_);
}
}
SharedPtr& operator=(const SharedPtr& rhs) {
this->~SharedPtr();
new (this) SharedPtr(rhs);
return *this;
}
SharedPtr& operator=(SharedPtr&& rhs) {
this->~SharedPtr();
new (this) SharedPtr(std::move(rhs));
return *this;
}
T& operator*() {
return *operator->();
}
T* operator->() {
return static_cast<T*>(ptr_);
}
private:
RefCountMixin<T>* ptr_;
};
#include <iostream>
struct A : RefCountMixin<A> {
A() {
std::cout << "A ctor\n";
}
~A() {
std::cout << "A dtor\n";
}
};
int main() {
std::cout << "1\n";
SharedPtr<A> a(new A);
std::cout << "2\n";
SharedPtr<A> b(new A);
a = b;
std::cout << "3\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment