class SharedCount
{
public:
SharedCount() : count_{1} {}
void add() { ++count_; }
void minus() { --count_; }
int get() const { return count_; }
private:
std::atomic<int> count_;
};
template<typename T> class SharedPtr
{
public:
SharedPtr(void) : ptr_(nullptr), ref_count_(nullptr) {}
SharedPtr(T* ptr) : ptr_(ptr), ref_count_(new SharedCount) {}
~SharedPtr(void) { clean(); }
SharedPtr(const SharedPtr& p)
{
if (this == &p) {
return;
}
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
ref_count_->add();
}
SharedPtr& operator=(const SharedPtr& p)
{
if (this->ptr_ == p.ptr_ ) {
return *this;
}
clean();
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
ref_count_->add();
return *this;
}
SharedPtr(SharedPtr&& p)
{
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
p.ptr_ = nullptr;
p.ref_count_ = nullptr;
}
SharedPtr& operator=(SharedPtr&& p)
{
clean();
this->ptr_ = p.ptr_;
this->ref_count_ = p.ref_count_;
p.ptr_ = nullptr;
p.ref_count_ = nullptr;
return *this;
}
int use_count() { return ref_count_->get(); }
T* get() const { return ptr_; }
T* operator->(void) const { return ptr_; }
T const* operator->(void) const {return ptr_;}
T& operator*(void) const { return *ptr_; }
T const& operator*(void) const { return *ptr_; }
operator bool() const { return ptr_ != nullptr; }
bool isValid() const { return nullptr != ptr_; }
bool isNull(void) const { return !isValid(); }
void setNull(void);
void swap(SharedPtr& rhs)
{
T* temp = ptr_;
ptr_ = rhs.ptr_;
rhs.ptr_ = temp;
}
bool operator ==(T* rhs) const {return ptr_ == rhs;}
bool operator !=(T* rhs) const {return ptr_ != rhs;}
bool operator ==(T const* rhs) const;
bool operator !=(T const* rhs) const;
bool operator ==(SharedPtr<T> const& rhs) const { return ptr_ == rhs.ptr_; }
bool operator !=(SharedPtr<T> const& rhs) const { return ptr_ != rhs.ptr_; }
SharedPtr<T>& operator =(T* rhs);
SharedPtr<T>& operator =(SharedPtr<T>& rhs);
template<typename U> SharedPtr<T>& operator =(U*);
template<typename U> SharedPtr<T>& operator =(const SharedPtr<U>& rhs)
{
SharedPtr(rhs).swap(*this);
return *this;
}
template<typename U> explicit operator U* (void) const;
private:
void clean()
{
if (ref_count_) {
ref_count_->minus();
if (ref_count_->get() == 0) {
if (ptr_) {
delete ptr_;
ptr_ = nullptr;
}
delete ref_count_;
ref_count_ = nullptr;
}
}
}
T* ptr_;
SharedCount* ref_count_;
};