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
26template <typename T>
28 public:
29 template <typename>
30 friend class IntrusiveSharedPtr;
31
34
36 // NOLINTNEXTLINE (google-explicit-constructor)
38
43 explicit constexpr IntrusiveSharedPtr(T* ptr) noexcept : m_ptr{ptr} {
44 if (m_ptr != nullptr) {
45 inc_ref_count(m_ptr);
46 }
47 }
48
49 constexpr ~IntrusiveSharedPtr() {
50 if (m_ptr != nullptr) {
51 dec_ref_count(m_ptr);
52 }
53 }
54
59 : m_ptr{rhs.m_ptr} {
60 if (m_ptr != nullptr) {
61 inc_ref_count(m_ptr);
62 }
63 }
64
68 template <typename U>
69 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
70 // NOLINTNEXTLINE (google-explicit-constructor)
72 : m_ptr{rhs.m_ptr} {
73 if (m_ptr != nullptr) {
74 inc_ref_count(m_ptr);
75 }
76 }
77
82 // NOLINTNEXTLINE (google-explicit-constructor)
84 const IntrusiveSharedPtr<T>& rhs) noexcept {
85 if (m_ptr == rhs.m_ptr) {
86 return *this;
87 }
88
89 if (m_ptr != nullptr) {
90 dec_ref_count(m_ptr);
91 }
92
93 m_ptr = rhs.m_ptr;
94
95 if (m_ptr != nullptr) {
96 inc_ref_count(m_ptr);
97 }
98
99 return *this;
100 }
101
106 template <typename U>
107 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
108 // NOLINTNEXTLINE (google-explicit-constructor)
109 constexpr IntrusiveSharedPtr<T>& operator=(
110 const IntrusiveSharedPtr<U>& rhs) noexcept {
111 if (m_ptr == rhs.m_ptr) {
112 return *this;
113 }
114
115 if (m_ptr != nullptr) {
116 dec_ref_count(m_ptr);
117 }
118
119 m_ptr = rhs.m_ptr;
120
121 if (m_ptr != nullptr) {
122 inc_ref_count(m_ptr);
123 }
124
125 return *this;
126 }
127
132 : m_ptr{std::exchange(rhs.m_ptr, nullptr)} {}
133
137 template <typename U>
138 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
139 // NOLINTNEXTLINE (google-explicit-constructor)
141 : m_ptr{std::exchange(rhs.m_ptr, nullptr)} {}
142
148 IntrusiveSharedPtr<T>&& rhs) noexcept {
149 if (m_ptr == rhs.m_ptr) {
150 return *this;
151 }
152
153 std::swap(m_ptr, rhs.m_ptr);
154
155 return *this;
156 }
157
162 template <typename U>
163 requires(!std::same_as<T, U> && std::convertible_to<U*, T*>)
164 constexpr IntrusiveSharedPtr<T>& operator=(
165 IntrusiveSharedPtr<U>&& rhs) noexcept {
166 if (m_ptr == rhs.m_ptr) {
167 return *this;
168 }
169
170 std::swap(m_ptr, rhs.m_ptr);
171
172 return *this;
173 }
174
178 constexpr T* get() const noexcept { return m_ptr; }
179
183 constexpr T& operator*() const noexcept { return *m_ptr; }
184
188 constexpr T* operator->() const noexcept { return m_ptr; }
189
193 explicit constexpr operator bool() const noexcept { return m_ptr != nullptr; }
194
200 friend constexpr bool operator==(const IntrusiveSharedPtr<T>& lhs,
201 const IntrusiveSharedPtr<T>& rhs) noexcept {
202 return lhs.m_ptr == rhs.m_ptr;
203 }
204
210 friend constexpr bool operator!=(const IntrusiveSharedPtr<T>& lhs,
211 const IntrusiveSharedPtr<T>& rhs) noexcept {
212 return lhs.m_ptr != rhs.m_ptr;
213 }
214
218 friend constexpr bool operator==(const IntrusiveSharedPtr<T>& lhs,
219 std::nullptr_t) noexcept {
220 return lhs.m_ptr == nullptr;
221 }
222
226 friend constexpr bool operator==(std::nullptr_t,
227 const IntrusiveSharedPtr<T>& rhs) noexcept {
228 return nullptr == rhs.m_ptr;
229 }
230
235 friend constexpr bool operator!=(const IntrusiveSharedPtr<T>& lhs,
236 std::nullptr_t) noexcept {
237 return lhs.m_ptr != nullptr;
238 }
239
244 friend constexpr bool operator!=(std::nullptr_t,
245 const IntrusiveSharedPtr<T>& rhs) noexcept {
246 return nullptr != rhs.m_ptr;
247 }
248
249 private:
250 T* m_ptr = nullptr;
251};
252
259template <typename T, typename... Args>
260IntrusiveSharedPtr<T> make_intrusive_shared(Args&&... args) {
261 return IntrusiveSharedPtr<T>{new T(std::forward<Args>(args)...)};
262}
263
273template <typename T, typename Alloc, typename... Args>
274IntrusiveSharedPtr<T> allocate_intrusive_shared(Alloc alloc, Args&&... args) {
275 auto ptr = std::allocator_traits<Alloc>::allocate(alloc, sizeof(T));
276 std::allocator_traits<Alloc>::construct(alloc, ptr,
277 std::forward<Args>(args)...);
278 return IntrusiveSharedPtr<T>{ptr};
279}
280
281} // namespace slp
Definition intrusive_shared_ptr.hpp:27
constexpr IntrusiveSharedPtr(IntrusiveSharedPtr< U > &&rhs) noexcept
Definition intrusive_shared_ptr.hpp:140
constexpr IntrusiveSharedPtr< T > & operator=(IntrusiveSharedPtr< T > &&rhs) noexcept
Definition intrusive_shared_ptr.hpp:147
friend constexpr bool operator==(std::nullptr_t, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:226
constexpr T * get() const noexcept
Definition intrusive_shared_ptr.hpp:178
constexpr IntrusiveSharedPtr(const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:58
constexpr T * operator->() const noexcept
Definition intrusive_shared_ptr.hpp:188
friend constexpr bool operator!=(const IntrusiveSharedPtr< T > &lhs, std::nullptr_t) noexcept
Definition intrusive_shared_ptr.hpp:235
friend constexpr bool operator==(const IntrusiveSharedPtr< T > &lhs, std::nullptr_t) noexcept
Definition intrusive_shared_ptr.hpp:218
friend constexpr bool operator==(const IntrusiveSharedPtr< T > &lhs, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:200
constexpr IntrusiveSharedPtr() noexcept=default
Constructs an empty intrusive shared pointer.
constexpr IntrusiveSharedPtr(T *ptr) noexcept
Definition intrusive_shared_ptr.hpp:43
friend constexpr bool operator!=(std::nullptr_t, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:244
constexpr IntrusiveSharedPtr(IntrusiveSharedPtr< T > &&rhs) noexcept
Definition intrusive_shared_ptr.hpp:131
constexpr T & operator*() const noexcept
Definition intrusive_shared_ptr.hpp:183
constexpr IntrusiveSharedPtr(const IntrusiveSharedPtr< U > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:71
friend constexpr bool operator!=(const IntrusiveSharedPtr< T > &lhs, const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:210
constexpr IntrusiveSharedPtr< T > & operator=(const IntrusiveSharedPtr< T > &rhs) noexcept
Definition intrusive_shared_ptr.hpp:83