-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSmartPointer.h
76 lines (60 loc) · 1.45 KB
/
SmartPointer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// SmartPointer.h
#include <cstdint>
#include <utility>
#include <type_traits>
class ControlBlock {
public:
uint32_t ref_count = 0;
};
template <typename T>
class SmartPointer {
static_assert(std::is_base_of<ControlBlock, T>::value, "You must use ControlBlock as a base class");
private:
public:
T& operator*(void) const { return *ptr; }
T* operator->(void) const { return ptr; }
SmartPointer(const SmartPointer<T>& rhs) { copy(rhs); }
SmartPointer<T>& operator=(const SmartPointer<T>& rhs) {
if (this != &rhs) {
destroy();
copy(rhs);
}
return *this;
}
template <typename U>
SmartPointer(const SmartPointer<U>& rhs) {
//static_assert(std::is_base_of<T, U>::value, "cannot upcast smart pointers");
if (rhs.ptr == nullptr) {
this->ptr = nullptr;
return;
}
ptr = dynamic_cast<T*>(rhs.ptr);
ptr->ControlBlock::ref_count += 1;
}
SmartPointer(T* obj = nullptr) {
ptr = obj;
if (obj) {
ptr->ControlBlock::ref_count += 1;
}
}
~SmartPointer(void) { destroy(); }
operator bool(void) const { return ptr; }
private:
T* ptr = nullptr;
template <typename U>
friend class SmartPointer;
void copy(const SmartPointer<T>& rhs) {
this->ptr = rhs.ptr;
if (ptr) {
ptr->ControlBlock::ref_count += 1;
}
}
void destroy(void) {
if (ptr) {
ptr->ControlBlock::ref_count -= 1;
if (ptr->ControlBlock::ref_count == 0) {
delete ptr;
}
}
}
};