shared_ptr.h
#include <utility>
namespace yuy {
class ref_count {
public:
int use_count() const { return count_; }
void inc_ref() { ++count_; }
int dec_ref() { return --count_; }
private:
int count_{1};
};
template<typename T>
class shared_ptr {
public:
explicit shared_ptr(T *ptr = nullptr);
~shared_ptr();
shared_ptr(const shared_ptr<T> &rhs);
shared_ptr<T> &operator=(const shared_ptr<T> &rhs);
shared_ptr(shared_ptr<T> &&rhs) noexcept;
shared_ptr<T> &operator=(shared_ptr<T> &&rhs) noexcept;
void swap(shared_ptr<T> &rhs);
void reset();
void reset(T *ptr);
T *get() const;
T &operator*() const;
T *operator->() const;
int use_count() const;
bool unique() const;
explicit operator bool() const;
private:
T *ptr_{nullptr};
ref_count *rep_{nullptr};
};
template<typename T>
shared_ptr<T>::shared_ptr(T *ptr): ptr_(ptr) {
if(ptr) {
rep_ = new ref_count{};
}
}
template<typename T>
shared_ptr<T>::~shared_ptr() {
if(rep_ && !rep_->dec_ref()) {
delete ptr_;
delete rep_;
}
}
template<typename T>
shared_ptr<T>::shared_ptr(const shared_ptr<T> &rhs): ptr_(rhs.ptr_), rep_(rhs.rep_) {
if(rep_) {
rep_->inc_ref();
}
}
template<typename T>
shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr<T> &rhs) {
shared_ptr{ rhs }.swap(*this);
return *this;
}
template<typename T>
shared_ptr<T>::shared_ptr(shared_ptr<T> &&rhs) noexcept: ptr_(rhs.ptr_), rep_(rhs.rep_) {
rhs.ptr_ = nullptr;
rhs.rep_ = nullptr;
}
template<typename T>
shared_ptr<T> &shared_ptr<T>::operator=(shared_ptr<T> &&rhs) noexcept{
shared_ptr{ std::move(rhs) }.swap(*this);
return *this;
}
template<typename T>
void shared_ptr<T>::swap(shared_ptr<T> &rhs) {
std::swap(ptr_, rhs.ptr_);
std::swap(rep_, rhs.rep_);
}
template<typename T>
void shared_ptr<T>::reset() {
shared_ptr{}.swap(*this);
}
template<typename T>
void shared_ptr<T>::reset(T *ptr) {
shared_ptr{ ptr }.swap(*this);
}
template<typename T>
T *shared_ptr<T>::get() const {
return ptr_;
}
template<typename T>
T &shared_ptr<T>::operator*() const {
return *ptr_;
}
template<typename T>
T *shared_ptr<T>::operator->() const {
return ptr_;
}
template<typename T>
int shared_ptr<T>::use_count() const {
return rep_ ? rep_->use_count() : 0;
}
template<typename T>
bool shared_ptr<T>::unique() const {
return use_count() == 1;
}
template<typename T>
shared_ptr<T>::operator bool() const {
return static_cast<bool>(ptr_);
}
}