Sleipnir C++ API
Loading...
Searching...
No Matches
intrusive_shared_ptr.hpp
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <concepts>
6#include <cstddef>
7#include <memory>
8#include <utility>
9
10namespace slp {
11
28template <typename T>
30 public:
31 template <typename>
32 friend class IntrusiveSharedPtr;
33
38
42 // NOLINTNEXTLINE (google-explicit-constructor)
44
51 explicit constexpr IntrusiveSharedPtr(T* ptr) noexcept : m_ptr{ptr} {
52 if (m_ptr != nullptr) {
53 inc_ref_count(m_ptr);
54 }
55 }
56
57 constexpr ~IntrusiveSharedPtr() {
58 if (m_ptr != nullptr) {
59 dec_ref_count(m_ptr);
60 }
61 }
62
69 : m_ptr{rhs.m_ptr} {
70 if (m_ptr != nullptr) {
71 inc_ref_count(m_ptr);
72 }
73 }
74
80 template <typename U>
81 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
82 // NOLINTNEXTLINE (google-explicit-constructor)
84 : m_ptr{rhs.m_ptr} {
85 if (m_ptr != nullptr) {
86 inc_ref_count(m_ptr);
87 }
88 }
89
96 // NOLINTNEXTLINE (google-explicit-constructor)
98 const IntrusiveSharedPtr<T>& rhs) noexcept {
99 if (m_ptr == rhs.m_ptr) {
100 return *this;
101 }
102
103 if (m_ptr != nullptr) {
104 dec_ref_count(m_ptr);
105 }
106
107 m_ptr = rhs.m_ptr;
108
109 if (m_ptr != nullptr) {
110 inc_ref_count(m_ptr);
111 }
112
113 return *this;
114 }
115
122 template <typename U>
123 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
124 // NOLINTNEXTLINE (google-explicit-constructor)
125 constexpr IntrusiveSharedPtr<T>& operator=(
126 const IntrusiveSharedPtr<U>& rhs) noexcept {
127 if (m_ptr == rhs.m_ptr) {
128 return *this;
129 }
130
131 if (m_ptr != nullptr) {
132 dec_ref_count(m_ptr);
133 }
134
135 m_ptr = rhs.m_ptr;
136
137 if (m_ptr != nullptr) {
138 inc_ref_count(m_ptr);
139 }
140
141 return *this;
142 }
143
150 : m_ptr{std::exchange(rhs.m_ptr, nullptr)} {}
151
157 template <typename U>
158 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
159 // NOLINTNEXTLINE (google-explicit-constructor)
161 : m_ptr{std::exchange(rhs.m_ptr, nullptr)} {}
162
170 IntrusiveSharedPtr<T>&& rhs) noexcept {
171 if (m_ptr == rhs.m_ptr) {
172 return *this;
173 }
174
175 std::swap(m_ptr, rhs.m_ptr);
176
177 return *this;
178 }
179
186 template <typename U>
187 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
188 constexpr IntrusiveSharedPtr<T>& operator=(
189 IntrusiveSharedPtr<U>&& rhs) noexcept {
190 if (m_ptr == rhs.m_ptr) {
191 return *this;
192 }
193
194 std::swap(m_ptr, rhs.m_ptr);
195
196 return *this;
197 }
198
204 constexpr T* get() const noexcept { return m_ptr; }
205
211 constexpr T& operator*() const noexcept { return *m_ptr; }
212
218 constexpr T* operator->() const noexcept { return m_ptr; }
219
225 explicit constexpr operator bool() const noexcept { return m_ptr != nullptr; }
226
234 friend constexpr bool operator==(const IntrusiveSharedPtr<T>& lhs,
235 const IntrusiveSharedPtr<T>& rhs) noexcept {
236 return lhs.m_ptr == rhs.m_ptr;
237 }
238
246 friend constexpr bool operator!=(const IntrusiveSharedPtr<T>& lhs,
247 const IntrusiveSharedPtr<T>& rhs) noexcept {
248 return lhs.m_ptr != rhs.m_ptr;
249 }
250
256 friend constexpr bool operator==(const IntrusiveSharedPtr<T>& lhs,
257 std::nullptr_t) noexcept {
258 return lhs.m_ptr == nullptr;
259 }
260
266 friend constexpr bool operator==(std::nullptr_t,
267 const IntrusiveSharedPtr<T>& rhs) noexcept {
268 return nullptr == rhs.m_ptr;
269 }
270
277 friend constexpr bool operator!=(const IntrusiveSharedPtr<T>& lhs,
278 std::nullptr_t) noexcept {
279 return lhs.m_ptr != nullptr;
280 }
281
288 friend constexpr bool operator!=(std::nullptr_t,
289 const IntrusiveSharedPtr<T>& rhs) noexcept {
290 return nullptr != rhs.m_ptr;
291 }
292
293 private:
294 T* m_ptr = nullptr;
295};
296
305template <typename T, typename... Args>
306IntrusiveSharedPtr<T> make_intrusive_shared(Args&&... args) {
307 return IntrusiveSharedPtr<T>{new T(std::forward<Args>(args)...)};
308}
309
321template <typename T, typename Alloc, typename... Args>
322IntrusiveSharedPtr<T> allocate_intrusive_shared(Alloc alloc, Args&&... args) {
323 auto ptr = std::allocator_traits<Alloc>::allocate(alloc, sizeof(T));
324 std::allocator_traits<Alloc>::construct(alloc, ptr,
325 std::forward<Args>(args)...);
326 return IntrusiveSharedPtr<T>{ptr};
327}
328
329} // namespace slp
Definition intrusive_shared_ptr.hpp:29
constexpr IntrusiveSharedPtr(IntrusiveSharedPtr< U > &&rhs) noexcept
Definition intrusive_shared_ptr.hpp:160
constexpr IntrusiveSharedPtr< T > & operator=(IntrusiveSharedPtr< T > &&rhs) noexcept
Definition intrusive_shared_ptr.hpp:169
friend constexpr bool operator==(std::nullptr_t, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:266
constexpr T * get() const noexcept
Definition intrusive_shared_ptr.hpp:204
constexpr IntrusiveSharedPtr(const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:68
constexpr T * operator->() const noexcept
Definition intrusive_shared_ptr.hpp:218
friend constexpr bool operator!=(const IntrusiveSharedPtr< T > &lhs, std::nullptr_t) noexcept
Definition intrusive_shared_ptr.hpp:277
friend constexpr bool operator==(const IntrusiveSharedPtr< T > &lhs, std::nullptr_t) noexcept
Definition intrusive_shared_ptr.hpp:256
friend constexpr bool operator==(const IntrusiveSharedPtr< T > &lhs, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:234
constexpr IntrusiveSharedPtr() noexcept=default
constexpr IntrusiveSharedPtr(T *ptr) noexcept
Definition intrusive_shared_ptr.hpp:51
friend constexpr bool operator!=(std::nullptr_t, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:288
constexpr IntrusiveSharedPtr(IntrusiveSharedPtr< T > &&rhs) noexcept
Definition intrusive_shared_ptr.hpp:149
constexpr T & operator*() const noexcept
Definition intrusive_shared_ptr.hpp:211
constexpr IntrusiveSharedPtr(const IntrusiveSharedPtr< U > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:83
friend constexpr bool operator!=(const IntrusiveSharedPtr< T > &lhs, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:246
constexpr IntrusiveSharedPtr< T > & operator=(const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:97