Kiwano Engine v1.3.x
RefBasePtr.hpp
1// Copyright (c) 2016-2018 Kiwano - Nomango
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#pragma once
22#include <utility>
23#include <type_traits>
24#include <kiwano/core/Common.h>
25
26namespace kiwano
27{
28
33template <typename _Ty, typename _RefPolicy>
34class RefBasePtr : protected _RefPolicy
35{
36public:
37 using value_type = _Ty;
38 using pointer_type = _Ty*;
39 using const_pointer_type = const _Ty*;
40 using reference_type = _Ty&;
41 using const_reference_type = const _Ty&;
42
43 RefBasePtr() noexcept
44 : ptr_(nullptr)
45 {
46 }
47
48 RefBasePtr(std::nullptr_t) noexcept
49 : ptr_(nullptr)
50 {
51 }
52
53 RefBasePtr(pointer_type p)
54 : ptr_(p)
55 {
56 _RefPolicy::Retain(ptr_);
57 }
58
59 RefBasePtr(const RefBasePtr& other)
60 : ptr_(other.ptr_)
61 {
62 _RefPolicy::Retain(ptr_);
63 }
64
65 RefBasePtr(RefBasePtr&& other) noexcept
66 : ptr_(nullptr)
67 {
68 Swap(other);
69 }
70
72 {
73 Tidy();
74 }
75
76 template <typename _UTy, typename std::enable_if<std::is_convertible<_UTy*, _Ty*>::value, int>::type = 0>
78 {
79 ptr_ = dynamic_cast<pointer_type>(other.Get());
80 _RefPolicy::Retain(ptr_);
81 }
82
83 inline pointer_type Get() const noexcept
84 {
85 return ptr_;
86 }
87
88 inline pointer_type* GetAddressOfAndRelease()
89 {
90 Tidy();
91 return &ptr_;
92 }
93
94 inline void Reset(pointer_type ptr = nullptr)
95 {
96 if (ptr)
97 RefBasePtr(ptr).Swap(*this);
98 else
99 Tidy();
100 }
101
102 inline void Swap(RefBasePtr& other) noexcept
103 {
104 std::swap(ptr_, other.ptr_);
105 }
106
107 inline pointer_type operator->()
108 {
109 return ptr_;
110 }
111
112 inline const_pointer_type operator->() const
113 {
114 return ptr_;
115 }
116
117 inline reference_type operator*()
118 {
119 return *ptr_;
120 }
121
122 inline const_reference_type operator*() const
123 {
124 return *ptr_;
125 }
126
127 inline pointer_type* operator&()
128 {
129 return this->GetAddressOfAndRelease();
130 }
131
132 inline operator bool() const noexcept
133 {
134 return ptr_ != nullptr;
135 }
136
137 inline bool operator!() const noexcept
138 {
139 return ptr_ == 0;
140 }
141
142 inline RefBasePtr& operator=(const RefBasePtr& other)
143 {
144 if (other.ptr_ != ptr_)
145 RefBasePtr(other).Swap(*this);
146 return (*this);
147 }
148
149 inline RefBasePtr& operator=(RefBasePtr&& other) noexcept
150 {
151 if (other.ptr_ != ptr_)
152 other.Swap(*this);
153 return (*this);
154 }
155
156 inline RefBasePtr& operator=(pointer_type p)
157 {
158 if (p != ptr_)
159 RefBasePtr(p).Swap(*this);
160 return (*this);
161 }
162
163 template <typename _UTy, typename std::enable_if<std::is_convertible<_UTy*, _Ty*>::value, int>::type = 0>
164 inline RefBasePtr& operator=(const RefBasePtr<_UTy, _RefPolicy>& other)
165 {
166 if (other.Get() != ptr_)
167 RefBasePtr(dynamic_cast<pointer_type>(other.Get())).Swap(*this);
168 return (*this);
169 }
170
171 inline RefBasePtr& operator=(std::nullptr_t)
172 {
173 Tidy();
174 return *this;
175 }
176
177private:
178 void Tidy()
179 {
180 _RefPolicy::Release(ptr_);
181 ptr_ = nullptr;
182 }
183
184private:
185 pointer_type ptr_;
186};
187
188template <class _Ty, class _UTy, class _RefPolicy>
189inline bool operator==(const RefBasePtr<_Ty, _RefPolicy>& lhs, const RefBasePtr<_UTy, _RefPolicy>& rhs) noexcept
190{
191 return lhs.Get() == rhs.Get();
192}
193
194template <class _Ty, class _RefPolicy>
195inline bool operator==(const RefBasePtr<_Ty, _RefPolicy>& lhs, _Ty* rhs) noexcept
196{
197 return lhs.Get() == rhs;
198}
199
200template <class _Ty, class _RefPolicy>
201inline bool operator==(_Ty* lhs, const RefBasePtr<_Ty, _RefPolicy>& rhs) noexcept
202{
203 return lhs == rhs.Get();
204}
205
206template <class _Ty, class _RefPolicy>
207inline bool operator==(const RefBasePtr<_Ty, _RefPolicy>& lhs, std::nullptr_t) noexcept
208{
209 return !static_cast<bool>(lhs);
210}
211
212template <class _Ty, class _RefPolicy>
213inline bool operator==(std::nullptr_t, const RefBasePtr<_Ty, _RefPolicy>& rhs) noexcept
214{
215 return !static_cast<bool>(rhs);
216}
217
218template <class _Ty, class _UTy, class _RefPolicy>
219inline bool operator!=(const RefBasePtr<_Ty, _RefPolicy>& lhs, const RefBasePtr<_UTy, _RefPolicy>& rhs) noexcept
220{
221 return !(lhs == rhs);
222}
223
224template <class _Ty, class _RefPolicy>
225inline bool operator!=(const RefBasePtr<_Ty, _RefPolicy>& lhs, _Ty* rhs) noexcept
226{
227 return lhs.Get() != rhs;
228}
229
230template <class _Ty, class _RefPolicy>
231inline bool operator!=(_Ty* lhs, const RefBasePtr<_Ty, _RefPolicy>& rhs) noexcept
232{
233 return lhs != rhs.Get();
234}
235
236template <class _Ty, class _RefPolicy>
237inline bool operator!=(const RefBasePtr<_Ty, _RefPolicy>& lhs, std::nullptr_t) noexcept
238{
239 return static_cast<bool>(lhs);
240}
241
242template <class _Ty, class _RefPolicy>
243inline bool operator!=(std::nullptr_t, const RefBasePtr<_Ty, _RefPolicy>& rhs) noexcept
244{
245 return static_cast<bool>(rhs);
246}
247
248template <class _Ty, class _UTy, class _RefPolicy>
249inline bool operator<(const RefBasePtr<_Ty, _RefPolicy>& lhs, const RefBasePtr<_UTy, _RefPolicy>& rhs) noexcept
250{
251 return lhs.Get() < rhs.Get();
252}
253
254// template class cannot specialize std::swap,
255// so implement a swap function in kiwano namespace
256template <class _Ty, class _RefPolicy>
257inline void swap(RefBasePtr<_Ty, _RefPolicy>& lhs, RefBasePtr<_Ty, _RefPolicy>& rhs) noexcept
258{
259 lhs.Swap(rhs);
260}
261
262} // namespace kiwano
引用计数智能指针
Definition: RefBasePtr.hpp:35