-
Notifications
You must be signed in to change notification settings - Fork 17
/
UniquePtr.hpp
155 lines (122 loc) · 4.21 KB
/
UniquePtr.hpp
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#pragma once
#include <type_traits>
#include <utility>
template <class _Tp>
struct DefaultDeleter { // 默认使用 delete 释放内存
void operator()(_Tp *p) const {
delete p;
}
};
template <class _Tp>
struct DefaultDeleter<_Tp[]> { // 偏特化
void operator()(_Tp *p) const {
delete[] p;
}
};
template <class _Tp, class _Deleter = DefaultDeleter<_Tp>>
struct UniquePtr {
private:
_Tp *_M_p;
[[no_unique_address]] _Deleter _M_deleter;
template <class _Up, class _UDeleter>
friend struct UniquePtr;
public:
using element_type = _Tp;
using pointer = _Tp *;
using deleter_type = _Deleter;
UniquePtr(std::nullptr_t = nullptr) noexcept : _M_p(nullptr) { // 默认构造函数
}
explicit UniquePtr(_Tp *p) noexcept : _M_p(p) { // 自定义构造函数
}
template <class _Up, class _UDeleter, class = std::enable_if_t<std::is_convertible_v<_Up *, _Tp *>>> // 没有 C++20 的写法
// template <class _Up, class _UDeleter> requires (std::convertible_to<_Up *, _Tp *>) // 有 C++20 的写法
UniquePtr(UniquePtr<_Up, _UDeleter> &&__that) noexcept : _M_p(__that._M_p) { // 从子类型_Up的智能指针转换到_Tp类型的智能指针
__that._M_p = nullptr;
}
~UniquePtr() noexcept { // 析构函数
if (_M_p)
_M_deleter(_M_p);
}
UniquePtr(UniquePtr const &__that) = delete; // 拷贝构造函数
UniquePtr &operator=(UniquePtr const &__that) = delete; // 拷贝赋值函数
UniquePtr(UniquePtr &&__that) noexcept : _M_p(__that._M_p) { // 移动构造函数
__that._M_p = nullptr;
}
UniquePtr &operator=(UniquePtr &&__that) noexcept { // 移动赋值函数
if (this != &__that) [[likely]] {
if (_M_p)
_M_deleter(_M_p);
_M_p = std::exchange(__that._M_p, nullptr);
}
return *this;
}
void swap(UniquePtr &__that) noexcept { // 交换函数
std::swap(_M_p, __that._M_p);
}
_Tp *get() const noexcept {
return _M_p;
}
_Tp *operator->() const noexcept {
return _M_p;
}
std::add_lvalue_reference_t<_Tp> operator*() const noexcept {
return *_M_p;
}
_Deleter get_deleter() const noexcept {
return _M_deleter;
}
_Tp *release() noexcept {
_Tp *__p = _M_p;
_M_p = nullptr;
return __p;
}
void reset(_Tp *__p = nullptr) noexcept {
if (_M_p)
_M_deleter(_M_p);
_M_p = __p;
}
explicit operator bool() const noexcept {
return _M_p != nullptr;
}
bool operator==(UniquePtr const &__that) const noexcept {
return _M_p == __that._M_p;
}
bool operator!=(UniquePtr const &__that) const noexcept {
return _M_p != __that._M_p;
}
bool operator<(UniquePtr const &__that) const noexcept {
return _M_p < __that._M_p;
}
bool operator<=(UniquePtr const &__that) const noexcept {
return _M_p <= __that._M_p;
}
bool operator>(UniquePtr const &__that) const noexcept {
return _M_p > __that._M_p;
}
bool operator>=(UniquePtr const &__that) const noexcept {
return _M_p >= __that._M_p;
}
};
template <class _Tp, class _Deleter>
struct UniquePtr<_Tp[], _Deleter> : UniquePtr<_Tp, _Deleter> {
using UniquePtr<_Tp, _Deleter>::UniquePtr;
std::add_lvalue_reference_t<_Tp> operator[](std::size_t __i) {
return this->get()[__i];
}
};
template <class _Tp, class ..._Args, std::enable_if_t<!std::is_unbounded_array_v<_Tp>, int> = 0>
UniquePtr<_Tp> makeUnique(_Args &&...__args) {
return UniquePtr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
}
template <class _Tp, std::enable_if_t<!std::is_unbounded_array_v<_Tp>, int> = 0>
UniquePtr<_Tp> makeUniqueForOverwrite() {
return UniquePtr<_Tp>(new _Tp);
}
template <class _Tp, std::enable_if_t<std::is_unbounded_array_v<_Tp>, int> = 0>
UniquePtr<_Tp> makeUnique(std::size_t __len) {
return UniquePtr<_Tp>(new std::remove_extent_t<_Tp>[__len]());
}
template <class _Tp, std::enable_if_t<std::is_unbounded_array_v<_Tp>, int> = 0>
UniquePtr<_Tp> makeUniqueForOverwrite(std::size_t __len) {
return UniquePtr<_Tp>(new std::remove_extent_t<_Tp>[__len]);
}