cycle_ptr
intrusive_ptr.h
1 #ifndef CYCLE_PTR_DETAIL_INTRUSIVE_PTR_H
2 #define CYCLE_PTR_DETAIL_INTRUSIVE_PTR_H
3 
4 #include <cassert>
5 #include <cstddef>
6 #include <functional>
7 #include <iosfwd>
8 #include <utility>
9 
10 namespace cycle_ptr::detail {
11 
12 
20 template<typename T>
22  public:
23  using element_type = T;
24 
25  constexpr intrusive_ptr() noexcept = default;
26 
27  constexpr intrusive_ptr([[maybe_unused]] std::nullptr_t nil) noexcept
28  : intrusive_ptr()
29  {}
30 
31  intrusive_ptr(T* p, bool acquire) noexcept
32  : ptr_(p)
33  {
34  if (ptr_ != nullptr && acquire)
35  intrusive_ptr_add_ref(ptr_); // ADL
36  }
37 
38  intrusive_ptr(const intrusive_ptr& x) noexcept
39  : intrusive_ptr(x.ptr_, true)
40  {}
41 
42  intrusive_ptr(intrusive_ptr&& x) noexcept
43  : ptr_(std::exchange(x.ptr_, nullptr))
44  {}
45 
46  auto operator=(const intrusive_ptr& x)
47  noexcept
48  -> intrusive_ptr& {
49  T* old = std::exchange(ptr_, x.ptr_);
50  if (ptr_ != nullptr)
51  intrusive_ptr_add_ref(ptr_); // ADL
52  if (old != nullptr)
53  intrusive_ptr_release(old); // ADL
54  return *this;
55  }
56 
57  auto operator=(intrusive_ptr&& x)
58  noexcept
59  -> intrusive_ptr& {
60  T* old = std::exchange(ptr_, std::exchange(x.ptr_, nullptr));
61  if (old != nullptr)
62  intrusive_ptr_release(old); // ADL
63  return *this;
64  }
65 
66  ~intrusive_ptr() noexcept {
67  if (ptr_ != nullptr)
68  intrusive_ptr_release(ptr_); // ADL
69  }
70 
71  auto reset() noexcept
72  -> void {
73  if (ptr_ != nullptr)
74  intrusive_ptr_release(std::exchange(ptr_, nullptr)); // ADL
75  }
76 
77  auto swap(intrusive_ptr& other)
78  noexcept
79  -> void {
80  std::swap(ptr_, other.ptr_);
81  }
82 
83  auto detach()
84  noexcept
85  -> T* {
86  return std::exchange(ptr_, nullptr);
87  }
88 
89  auto get() const
90  noexcept
91  -> T* {
92  return ptr_;
93  }
94 
95  auto operator*() const
96  noexcept
97  -> T& {
98  assert(ptr_ != nullptr);
99  return *ptr_;
100  }
101 
102  auto operator->() const
103  noexcept
104  -> T* {
105  assert(ptr_ != nullptr);
106  return ptr_;
107  }
108 
109  explicit operator bool() const noexcept {
110  return ptr_ != nullptr;
111  }
112 
113  private:
114  T* ptr_ = nullptr;
115 };
116 
117 
120 template<typename T>
122 noexcept
123 -> void {
124  x.swap(y);
125 }
126 
129 template<typename T, typename U>
131 noexcept
132 -> bool {
133  return x.get() == y.get();
134 }
135 
138 template<typename T, typename U>
139 auto operator==(T* x, const intrusive_ptr<U>& y)
140 noexcept
141 -> bool {
142  return x == y.get();
143 }
144 
147 template<typename T, typename U>
148 auto operator==(const intrusive_ptr<T>& x, U* y)
149 noexcept
150 -> bool {
151  return x.get() == y;
152 }
153 
156 template<typename U>
157 auto operator==([[maybe_unused]] std::nullptr_t x, const intrusive_ptr<U>& y)
158 noexcept
159 -> bool {
160  return !y;
161 }
162 
165 template<typename T>
166 auto operator==(const intrusive_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
167 noexcept
168 -> bool {
169  return !x;
170 }
171 
174 template<typename T, typename U>
176 noexcept
177 -> bool {
178  return !(x == y);
179 }
180 
183 template<typename T, typename U>
184 auto operator!=(T* x, const intrusive_ptr<U>& y)
185 noexcept
186 -> bool {
187  return !(x == y);
188 }
189 
192 template<typename T, typename U>
193 auto operator!=(const intrusive_ptr<T>& x, U* y)
194 noexcept
195 -> bool {
196  return !(x == y);
197 }
198 
201 template<typename U>
202 auto operator!=([[maybe_unused]] std::nullptr_t x, const intrusive_ptr<U>& y)
203 noexcept
204 -> bool {
205  return bool(y);
206 }
207 
210 template<typename T>
211 auto operator!=(const intrusive_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
212 noexcept
213 -> bool {
214  return bool(x);
215 }
216 
219 template<typename T, typename U>
221 noexcept
222 -> bool {
223  return x.get() < y.get();
224 }
225 
228 template<typename T, typename U>
229 auto operator<(T* x, const intrusive_ptr<U>& y)
230 noexcept
231 -> bool {
232  return x < y.get();
233 }
234 
237 template<typename T, typename U>
238 auto operator<(const intrusive_ptr<T>& x, U* y)
239 noexcept
240 -> bool {
241  return x.get() < y;
242 }
243 
246 template<typename U>
247 auto operator<([[maybe_unused]] std::nullptr_t x, const intrusive_ptr<U>& y)
248 noexcept
249 -> bool {
250  return std::less<typename intrusive_ptr<U>::element_type*>()(nullptr, y.get());
251 }
252 
255 template<typename T>
256 auto operator<(const intrusive_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
257 noexcept
258 -> bool {
259  return std::less<typename intrusive_ptr<T>::element_type*>()(x.get(), nullptr);
260 }
261 
264 template<typename T, typename U>
266 noexcept
267 -> bool {
268  return y < x;
269 }
270 
273 template<typename T, typename U>
274 auto operator>(T* x, const intrusive_ptr<U>& y)
275 noexcept
276 -> bool {
277  return y < x;
278 }
279 
282 template<typename T, typename U>
283 auto operator>(const intrusive_ptr<T>& x, U* y)
284 noexcept
285 -> bool {
286  return y < x;
287 }
288 
291 template<typename U>
292 auto operator>([[maybe_unused]] std::nullptr_t x, const intrusive_ptr<U>& y)
293 noexcept
294 -> bool {
295  return y < nullptr;
296 }
297 
300 template<typename T>
301 auto operator>(const intrusive_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
302 noexcept
303 -> bool {
304  return nullptr < x;
305 }
306 
309 template<typename T, typename U>
311 noexcept
312 -> bool {
313  return !(y < x);
314 }
315 
318 template<typename T, typename U>
319 auto operator<=(T* x, const intrusive_ptr<U>& y)
320 noexcept
321 -> bool {
322  return !(y < x);
323 }
324 
327 template<typename T, typename U>
328 auto operator<=(const intrusive_ptr<T>& x, U* y)
329 noexcept
330 -> bool {
331  return !(y < x);
332 }
333 
336 template<typename U>
337 auto operator<=([[maybe_unused]] std::nullptr_t x, const intrusive_ptr<U>& y)
338 noexcept
339 -> bool {
340  return !(y < nullptr);
341 }
342 
345 template<typename T>
346 auto operator<=(const intrusive_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
347 noexcept
348 -> bool {
349  return !(nullptr < x);
350 }
351 
354 template<typename T, typename U>
356 noexcept
357 -> bool {
358  return !(x < y);
359 }
360 
363 template<typename T, typename U>
364 auto operator>=(T* x, const intrusive_ptr<U>& y)
365 noexcept
366 -> bool {
367  return !(x < y);
368 }
369 
372 template<typename T, typename U>
373 auto operator>=(const intrusive_ptr<T>& x, U* y)
374 noexcept
375 -> bool {
376  return !(x < y);
377 }
378 
381 template<typename U>
382 auto operator>=([[maybe_unused]] std::nullptr_t x, const intrusive_ptr<U>& y)
383 noexcept
384 -> bool {
385  return !(nullptr < y);
386 }
387 
390 template<typename T>
391 auto operator>=(const intrusive_ptr<T>& x, [[maybe_unused]] std::nullptr_t y)
392 noexcept
393 -> bool {
394  return !(x < nullptr);
395 }
396 
399 template<typename Char, typename Traits, typename T>
400 auto operator<<(std::basic_ostream<Char, Traits>& out, const intrusive_ptr<T>& ptr)
401 -> std::basic_ostream<Char, Traits>& {
402  return out << ptr.get();
403 }
404 
405 
406 } /* namespace cycle_ptr::detail */
407 
408 #endif /* CYCLE_PTR_DETAIL_INTRUSIVE_PTR_H */
auto swap(intrusive_ptr< T > &x, intrusive_ptr< T > &y) noexcept -> void
Swap operation.
Definition: intrusive_ptr.h:121
auto operator<<(std::basic_ostream< Char, Traits > &out, const intrusive_ptr< T > &ptr) -> std::basic_ostream< Char, Traits > &
Write pointer to output stream.
Definition: intrusive_ptr.h:400
auto operator>([[maybe_unused]] std::nullptr_t x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:292
auto operator>(T *x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:274
auto operator!=(const intrusive_ptr< T > &x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:175
auto operator>=(T *x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:364
auto operator<=(const intrusive_ptr< T > &x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:310
auto operator>=(const intrusive_ptr< T > &x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:355
auto operator<(const intrusive_ptr< T > &x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:220
auto operator<=(T *x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:319
auto operator>(const intrusive_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:301
auto operator>=(const intrusive_ptr< T > &x, U *y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:373
auto operator<(const intrusive_ptr< T > &x, U *y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:238
auto operator<([[maybe_unused]] std::nullptr_t x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:247
Intrusive pointer.
Definition: intrusive_ptr.h:21
auto operator==(const intrusive_ptr< T > &x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:130
auto operator!=(T *x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:184
auto operator>(const intrusive_ptr< T > &x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:265
auto operator<=([[maybe_unused]] std::nullptr_t x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:337
auto operator>=(const intrusive_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:391
auto operator==([[maybe_unused]] std::nullptr_t x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:157
auto operator<=(const intrusive_ptr< T > &x, U *y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:328
auto operator==(T *x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:139
auto operator>(const intrusive_ptr< T > &x, U *y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:283
auto operator==(const intrusive_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:166
auto operator<(T *x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:229
auto operator!=([[maybe_unused]] std::nullptr_t x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:202
auto operator==(const intrusive_ptr< T > &x, U *y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:148
auto operator!=(const intrusive_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:211
auto operator>=([[maybe_unused]] std::nullptr_t x, const intrusive_ptr< U > &y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:382
auto operator<=(const intrusive_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:346
auto operator!=(const intrusive_ptr< T > &x, U *y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:193
auto operator<(const intrusive_ptr< T > &x, [[maybe_unused]] std::nullptr_t y) noexcept -> bool
Comparison.
Definition: intrusive_ptr.h:256