//
// Created by bomeng on 6/14/23.
//
#ifndef DEMO_MY_SHARED_PTR_H
#define DEMO_MY_SHARED_PTR_H
#include <stdexcept>
namespace bomeng {
template<typename T>
class Ref {
private:
int r_count;
T *obj;
public:
explicit Ref(T *target)
: obj(target), r_count(1) {}
~Ref() {
delete obj;
obj = nullptr;
}
inline void increase() { r_count++; }
inline void reduce() { r_count--; }
T *get() { return obj; }
int getCount() { return r_count; }
};
template<class T>
class shared_ptr {
private:
Ref<T> *ref;
private:
void deleteRef() {
if (ref) {
ref->reduce();
if (ref->getCount() == 0)
delete ref;
ref = nullptr;
}
}
public:
shared_ptr()
: ref(nullptr) {}
explicit shared_ptr(T *ptr)
: ref(new Ref<T>(ptr)) {}
~shared_ptr() {
deleteRef();
}
//拷贝构造
shared_ptr(const shared_ptr<T> &s_ptr)
: ref(s_ptr.ref) {
if (ref)
ref->increase();
}
//拷贝赋值
shared_ptr<T> &operator=(const shared_ptr<T> &s_ptr) {
deleteRef();
ref = s_ptr.ref;
if (ref)
ref->increase();
}
//移动构造
shared_ptr(shared_ptr<T> &&s_ptr)
: ref(s_ptr.ref) {
s_ptr.ref = nullptr;
}
//移动赋值
shared_ptr<T> &operator=(shared_ptr<T> &&s_ptr) {
deleteRef();
ref = s_ptr.ref;
s_ptr.ref = nullptr;
}
public:
void reset(T *target = nullptr) {
deleteRef();
if (target)
ref = new Ref<T>(target);
}
T &operator*() {
if (ref == nullptr)
throw std::runtime_error("ERROR dereference a null pointer!");
return *(ref->get());
}
T *operator->() {
if (ref == nullptr)
throw std::runtime_error("ERROR dereference a null pointer!");
return ref->get();
}
int use_count() {
if (ref)
return ref->getCount();
return 0;
}
T *get() { return ref->get(); }
public:
template<typename T2>
friend bool operator==(const shared_ptr<T2> &s_ptr1, const shared_ptr<T2> &s_ptr2);
template<typename T2>
friend bool operator!=(const shared_ptr<T2> &s_ptr1, const shared_ptr<T2> &s_ptr2);
template<typename T2>
friend bool operator==(const shared_ptr<T2> &s_ptr, std::nullptr_t);
template<typename T2>
friend bool operator!=(const shared_ptr<T2> &s_ptr, std::nullptr_t);
template<typename T2>
friend bool operator==(std::nullptr_t, const shared_ptr<T2> &s_ptr);
template<typename T2>
friend bool operator!=(std::nullptr_t, const shared_ptr<T2> &s_ptr);
};
template<typename T>
bool operator==(const shared_ptr<T> &s_ptr1, const shared_ptr<T> &s_ptr2) {
return s_ptr1.ref == s_ptr2.ref;
}
template<typename T>
bool operator!=(const shared_ptr<T> &s_ptr1, const shared_ptr<T> &s_ptr2) {
return s_ptr1.ref != s_ptr2.ref;
}
template<typename T>
bool operator==(const shared_ptr<T> &s_ptr, std::nullptr_t) {
return s_ptr.ref == nullptr;
}
template<typename T>
bool operator!=(const shared_ptr<T> &s_ptr, std::nullptr_t) {
return s_ptr.ref != nullptr;
}
template<typename T>
bool operator==(std::nullptr_t, const shared_ptr<T> &s_ptr) {
return s_ptr.ref == nullptr;
}
template<typename T>
bool operator!=(std::nullptr_t, const shared_ptr<T> &s_ptr) {
return s_ptr.ref != nullptr;
}
}
#endif //DEMO_MY_SHARED_PTR_H