libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rc_ptr.h
Go to the documentation of this file.
1// Copyright 2025 owent
2// Licenses under the MIT License
3// @note This is a smart pointer class that is compatible with std::shared_ptr, but it is more lightweight and do not
4// use atomic operation for reference counting. It is designed for single thread usage.
5// @note We support all APIs of std::shared_ptr in C++14, and partly APIs of std::shared_ptr in C++17/20/26.
6
7#pragma once
8
9#include <cstdint>
10#include <functional>
11#include <memory>
12#include <ostream>
13#include <type_traits>
14#include <utility>
15
16#ifdef __cpp_impl_three_way_comparison
17# include <compare>
18#endif
19
21#include "libcopp/utils/config/libcopp_build_features.h"
24
25LIBCOPP_COPP_NAMESPACE_BEGIN
26namespace memory {
27
28template <class T>
29class LIBCOPP_COPP_API_HEAD_ONLY weak_rc_ptr;
30
31template <class T>
32class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr;
33
34template <class T>
35class LIBCOPP_COPP_API_HEAD_ONLY enable_shared_rc_from_this;
36
38 public:
39 constexpr __rc_ptr_counted_data_base() noexcept : use_count_(1), weak_count_(1) {}
40
41 LIBCOPP_COPP_API virtual ~__rc_ptr_counted_data_base() noexcept;
42
43 // Called when use_count_ drops to zero, to release the resources
44 // managed by *this.
45 virtual void dispose() noexcept = 0;
46
47 // Called when weak_count_ drops to zero.
48 virtual void destroy() noexcept = 0;
49
50 // Donohting when with -fno-exception/EHsc-
51 LIBCOPP_COPP_API static void throw_bad_weak_ptr();
52
53 // Increment the use count if it is non-zero, throw otherwise.
54 LIBCOPP_UTIL_FORCEINLINE void add_ref() {
55 if (!add_ref_nothrow()) {
56 throw_bad_weak_ptr();
57 }
58 }
59
60 // Increment the use count if it is non-zero.
62 if (use_count_ == 0) {
63 return false;
64 }
65
66 ++use_count_;
67 return true;
68 }
69
70 // Decrement the use count.
72 if (--use_count_ == 0) {
73 dispose();
74 if (--weak_count_ == 0) {
75 destroy();
76 }
77 }
78 }
79
80 // Increment the weak count.
81 LIBCOPP_UTIL_FORCEINLINE void weak_add_ref() noexcept { ++weak_count_; }
82
83 // Decrement the weak count.
85 if (--weak_count_ == 0) {
86 destroy();
87 }
88 }
89
90 LIBCOPP_UTIL_FORCEINLINE std::size_t use_count() const noexcept { return use_count_; }
91
92 private:
95
96 private:
97 std::size_t use_count_;
98 std::size_t weak_count_;
99};
100
105template <class T>
106class LIBCOPP_COPP_API_HEAD_ONLY __rc_ptr_counted_data_default final : public __rc_ptr_counted_data_base {
107 public:
108 explicit __rc_ptr_counted_data_default(T* p) noexcept : ptr_(p) {}
109
110 void dispose() noexcept override {
111 using alloc_type = ::std::allocator<nostd::remove_cv_t<T>>;
112 using alloc_traits = ::std::allocator_traits<alloc_type>;
113 alloc_type alloc;
114 if (nullptr != ptr_) {
115 alloc_traits::destroy(alloc, const_cast<nostd::remove_cv_t<T>*>(ptr_));
116 alloc_traits::deallocate(alloc, const_cast<nostd::remove_cv_t<T>*>(ptr_), 1);
117 ptr_ = nullptr;
118 }
119 }
120
121 void destroy() noexcept override {
122 using alloc_type = ::std::allocator<__rc_ptr_counted_data_default<T>>;
123 alloc_type alloc;
124 allocated_ptr<alloc_type> guard_ptr{alloc, this};
126 }
127
128 private:
130};
131
137template <class T>
138class LIBCOPP_COPP_API_HEAD_ONLY __rc_ptr_counted_data_inplace final : public __rc_ptr_counted_data_base {
139 public:
140 template <class... Args>
141 explicit __rc_ptr_counted_data_inplace(Args&&... args) {
142 using alloc_type = ::std::allocator<nostd::remove_cv_t<T>>;
143 using alloc_traits = ::std::allocator_traits<alloc_type>;
144 alloc_type alloc;
145 alloc_traits::construct(alloc, const_cast<nostd::remove_cv_t<T>*>(ptr()), std::forward<Args>(args)...);
146 }
147
148 void dispose() noexcept override {
149 using alloc_type = ::std::allocator<nostd::remove_cv_t<T>>;
150 using alloc_traits = ::std::allocator_traits<alloc_type>;
151 alloc_type alloc;
152 alloc_traits::destroy(alloc, const_cast<nostd::remove_cv_t<T>*>(ptr()));
153 }
154
155 void destroy() noexcept override {
156 using alloc_type = ::std::allocator<__rc_ptr_counted_data_inplace<T>>;
157 using alloc_traits = ::std::allocator_traits<alloc_type>;
158 alloc_type alloc;
159 allocated_ptr<alloc_type> guard_ptr{alloc, this};
160 alloc_traits::destroy(alloc, this);
161 }
162
163 inline T* ptr() noexcept { return reinterpret_cast<T*>(addr()); }
164
165 private:
166 inline void* addr() { return reinterpret_cast<void*>(&storage_); }
167
168 nostd::aligned_storage_t<sizeof(T), alignof(T)> storage_;
169};
170
177template <class T, class Alloc>
178class LIBCOPP_COPP_API_HEAD_ONLY __rc_ptr_counted_data_inplace_alloc final : public __rc_ptr_counted_data_base {
179 public:
180 template <class AllocInput, class... Args>
181 explicit __rc_ptr_counted_data_inplace_alloc(AllocInput&& a, Args&&... args) {
182 // construct allocator first
183 using alloc_type_a = typename ::std::allocator_traits<Alloc>::template rebind_alloc<Alloc>;
184 using alloc_traits_a = ::std::allocator_traits<alloc_type_a>;
185 alloc_type_a aa;
186 alloc_traits_a::construct(aa, alloc_ptr(), std::forward<AllocInput>(a));
187
188// and then value
189#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
190 try {
191#endif
192 using alloc_traits_v = ::std::allocator_traits<Alloc>;
193 alloc_traits_v::construct(*alloc_ptr(), const_cast<nostd::remove_cv_t<T>*>(value_ptr()),
194 std::forward<Args>(args)...);
195#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
196 } catch (...) {
197 alloc_traits_a::destroy(aa, alloc_ptr());
198 throw;
199 }
200#endif
201 }
202
203 void dispose() noexcept override {
204 using alloc_traits_v = ::std::allocator_traits<Alloc>;
205 alloc_traits_v::destroy(*alloc_ptr(), const_cast<nostd::remove_cv_t<T>*>(value_ptr()));
206 }
207
208 void destroy() noexcept override {
209 using alloc_type_self =
210 typename ::std::allocator_traits<Alloc>::template rebind_alloc<__rc_ptr_counted_data_inplace_alloc<T, Alloc>>;
211 using alloc_traits_self = ::std::allocator_traits<alloc_type_self>;
212
213#if defined(__GNUC__) && !defined(__clang__) && !defined(__apple_build_version__)
214# if (__GNUC__ * 100 + __GNUC_MINOR__ * 10) >= 460
215# pragma GCC diagnostic push
216# endif
217# pragma GCC diagnostic ignored "-Wuninitialized"
218#elif defined(__clang__) || defined(__apple_build_version__)
219# pragma clang diagnostic push
220# pragma clang diagnostic ignored "-Wuninitialized"
221#endif
222
223 // destroy allocator first
224 using alloc_type_a = typename ::std::allocator_traits<Alloc>::template rebind_alloc<Alloc>;
225 using alloc_traits_a = ::std::allocator_traits<alloc_type_a>;
226 LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED alloc_type_a aa{*alloc_ptr()};
227 alloc_traits_a::destroy(aa, alloc_ptr());
228
229 // then, destroy and deallocate this
230 LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED alloc_type_self as{*alloc_ptr()};
231 allocated_ptr<alloc_type_self> guard_ptr{as, this};
232 alloc_traits_self::destroy(as, this);
233
234#if defined(__GNUC__) && !defined(__clang__) && !defined(__apple_build_version__)
235# if (__GNUC__ * 100 + __GNUC_MINOR__ * 10) >= 460
236# pragma GCC diagnostic pop
237# endif
238#elif defined(__clang__) || defined(__apple_build_version__)
239# pragma clang diagnostic pop
240#endif
241 }
242
243 inline T* value_ptr() noexcept { return reinterpret_cast<T*>(value_addr()); }
244 inline Alloc* alloc_ptr() noexcept { return reinterpret_cast<Alloc*>(alloc_addr()); }
245
246 private:
247 inline void* value_addr() { return reinterpret_cast<void*>(&storage_); }
248 inline void* alloc_addr() { return reinterpret_cast<void*>(&alloc_); }
249
250 nostd::aligned_storage_t<sizeof(T), alignof(T)> storage_;
251 nostd::aligned_storage_t<sizeof(Alloc), alignof(Alloc)> alloc_;
252};
253
258template <class T, class Deleter>
259class LIBCOPP_COPP_API_HEAD_ONLY __rc_ptr_counted_data_with_deleter final : public __rc_ptr_counted_data_base {
260 public:
261 template <class DeleterInput>
262 inline __rc_ptr_counted_data_with_deleter(T* p, DeleterInput&& d) noexcept
263 : ptr_(p), deleter_(std::forward<DeleterInput>(d)) {}
264
265 void dispose() noexcept override { deleter_(ptr_); }
266
267 void destroy() noexcept override {
268 using alloc_type = ::std::allocator<__rc_ptr_counted_data_with_deleter<T, Deleter>>;
269 using alloc_traits = ::std::allocator_traits<alloc_type>;
270 alloc_type alloc;
271
272 // deallocate this after function finished
273 allocated_ptr<alloc_type> guard_ptr{alloc, this};
274 alloc_traits::destroy(alloc, this);
275 }
276
277 private:
279 Deleter deleter_;
280};
281
286template <class T, class Deleter, class Alloc>
287class LIBCOPP_COPP_API_HEAD_ONLY __rc_ptr_counted_data_with_deleter_allocator final
289 public:
290 template <class DeleterInput, class AllocInput>
291 inline __rc_ptr_counted_data_with_deleter_allocator(T* p, DeleterInput&& d, AllocInput&& a) noexcept
292 : ptr_(p), deleter_(std::forward<DeleterInput>(d)), alloc_(std::forward<AllocInput>(a)) {}
293
294 void dispose() noexcept override { deleter_(ptr_); }
295
296 void destroy() noexcept override {
297 using alloc_type = typename ::std::allocator_traits<Alloc>::template rebind_alloc<
299 using alloc_traits = ::std::allocator_traits<alloc_type>;
300 alloc_type alloc{alloc_};
301
302 // deallocate this after function finished
303 allocated_ptr<alloc_type> guard_ptr{alloc, this};
304 alloc_traits::destroy(alloc, this);
305 }
306
307 private:
309 Deleter deleter_;
310 Alloc alloc_;
311};
312
313template <class T>
314struct LIBCOPP_COPP_API_HEAD_ONLY __strong_rc_default_alloc_shared_tag {};
315
316template <class T>
317struct LIBCOPP_COPP_API_HEAD_ONLY __strong_rc_with_alloc_shared_tag {};
318
319template <class T>
320class LIBCOPP_COPP_API_HEAD_ONLY __weak_rc_counter;
321
322template <class T>
323class LIBCOPP_COPP_API_HEAD_ONLY __strong_rc_counter {
324 // Prevent __strong_rc_default_alloc_shared_tag and __strong_rc_with_alloc_shared_tag from matching the shared_ptr(P,
325 // D) ctor.
326 template <class>
328 using type = void;
329 };
330
331 template <class Y>
333
334 template <class Y>
336
337 public:
338 constexpr __strong_rc_counter() noexcept : pi_(nullptr) {}
339
340 template <class Y>
341 explicit __strong_rc_counter(Y* p) : pi_(nullptr) {
342 using alloc_type = ::std::allocator<__rc_ptr_counted_data_default<Y>>;
343 using alloc_traits = ::std::allocator_traits<alloc_type>;
344 alloc_type alloc;
345 auto guard = allocate_guarded(alloc);
346#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
347 try {
348#endif
349 alloc_traits::construct(alloc, guard.get(), p);
350 pi_ = guard.get();
351 guard = nullptr;
352
353#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
354 } catch (...) {
355 using alloc_type_y = ::std::allocator<nostd::remove_cv_t<Y>>;
356 using alloc_traits_y = ::std::allocator_traits<alloc_type_y>;
357 alloc_type_y alloc_y;
358
359 if (nullptr != p) {
360 alloc_traits_y::destroy(alloc_y, p);
361 alloc_traits_y::deallocate(alloc_y, const_cast<nostd::remove_cv_t<Y>*>(p), 1);
362 }
363 throw;
364 }
365#endif
366 }
367
368 template <class Y, class Deleter, class = typename __not_alloc_shared_tag<nostd::remove_cvref_t<Deleter>>::type>
369 __strong_rc_counter(Y* p, Deleter&& d) : pi_(nullptr) {
370 using alloc_type = ::std::allocator<__rc_ptr_counted_data_with_deleter<Y, nostd::remove_cvref_t<Deleter>>>;
371 using alloc_traits = ::std::allocator_traits<alloc_type>;
372 alloc_type alloc;
373 auto guard = allocate_guarded(alloc);
374#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
375 try {
376#endif
377 alloc_traits::construct(alloc, guard.get(), p, std::forward<Deleter>(d));
378 pi_ = guard.get();
379 guard = nullptr;
380#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
381 } catch (...) {
382 d(p);
383 throw;
384 }
385#endif
386 }
387
388 template <class Y, class Deleter, class Alloc,
389 class = typename __not_alloc_shared_tag<nostd::remove_cvref_t<Deleter>>::type>
390 __strong_rc_counter(Y* p, Deleter&& d, Alloc&& a) : pi_(nullptr) {
391 using origin_alloc_traits = ::std::allocator_traits<nostd::remove_cvref_t<Alloc>>;
392 using alloc_type = typename origin_alloc_traits::template rebind_alloc<
394 using alloc_traits = ::std::allocator_traits<alloc_type>;
395 alloc_type alloc{a};
396 auto guard = allocate_guarded(alloc);
397#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
398 try {
399#endif
400 alloc_traits::construct(alloc, guard.get(), p, std::forward<Deleter>(d), std::forward<Alloc>(a));
401 pi_ = guard.get();
402 guard = nullptr;
403#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
404 } catch (...) {
405 d(p);
406 throw;
407 }
408#endif
409 }
410
411 template <class... Args>
412 __strong_rc_counter(T*& __p, __strong_rc_default_alloc_shared_tag<T>, Args&&... args) : pi_(nullptr) {
413 using alloc_type = ::std::allocator<__rc_ptr_counted_data_inplace<T>>;
414 using alloc_traits = ::std::allocator_traits<alloc_type>;
415 alloc_type alloc;
416 auto guard = allocate_guarded(alloc);
417
418#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
419 try {
420#endif
421 alloc_traits::construct(alloc, guard.get(), std::forward<Args>(args)...);
422 pi_ = guard.get();
423 __p = guard.get()->ptr();
424 guard = nullptr;
425#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
426 } catch (...) {
427 throw;
428 }
429#endif
430 }
431
432 template <class Alloc, class... Args>
433 __strong_rc_counter(T*& __p, __strong_rc_with_alloc_shared_tag<T>, Alloc&& a, Args&&... args) : pi_(nullptr) {
434 using origin_alloc_traits = ::std::allocator_traits<nostd::remove_cvref_t<Alloc>>;
435
436 using alloc_type = typename origin_alloc_traits::template rebind_alloc<
438 using alloc_traits = ::std::allocator_traits<alloc_type>;
439 alloc_type alloc{a};
440 auto guard = allocate_guarded(alloc);
441
442#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
443 try {
444#endif
445 alloc_traits::construct(alloc, guard.get(), std::forward<Alloc>(a), std::forward<Args>(args)...);
446 pi_ = guard.get();
447 __p = guard.get()->value_ptr();
448 guard = nullptr;
449#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
450 } catch (...) {
451 throw;
452 }
453#endif
454 }
455
456 template <class UT, class UDeleter>
457 explicit __strong_rc_counter(std::unique_ptr<UT, UDeleter>&& r) : pi_(nullptr) {
458 if (r.get() == nullptr) {
459 return;
460 }
461
462 using alloc_type = ::std::allocator<__rc_ptr_counted_data_with_deleter<UT, nostd::remove_cvref_t<UDeleter>>>;
463 using alloc_traits = ::std::allocator_traits<alloc_type>;
464 alloc_type alloc;
465 auto guard = allocate_guarded(alloc);
466
467#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
468 try {
469#endif
470 alloc_traits::construct(alloc, guard.get(), r.get(), std::forward<UDeleter>(r.get_deleter()));
471 pi_ = guard.get();
472 guard = nullptr;
473
474 r.release();
475#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
476 } catch (...) {
477 throw;
478 }
479#endif
480 }
481
483
484 __strong_rc_counter(const __weak_rc_counter<T>& w, std::nothrow_t) noexcept;
485
487 if (nullptr != pi_) {
488 pi_->release();
489 }
490 }
491
492 __strong_rc_counter(const __strong_rc_counter& r) noexcept : pi_(r.pi_) {
493 if (nullptr != pi_) {
494 pi_->add_ref();
495 }
496 }
497
498 __strong_rc_counter(__strong_rc_counter&& r) noexcept : pi_(r.pi_) { r.pi_ = nullptr; }
499
500 template <class Y>
501 __strong_rc_counter(const __strong_rc_counter<Y>& r) noexcept : pi_(r.pi_) {
502 if (nullptr != pi_) {
503 pi_->add_ref();
504 }
505 }
506
507 template <class Y>
508 __strong_rc_counter(__strong_rc_counter<Y>&& r) noexcept : pi_(r.pi_) {
509 r.pi_ = nullptr;
510 }
511
513 if (pi_ != r.pi_) {
514 __rc_ptr_counted_data_base* origin_pi = pi_;
515
516 pi_ = r.pi_;
517 if (nullptr != pi_) {
518 pi_->add_ref();
519 }
520 if (nullptr != origin_pi) {
521 origin_pi->release();
522 }
523 }
524 return *this;
525 }
526
528 if (pi_ != r.pi_) {
529 __rc_ptr_counted_data_base* origin_pi = pi_;
530 pi_ = r.pi_;
531 r.pi_ = nullptr;
532
533 if (nullptr != origin_pi) {
534 origin_pi->release();
535 }
536 }
537 return *this;
538 }
539
540 inline void swap(__strong_rc_counter& r) noexcept {
542 pi_ = r.pi_;
543 r.pi_ = tmp;
544 }
545
546 template <class Y>
547 inline void swap(__strong_rc_counter<Y>& r) noexcept {
549 pi_ = r.pi_;
550 r.pi_ = tmp;
551 }
552
553 inline std::size_t use_count() const noexcept { return (nullptr != pi_) ? pi_->use_count() : 0; }
554
555 inline __rc_ptr_counted_data_base* ref_counter() const noexcept { return pi_; }
556
557 private:
558 template <class>
559 friend class LIBCOPP_COPP_API_HEAD_ONLY __strong_rc_counter;
560
562};
563
564template <class T>
565class LIBCOPP_COPP_API_HEAD_ONLY __weak_rc_counter {
566 public:
567 constexpr __weak_rc_counter() noexcept : pi_(nullptr) {}
568
569 template <class Y>
570 explicit __weak_rc_counter(const __strong_rc_counter<Y>& other) noexcept : pi_(other.ref_counter()) {
571 if (nullptr != pi_) {
572 pi_->weak_add_ref();
573 }
574 }
575
577 if (nullptr != pi_) {
578 pi_->weak_release();
579 }
580 }
581
582 __weak_rc_counter(const __weak_rc_counter& r) noexcept : pi_(r.pi_) {
583 if (nullptr != pi_) {
584 pi_->weak_add_ref();
585 }
586 }
587
588 __weak_rc_counter(__weak_rc_counter&& r) noexcept : pi_(r.pi_) { r.pi_ = nullptr; }
589
590 template <class Y>
591 __weak_rc_counter(const __weak_rc_counter<Y>& r) noexcept : pi_(r.pi_) {
592 if (nullptr != pi_) {
593 pi_->weak_add_ref();
594 }
595 }
596
597 template <class Y>
598 __weak_rc_counter(__weak_rc_counter<Y>&& r) noexcept : pi_(r.pi_) {
599 r.pi_ = nullptr;
600 }
601
603 if (pi_ != r.pi_) {
604 __rc_ptr_counted_data_base* origin_pi = pi_;
605 pi_ = r.pi_;
606 if (nullptr != pi_) {
607 pi_->weak_add_ref();
608 }
609
610 if (nullptr != origin_pi) {
611 origin_pi->weak_release();
612 }
613 }
614 return *this;
615 }
616
618 if (pi_ != r.pi_) {
619 __rc_ptr_counted_data_base* origin_pi = pi_;
620 pi_ = r.pi_;
621 r.pi_ = nullptr;
622
623 if (nullptr != origin_pi) {
624 origin_pi->weak_release();
625 }
626 }
627 return *this;
628 }
629
630 inline void swap(__weak_rc_counter& r) noexcept {
632 pi_ = r.pi_;
633 r.pi_ = tmp;
634 }
635
636 template <class Y>
637 inline void swap(__weak_rc_counter<Y>& r) noexcept {
639 pi_ = r.pi_;
640 r.pi_ = tmp;
641 }
642
643 inline std::size_t use_count() const noexcept { return (nullptr != pi_) ? pi_->use_count() : 0; }
644
645 inline __rc_ptr_counted_data_base* ref_counter() const noexcept { return pi_; }
646
647 private:
648 template <class>
649 friend class LIBCOPP_COPP_API_HEAD_ONLY __weak_rc_counter;
650
652};
653
654template <class T>
656 if (nullptr == pi_ || !pi_->add_ref_nothrow()) {
657 pi_ = nullptr;
659 }
660}
661
662template <class T>
664 : pi_(w.ref_counter()) {
665 if (nullptr != pi_ && !pi_->add_ref_nothrow()) {
666 pi_ = nullptr;
667 }
668}
669
673template <class T, bool = std::is_array<T>::value, bool = std::is_void<T>::value>
674class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr_access {
675 public:
676 using element_type = T;
677
678 inline element_type& operator*() const noexcept {
679 element_type* ret = get();
680#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
681 if (nullptr == ret) {
682 __rc_ptr_counted_data_base::throw_bad_weak_ptr();
683 }
684#endif
685 return *ret;
686 }
687
688 inline element_type* operator->() const noexcept {
689 element_type* ret = get();
690#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
691 if (nullptr == ret) {
692 __rc_ptr_counted_data_base::throw_bad_weak_ptr();
693 }
694#endif
695 return ret;
696 }
697
698 private:
699 inline element_type* get() const noexcept { return static_cast<const strong_rc_ptr<T>*>(this)->get(); }
700};
701
705template <class T>
706class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr_access<T, false, true> {
707 public:
708 using element_type = T;
709
710 inline element_type* operator->() const noexcept {
711 element_type* ret = get();
712#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
713 if (nullptr == ret) {
714 __rc_ptr_counted_data_base::throw_bad_weak_ptr();
715 }
716#endif
717 return ret;
718 }
719
720 private:
721 inline element_type* get() const noexcept { return static_cast<const strong_rc_ptr<T>*>(this)->get(); }
722};
723
724template <class T>
725class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr_access<T, true, false> {
726 public:
727 using element_type = nostd::remove_extent_t<T>;
728
729 element_type& operator[](std::ptrdiff_t __i) const noexcept {
730 element_type* ret = get();
731#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
732 if (nullptr == ret) {
733 __rc_ptr_counted_data_base::throw_bad_weak_ptr();
734 }
735#endif
736 return ret[__i];
737 }
738
739 private:
740 inline element_type* get() const noexcept { return static_cast<const strong_rc_ptr<T>*>(this)->get(); }
741};
742
748template <class T1, class T2, class T3>
749LIBCOPP_COPP_API_HEAD_ONLY inline void __enable_shared_from_this_with(const __strong_rc_counter<T1>* __n,
750 const T2* __py,
752 if (nullptr != __p) {
753 __p->__internal_weak_assign(const_cast<T2*>(__py), *__n);
754 }
755}
756
757// All ptr shares the same lifetime.
758template <class T1, class T2, class T3, size_t T3SIZE>
759LIBCOPP_COPP_API_HEAD_ONLY inline void __enable_shared_from_this_with(
760 const __strong_rc_counter<T1>* __n, const T2* __py, const enable_shared_rc_from_this<T3[T3SIZE]>* __p) {
761 if (nullptr != __p) {
762 for (auto& p : *__p) {
763 p->__internal_weak_assign(const_cast<T2*>(__py), *__n);
764 }
765 }
766}
767
768#ifdef _MANAGED
769
770// Avoid C4793, ... causes native code generation
771
772struct __sp_any_pointer {
773 template <class T>
774 __sp_any_pointer(T*) {} // NOLINT: runtime/explicit
775};
776
777LIBCOPP_COPP_API_HEAD_ONLY inline void __enable_shared_from_this_with(__sp_any_pointer, __sp_any_pointer,
778 __sp_any_pointer) {}
779
780#else // _MANAGED
781
782LIBCOPP_COPP_API_HEAD_ONLY inline void __enable_shared_from_this_with(...) {}
783
784#endif // _MANAGED
785
790template <class T>
791class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr : public strong_rc_ptr_access<T> {
792 public:
793 using element_type = nostd::remove_extent_t<T>;
795
796 // Allow nostd::nullable<T> to be used as a strong_rc_ptr<T>
799
800 public:
801 constexpr strong_rc_ptr() noexcept : ptr_(nullptr), ref_counter_() {}
802
803 constexpr strong_rc_ptr(std::nullptr_t) noexcept : ptr_(nullptr), ref_counter_() {}
804
805 template <class Y>
806 strong_rc_ptr(Y* ptr) noexcept // NOLINT: runtime/explicit
807 : ptr_(ptr), ref_counter_(ptr) {
808 static_assert(!std::is_void<Y>::value, "incomplete type");
809 static_assert(sizeof(Y) > 0, "incomplete type");
810 __enable_shared_from_this_with(&ref_counter_, ptr, ptr);
811 }
812
813 template <class Y, class Deleter>
814 strong_rc_ptr(Y* ptr, Deleter d) : ptr_(ptr), ref_counter_(ptr, std::move(d)) {
815 __enable_shared_from_this_with(&ref_counter_, ptr, ptr);
816 }
817
818 template <class Y, class Deleter, class Alloc>
819 strong_rc_ptr(Y* ptr, Deleter d, Alloc a) : ptr_(ptr), ref_counter_(ptr, std::move(d), std::move(a)) {
820 __enable_shared_from_this_with(&ref_counter_, ptr, ptr);
821 }
822
823 template <class Deleter>
824 strong_rc_ptr(std::nullptr_t ptr, Deleter d) : ptr_(ptr), ref_counter_(ptr, std::move(d)) {}
825
826 template <class Y, class Deleter, class Alloc>
827 strong_rc_ptr(std::nullptr_t ptr, Deleter d, Alloc a) : ptr_(ptr), ref_counter_(ptr, std::move(d), std::move(a)) {}
828
829 template <class Y>
830 strong_rc_ptr(const strong_rc_ptr<Y>& other) noexcept : ptr_(other.ptr_), ref_counter_(other.ref_counter_) {}
831
832 template <class Y>
833 strong_rc_ptr(strong_rc_ptr<Y>&& other) noexcept : ptr_(other.ptr_), ref_counter_() {
834 ref_counter_.swap(other.ref_counter_);
835 other.ptr_ = nullptr;
836 }
837
838 template <class Y>
839 strong_rc_ptr(const strong_rc_ptr<Y>& other, element_type* ptr) noexcept
840 : ptr_(ptr), ref_counter_(other.ref_counter_) {}
841
842 template <class Y>
843 strong_rc_ptr(strong_rc_ptr<Y>&& other, element_type* ptr) noexcept : ptr_(ptr), ref_counter_() {
844 ref_counter_.swap(other.ref_counter_);
845 other.ptr_ = nullptr;
846 }
847
848 strong_rc_ptr(const weak_rc_ptr<T>& other) // NOLINT: runtime/explicit
849 : ptr_(nullptr), ref_counter_(other.ref_counter_) {
850 ptr_ = other.ptr_;
851 }
852
853 strong_rc_ptr(const weak_rc_ptr<T>& other, std::nothrow_t) noexcept
854 : ptr_(nullptr), ref_counter_(other.ref_counter_, std::nothrow) {
855 ptr_ = other.use_count() > 0 ? other.ptr_ : nullptr;
856 }
857
858 template <class Y>
859 strong_rc_ptr(const weak_rc_ptr<Y>& other) // NOLINT: runtime/explicit
860 : ptr_(nullptr), ref_counter_(other.ref_counter_) {
861 ptr_ = other.ptr_;
862 }
863
864 template <class Y, class Deleter>
865 strong_rc_ptr(std::unique_ptr<Y, Deleter>&& other) // NOLINT: runtime/explicit
866 : ptr_(other.get()), ref_counter_() {
867 ref_counter_ = __strong_rc_counter<element_type>{std::move(other)};
868 __enable_shared_from_this_with(&ref_counter_, ptr_, ptr_);
869 }
870
876 template <class... Args>
877 strong_rc_ptr(__strong_rc_default_alloc_shared_tag<T> __tag, Args&&... args) // NOLINT: runtime/explicit
878 : ptr_(nullptr), ref_counter_(ptr_, __tag, std::forward<Args>(args)...) {
879 __enable_shared_from_this_with(&ref_counter_, ptr_, ptr_);
880 }
881
887 template <class... Args>
888 strong_rc_ptr(__strong_rc_with_alloc_shared_tag<T> __tag, Args&&... args) // NOLINT: runtime/explicit
889 : ptr_(nullptr), ref_counter_(ptr_, __tag, std::forward<Args>(args)...) {
890 __enable_shared_from_this_with(&ref_counter_, ptr_, ptr_);
891 }
892
893 ~strong_rc_ptr() noexcept = default;
894 explicit strong_rc_ptr(const strong_rc_ptr&) noexcept = default;
895 strong_rc_ptr& operator=(const strong_rc_ptr&) noexcept = default;
896
897 explicit strong_rc_ptr(strong_rc_ptr&& other) noexcept : ptr_(other.ptr_), ref_counter_() {
898 ref_counter_.swap(other.ref_counter_);
899 other.ptr_ = nullptr;
900 }
901
902 inline strong_rc_ptr& operator=(strong_rc_ptr&& other) noexcept {
903 strong_rc_ptr{std::move(other)}.swap(*this);
904 return *this;
905 }
906
907 template <class Y>
908 inline strong_rc_ptr& operator=(const strong_rc_ptr<Y>& other) noexcept {
909 ptr_ = other.ptr_;
910 ref_counter_ = other.ref_counter_;
911 return *this;
912 }
913
914 template <class Y>
915 inline strong_rc_ptr& operator=(strong_rc_ptr<Y>&& other) noexcept {
916 strong_rc_ptr{std::move(other)}.swap(*this);
917 return *this;
918 }
919
920 template <class Y, class Deleter>
921 inline strong_rc_ptr& operator=(std::unique_ptr<Y, Deleter>&& other) {
922 strong_rc_ptr{std::move(other)}.swap(*this);
923 return *this;
924 }
925
926 inline void reset() noexcept { strong_rc_ptr().swap(*this); }
927
928 template <class Y>
929 inline void reset(Y* ptr) noexcept {
930 if (ptr_ == ptr && ptr != nullptr) {
931 return;
932 }
933
934 strong_rc_ptr{ptr}.swap(*this);
935 }
936
937 template <class Y, class Deleter>
938 inline void reset(Y* ptr, Deleter d) noexcept {
939 strong_rc_ptr{ptr, std::move(d)}.swap(*this);
940 }
941
942 template <class Y, class Deleter, class Alloc>
943 inline void reset(Y* ptr, Deleter d, Alloc a) noexcept {
944 strong_rc_ptr{ptr, std::move(d), std::move(a)}.swap(*this);
945 }
946
947 inline void swap(strong_rc_ptr& other) noexcept {
948 std::swap(ptr_, other.ptr_);
949 ref_counter_.swap(other.ref_counter_);
950 }
951
952 inline element_type* get() const noexcept { return ptr_; }
953
954 inline std::size_t use_count() const noexcept { return ref_counter_.use_count(); }
955
956 inline bool unique() const noexcept { return ref_counter_.use_count() == 1; }
957
958 inline explicit operator bool() const noexcept { return nullptr != get(); }
959
960 template <class Y>
961 inline bool owner_before(strong_rc_ptr<Y> const& r) const noexcept {
962 return std::less<__rc_ptr_counted_data_base*>()(ref_counter_.ref_counter(), r.ref_counter_.ref_counter());
963 }
964
965 template <class Y>
966 inline bool owner_before(weak_rc_ptr<Y> const& r) const noexcept {
967 return std::less<__rc_ptr_counted_data_base*>()(ref_counter_.ref_counter(), r.ref_counter_.ref_counter());
968 }
969
970 template <class Y>
971 inline bool owner_equal(strong_rc_ptr<Y> const& r) const noexcept {
972 return ref_counter_.ref_counter() == r.ref_counter_.ref_counter();
973 }
974
975 template <class Y>
976 inline bool owner_equal(weak_rc_ptr<Y> const& r) const noexcept {
977 return ref_counter_.ref_counter() == r.ref_counter_.ref_counter();
978 }
979
980 std::size_t owner_hash() const noexcept {
981 return std::hash<__rc_ptr_counted_data_base*>()(ref_counter_.ref_counter());
982 }
983
984 private:
985 template <class>
986 friend class LIBCOPP_COPP_API_HEAD_ONLY weak_rc_ptr;
987
988 template <class>
989 friend class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr;
990
991 private:
994};
995
996template <class T1, class T2>
997LIBCOPP_COPP_API_HEAD_ONLY inline bool operator==(const strong_rc_ptr<T1>& l, const strong_rc_ptr<T2>& r) noexcept {
998 return l.get() == r.get();
999}
1000
1001template <class T1>
1002LIBCOPP_COPP_API_HEAD_ONLY inline bool operator==(const strong_rc_ptr<T1>& l, ::std::nullptr_t) noexcept {
1003 return !l;
1004}
1005
1006template <class T1, class T2, bool = std::is_convertible<T1*, T2*>::value || std::is_convertible<T2*, T1*>::value>
1008
1009template <class T1, class T2>
1011 using left_type = T1*;
1012 using right_type = T2*;
1013
1014 using common_type = nostd::common_type_t<left_type, right_type>;
1015};
1016
1017template <class T1, class T2>
1019 using left_type = const void*;
1020 using right_type = const void*;
1021
1022 using common_type = const void*;
1023};
1024
1025// Use three way comparison if available
1026#ifdef __cpp_impl_three_way_comparison
1027template <class T1, class T2>
1028LIBCOPP_COPP_API_HEAD_ONLY inline std::strong_ordering operator<=>(const strong_rc_ptr<T1>& l,
1029 const strong_rc_ptr<T2>& r) noexcept {
1030 return reinterpret_cast<typename __strong_rc_ptr_compare_common_type<T1, T2>::left_type>(l.get()) <=>
1031 reinterpret_cast<typename __strong_rc_ptr_compare_common_type<T1, T2>::right_type>(r.get());
1032}
1033
1034template <class T1>
1035LIBCOPP_COPP_API_HEAD_ONLY inline std::strong_ordering operator<=>(const strong_rc_ptr<T1>& l,
1036 ::std::nullptr_t) noexcept {
1037 return l.get() <=> static_cast<T1*>(nullptr);
1038}
1039#else
1040
1041template <class T1>
1042LIBCOPP_COPP_API_HEAD_ONLY inline bool operator==(::std::nullptr_t, const strong_rc_ptr<T1>& r) noexcept {
1043 return !r;
1044}
1045
1046template <class T1, class T2>
1047LIBCOPP_COPP_API_HEAD_ONLY inline bool operator!=(const strong_rc_ptr<T1>& l, const strong_rc_ptr<T2>& r) noexcept {
1048 return l.get() != r.get();
1049}
1050
1051template <class T1>
1052LIBCOPP_COPP_API_HEAD_ONLY inline bool operator!=(const strong_rc_ptr<T1>& l, ::std::nullptr_t) noexcept {
1053 return l.get() != nullptr;
1054}
1055
1056template <class T1>
1057LIBCOPP_COPP_API_HEAD_ONLY inline bool operator!=(::std::nullptr_t, const strong_rc_ptr<T1>& r) noexcept {
1058 return r.get() != nullptr;
1059}
1060
1061template <class T1, class T2>
1062LIBCOPP_COPP_API_HEAD_ONLY inline bool operator<(const strong_rc_ptr<T1>& l, const strong_rc_ptr<T2>& r) noexcept {
1063 return std::less<typename __strong_rc_ptr_compare_common_type<
1064 typename strong_rc_ptr<T1>::element_type, typename strong_rc_ptr<T2>::element_type>::common_type>()(l.get(),
1065 r.get());
1066}
1067
1068template <class T1>
1069LIBCOPP_COPP_API_HEAD_ONLY inline bool operator<(const strong_rc_ptr<T1>& l, ::std::nullptr_t) noexcept {
1070 return std::less<T1>()(l.get(), nullptr);
1071}
1072
1073template <class T1>
1074LIBCOPP_COPP_API_HEAD_ONLY inline bool operator<(::std::nullptr_t, const strong_rc_ptr<T1>& r) noexcept {
1075 return std::less<T1>()(nullptr, r.get());
1076}
1077
1078template <class T1, class T2>
1079LIBCOPP_COPP_API_HEAD_ONLY inline bool operator>(const strong_rc_ptr<T1>& l, const strong_rc_ptr<T2>& r) noexcept {
1080 return std::greater<typename __strong_rc_ptr_compare_common_type<
1081 typename strong_rc_ptr<T1>::element_type, typename strong_rc_ptr<T2>::element_type>::common_type>()(l.get(),
1082 r.get());
1083}
1084
1085template <class T1>
1086LIBCOPP_COPP_API_HEAD_ONLY inline bool operator>(const strong_rc_ptr<T1>& l, ::std::nullptr_t) noexcept {
1087 return std::greater<T1>()(l.get(), nullptr);
1088}
1089
1090template <class T1>
1091LIBCOPP_COPP_API_HEAD_ONLY inline bool operator>(::std::nullptr_t, const strong_rc_ptr<T1>& r) noexcept {
1092 return std::greater<T1>()(nullptr, r.get());
1093}
1094
1095template <class T1, class T2>
1096LIBCOPP_COPP_API_HEAD_ONLY inline bool operator<=(const strong_rc_ptr<T1>& l, const strong_rc_ptr<T2>& r) noexcept {
1097 return !(r < l);
1098}
1099
1100template <class T1>
1101LIBCOPP_COPP_API_HEAD_ONLY inline bool operator<=(const strong_rc_ptr<T1>& l, ::std::nullptr_t) noexcept {
1102 return !(nullptr < l);
1103}
1104
1105template <class T1>
1106LIBCOPP_COPP_API_HEAD_ONLY inline bool operator<=(::std::nullptr_t, const strong_rc_ptr<T1>& r) noexcept {
1107 return !(r < nullptr);
1108}
1109
1110template <class T1, class T2>
1111LIBCOPP_COPP_API_HEAD_ONLY inline bool operator>=(const strong_rc_ptr<T1>& l, const strong_rc_ptr<T2>& r) noexcept {
1112 return !(r > l);
1113}
1114
1115template <class T1>
1116LIBCOPP_COPP_API_HEAD_ONLY inline bool operator>=(const strong_rc_ptr<T1>& l, ::std::nullptr_t) noexcept {
1117 return !(nullptr > l);
1118}
1119
1120template <class T1>
1121LIBCOPP_COPP_API_HEAD_ONLY inline bool operator>=(::std::nullptr_t, const strong_rc_ptr<T1>& r) noexcept {
1122 return !(r > nullptr);
1123}
1124#endif
1125
1130template <typename T>
1131class LIBCOPP_COPP_API_HEAD_ONLY weak_rc_ptr {
1132 public:
1133 using element_type = nostd::remove_extent_t<T>;
1134
1135 public:
1136 constexpr weak_rc_ptr() noexcept : ptr_(nullptr), ref_counter_() {}
1137
1138 weak_rc_ptr(const weak_rc_ptr&) noexcept = default; // NOLINT: runtime/explicit
1139 weak_rc_ptr& operator=(const weak_rc_ptr&) noexcept = default;
1140 ~weak_rc_ptr() = default;
1141
1142 weak_rc_ptr(weak_rc_ptr&& other) noexcept // NOLINT: runtime/explicit
1143 : ptr_(other.ptr_), ref_counter_(std::move(other.ref_counter_)) {
1144 other.ptr_ = nullptr;
1145 }
1146
1147 weak_rc_ptr& operator=(weak_rc_ptr&& other) noexcept {
1148 weak_rc_ptr{std::move(other)}.swap(*this);
1149 return *this;
1150 }
1151
1152 template <class Y>
1153 weak_rc_ptr(const strong_rc_ptr<Y>& other) noexcept // NOLINT: runtime/explicit
1154 : ptr_(other.ptr_), ref_counter_(other.ref_counter_) {}
1155
1156 template <class Y>
1157 weak_rc_ptr(const weak_rc_ptr<Y>& other) noexcept : ref_counter_(other.ref_counter_) {
1158 ptr_ = other.lock().get();
1159 }
1160
1161 template <class Y>
1162 weak_rc_ptr(weak_rc_ptr<Y>&& other) noexcept : ptr_(other.lock().get()), ref_counter_(std::move(other.ref_counter_)) {
1163 other.ptr_ = nullptr;
1164 }
1165
1166 template <class Y>
1167 weak_rc_ptr& operator=(const weak_rc_ptr<Y>& other) noexcept {
1168 ptr_ = other.lock().get();
1169 ref_counter_ = other.ref_counter_;
1170 return *this;
1171 }
1172
1173 template <class Y>
1175 weak_rc_ptr{std::move(other)}.swap(*this);
1176 return *this;
1177 }
1178
1179 template <class Y>
1180 weak_rc_ptr& operator=(const strong_rc_ptr<Y>& other) noexcept {
1181 ptr_ = other.ptr_;
1182 __weak_rc_counter<T>{other.ref_counter_}.swap(ref_counter_);
1183 return *this;
1184 }
1185
1186 inline void reset() noexcept { weak_rc_ptr{}.swap(*this); }
1187
1188 inline void swap(weak_rc_ptr& r) noexcept {
1189 std::swap(ptr_, r.ptr_);
1190 ref_counter_.swap(r.ref_counter_);
1191 }
1192
1193 inline std::size_t use_count() const noexcept { return ref_counter_.use_count(); }
1194
1195 inline bool expired() const noexcept { return ref_counter_.use_count() == 0; }
1196
1197 inline strong_rc_ptr<T> lock() const noexcept { return strong_rc_ptr<T>(*this, std::nothrow); }
1198
1199 template <class Y>
1200 inline bool owner_before(strong_rc_ptr<Y> const& r) const noexcept {
1201 return std::less<__rc_ptr_counted_data_base*>()(ref_counter_.ref_counter(), r.ref_counter_.ref_counter());
1202 }
1203
1204 template <class Y>
1205 inline bool owner_before(weak_rc_ptr<Y> const& r) const noexcept {
1206 return std::less<__rc_ptr_counted_data_base*>()(ref_counter_.ref_counter(), r.ref_counter_.ref_counter());
1207 }
1208
1209 template <class Y>
1210 inline bool owner_equal(strong_rc_ptr<Y> const& r) const noexcept {
1211 return ref_counter_.ref_counter() == r.ref_counter_.ref_counter();
1212 }
1213
1214 template <class Y>
1215 inline bool owner_equal(weak_rc_ptr<Y> const& r) const noexcept {
1216 return ref_counter_.ref_counter() == r.ref_counter_.ref_counter();
1217 }
1218
1219 std::size_t owner_hash() const noexcept {
1220 return std::hash<__rc_ptr_counted_data_base*>()(ref_counter_.ref_counter());
1221 }
1222
1223 private:
1224 template <class>
1225 friend class LIBCOPP_COPP_API_HEAD_ONLY enable_shared_rc_from_this;
1226
1227 // Used by enable_shared_rc_from_this.
1228 void assign(element_type* __ptr, const __strong_rc_counter<T>& __refcount) noexcept {
1229 if (use_count() == 0) {
1230 ptr_ = __ptr;
1231 ref_counter_ = __weak_rc_counter<T>{__refcount};
1232 }
1233 }
1234
1235 template <class>
1236 friend class LIBCOPP_COPP_API_HEAD_ONLY weak_rc_ptr;
1237
1238 template <class>
1239 friend class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr;
1240
1241 private:
1244};
1245
1246template <class T>
1248 public:
1250 strong_rc_ptr<T> result = weak_this_.lock();
1251#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
1252 if (this != result.get()) {
1254 }
1255#endif
1256 // NRVO
1257 return result;
1258 }
1259
1261 strong_rc_ptr<T> result = weak_this_.lock();
1262#if defined(LIBCOPP_MACRO_ENABLE_EXCEPTION) && LIBCOPP_MACRO_ENABLE_EXCEPTION
1263 if (this != result.get()) {
1265 }
1266#endif
1267 // NRVO
1269 }
1270
1272
1274
1275 protected:
1280
1281 private:
1282 template <class>
1283 friend class LIBCOPP_COPP_API_HEAD_ONLY strong_rc_ptr;
1284
1285 public:
1286 template <class Y>
1287 void __internal_weak_assign(T* __p, const __strong_rc_counter<Y>& __n) const noexcept {
1288 weak_this_.assign(__p, __n);
1289 }
1290
1291 private:
1293};
1294
1299template <class T, class... TArgs>
1300nostd::enable_if_t<!::std::is_array<T>::value, strong_rc_ptr<T>> make_strong_rc(TArgs&&... args) {
1301 return strong_rc_ptr<T>(__strong_rc_default_alloc_shared_tag<T>{}, std::forward<TArgs>(args)...);
1302}
1303
1308template <class T, class... TArgs>
1309nostd::enable_if_t<nostd::is_bounded_array<T>::value, strong_rc_ptr<T>> make_strong_rc(TArgs&&... args) {
1310 return strong_rc_ptr<T>(__strong_rc_default_alloc_shared_tag<T>{}, std::forward<TArgs>(args)...);
1311}
1312
1318template <class T, class Alloc, class... TArgs>
1319nostd::enable_if_t<!::std::is_array<T>::value, strong_rc_ptr<T>> allocate_strong_rc(const Alloc& alloc,
1320 TArgs&&... args) {
1321 return strong_rc_ptr<T>(__strong_rc_with_alloc_shared_tag<T>{}, alloc, std::forward<TArgs>(args)...);
1322}
1323
1329template <class T, class Alloc, class... TArgs>
1330nostd::enable_if_t<nostd::is_bounded_array<T>::value, strong_rc_ptr<T>> allocate_strong_rc(const Alloc& alloc,
1331 TArgs&&... args) {
1332 return strong_rc_ptr<T>(__strong_rc_with_alloc_shared_tag<T>{}, alloc, std::forward<TArgs>(args)...);
1333}
1334
1340template <class T, class Y>
1342 return strong_rc_ptr<T>(r, static_cast<typename strong_rc_ptr<T>::element_type*>(r.get()));
1343}
1344
1350template <class T, class Y>
1352 return strong_rc_ptr<T>(r, const_cast<typename strong_rc_ptr<T>::element_type*>(r.get()));
1353}
1354
1355#if defined(LIBCOPP_MACRO_ENABLE_RTTI) && LIBCOPP_MACRO_ENABLE_RTTI
1361template <class T, class Y>
1362strong_rc_ptr<T> dynamic_pointer_cast(const strong_rc_ptr<Y>& r) noexcept {
1363 return strong_rc_ptr<T>(r, dynamic_cast<typename strong_rc_ptr<T>::element_type*>(r.get()));
1364}
1365#endif
1366
1367} // namespace memory
1368LIBCOPP_COPP_NAMESPACE_END
1369
1370namespace std {
1376template <class T>
1377LIBCOPP_COPP_API_HEAD_ONLY void swap(LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr<T>& a,
1378 LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr<T>& b) noexcept {
1379 a.swap(b);
1380}
1381
1387template <class T>
1388struct LIBCOPP_COPP_API_HEAD_ONLY hash<LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr<T>> {
1389 std::size_t operator()(const LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr<T>& s) const noexcept {
1390 return std::hash<T*>()(s.get());
1391 }
1392};
1393
1399template <class CharT, class TraitT, class T>
1400LIBCOPP_COPP_API_HEAD_ONLY inline std::basic_ostream<CharT, TraitT>& operator<<(
1401 std::basic_ostream<CharT, TraitT>& __os, const LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr<T>& __p) {
1402 __os << __p.get();
1403 return __os;
1404}
1405} // namespace std
1406
1407LIBCOPP_COPP_NAMESPACE_BEGIN
1408namespace memory {
1409
1413enum class compat_strong_ptr_mode : int8_t {
1414 kStrongRc = 0, // Use strong_rc_ptr
1415 kStl = 1, // Use shared_ptr
1416};
1417
1421template <compat_strong_ptr_mode>
1422struct LIBCOPP_COPP_API_HEAD_ONLY compat_strong_ptr_function_trait;
1423
1424template <>
1426 template <class Y>
1428
1429 template <class Y>
1431
1432 template <class Y>
1434
1435 template <class Y, class... ArgsT>
1436 static inline memory::strong_rc_ptr<Y> make_shared(ArgsT&&... args) {
1437 return memory::make_strong_rc<Y>(std::forward<ArgsT>(args)...);
1438 }
1439
1440 template <class Y, class Alloc, class... TArgs>
1441 static inline memory::strong_rc_ptr<Y> allocate_shared(const Alloc& alloc, TArgs&&... args) {
1442 return memory::allocate_strong_rc<Y>(alloc, std::forward<TArgs>(args)...);
1443 }
1444
1445 template <class Y, class F>
1447 return memory::static_pointer_cast<Y>(std::forward<F>(f));
1448 }
1449
1450 template <class Y, class F>
1452 return memory::const_pointer_cast<Y>(std::forward<F>(f));
1453 }
1454
1455#if defined(LIBCOPP_MACRO_ENABLE_RTTI) && LIBCOPP_MACRO_ENABLE_RTTI
1456 template <class Y, class F>
1457 static inline memory::strong_rc_ptr<Y> dynamic_pointer_cast(F&& f) {
1458 return memory::dynamic_pointer_cast<Y>(std::forward<F>(f));
1459 }
1460#endif
1461};
1462
1463template <>
1465 template <class Y>
1466 using shared_ptr = std::shared_ptr<Y>;
1467
1468 template <class Y>
1469 using weak_ptr = std::weak_ptr<Y>;
1470
1471 template <class Y>
1472 using enable_shared_from_this = std::enable_shared_from_this<Y>;
1473
1474 template <class Y, class... ArgsT>
1475 static inline std::shared_ptr<Y> make_shared(ArgsT&&... args) {
1476 // Some versions os STL will cause warning by mistake, which may trigger -Werror/-WX to fail the build.
1477 // Use include guard to ignore them.
1478 // NOLINT: build/include
1479#include "libcopp/utils/config/stl_include_prefix.h" // IWYU pragma: keep
1480 return std::make_shared<Y>(std::forward<ArgsT>(args)...);
1481// NOLINT: build/include
1482#include "libcopp/utils/config/stl_include_suffix.h" // IWYU pragma: keep
1483 }
1484
1485 template <class Y, class Alloc, class... TArgs>
1486 static inline std::shared_ptr<Y> allocate_shared(const Alloc& alloc, TArgs&&... args) {
1487// Some versions os STL will cause warning by mistake, which may trigger -Werror/-WX to fail the build.
1488// Use include guard to ignore them.
1489// NOLINT: build/include
1490#include "libcopp/utils/config/stl_include_prefix.h" // IWYU pragma: keep
1491 return std::allocate_shared<Y>(alloc, std::forward<TArgs>(args)...);
1492// NOLINT: build/include
1493#include "libcopp/utils/config/stl_include_suffix.h" // IWYU pragma: keep
1494 }
1495
1496 template <class Y, class F>
1497 static inline std::shared_ptr<Y> static_pointer_cast(F&& f) {
1498 return std::static_pointer_cast<Y>(std::forward<F>(f));
1499 }
1500
1501 template <class Y, class F>
1502 static inline std::shared_ptr<Y> const_pointer_cast(F&& f) {
1503 return std::const_pointer_cast<Y>(std::forward<F>(f));
1504 }
1505
1506#if defined(LIBCOPP_MACRO_ENABLE_RTTI) && LIBCOPP_MACRO_ENABLE_RTTI
1507 template <class Y, class F>
1508 static inline std::shared_ptr<Y> dynamic_pointer_cast(F&& f) {
1509 return std::dynamic_pointer_cast<Y>(std::forward<F>(f));
1510 }
1511#endif
1512};
1513
1518template <class T, compat_strong_ptr_mode PtrMode>
1519struct LIBCOPP_COPP_API_HEAD_ONLY compat_strong_ptr_type_trait {
1520 using shared_ptr = typename compat_strong_ptr_function_trait<PtrMode>::template shared_ptr<T>;
1521 using weak_ptr = typename compat_strong_ptr_function_trait<PtrMode>::template weak_ptr<T>;
1522};
1523
1524} // namespace memory
1525LIBCOPP_COPP_NAMESPACE_END
LIBCOPP_UTIL_FORCEINLINE bool add_ref_nothrow() noexcept
Definition rc_ptr.h:61
__rc_ptr_counted_data_base & operator=(const __rc_ptr_counted_data_base &)=delete
__rc_ptr_counted_data_base(const __rc_ptr_counted_data_base &)=delete
static LIBCOPP_COPP_API void throw_bad_weak_ptr()
Definition rc_ptr.cpp:13
LIBCOPP_UTIL_FORCEINLINE void weak_release() noexcept
Definition rc_ptr.h:84
LIBCOPP_UTIL_FORCEINLINE void weak_add_ref() noexcept
Definition rc_ptr.h:81
constexpr __rc_ptr_counted_data_base() noexcept
Definition rc_ptr.h:39
LIBCOPP_UTIL_FORCEINLINE void add_ref()
Definition rc_ptr.h:54
LIBCOPP_UTIL_FORCEINLINE std::size_t use_count() const noexcept
Definition rc_ptr.h:90
LIBCOPP_UTIL_FORCEINLINE void release() noexcept
Definition rc_ptr.h:71
Template class definition for reference-counted.
Definition rc_ptr.h:106
void dispose() noexcept override
Definition rc_ptr.h:110
void destroy() noexcept override
Definition rc_ptr.h:121
__rc_ptr_counted_data_default(T *p) noexcept
Definition rc_ptr.h:108
Template class definition for reference-counted with allocator.(inplacement)
Definition rc_ptr.h:178
void dispose() noexcept override
Definition rc_ptr.h:203
nostd::aligned_storage_t< sizeof(T), alignof(T)> storage_
Definition rc_ptr.h:250
nostd::aligned_storage_t< sizeof(Alloc), alignof(Alloc)> alloc_
Definition rc_ptr.h:251
__rc_ptr_counted_data_inplace_alloc(AllocInput &&a, Args &&... args)
Definition rc_ptr.h:181
void destroy() noexcept override
Definition rc_ptr.h:208
Template class definition for reference-counted.(inplacement)
Definition rc_ptr.h:138
nostd::aligned_storage_t< sizeof(T), alignof(T)> storage_
Definition rc_ptr.h:168
void dispose() noexcept override
Definition rc_ptr.h:148
__rc_ptr_counted_data_inplace(Args &&... args)
Definition rc_ptr.h:141
void destroy() noexcept override
Definition rc_ptr.h:155
Template class definition for reference-counted with deletor and allocator.
Definition rc_ptr.h:288
__rc_ptr_counted_data_with_deleter_allocator(T *p, DeleterInput &&d, AllocInput &&a) noexcept
Definition rc_ptr.h:291
Template class definition for reference-counted with deletor.
Definition rc_ptr.h:259
void destroy() noexcept override
Definition rc_ptr.h:267
void dispose() noexcept override
Definition rc_ptr.h:265
__rc_ptr_counted_data_with_deleter(T *p, DeleterInput &&d) noexcept
Definition rc_ptr.h:262
__strong_rc_counter(Y *p, Deleter &&d)
Definition rc_ptr.h:369
__strong_rc_counter & operator=(const __strong_rc_counter &r) noexcept
Definition rc_ptr.h:512
void swap(__strong_rc_counter &r) noexcept
Definition rc_ptr.h:540
__strong_rc_counter(std::unique_ptr< UT, UDeleter > &&r)
Definition rc_ptr.h:457
__rc_ptr_counted_data_base * ref_counter() const noexcept
Definition rc_ptr.h:555
__strong_rc_counter(__strong_rc_counter< Y > &&r) noexcept
Definition rc_ptr.h:508
__rc_ptr_counted_data_base * pi_
Definition rc_ptr.h:561
__strong_rc_counter(const __weak_rc_counter< T > &w, std::nothrow_t) noexcept
Definition rc_ptr.h:663
friend class LIBCOPP_COPP_API_HEAD_ONLY __strong_rc_counter
Definition rc_ptr.h:559
__strong_rc_counter(const __strong_rc_counter< Y > &r) noexcept
Definition rc_ptr.h:501
__strong_rc_counter(__strong_rc_counter &&r) noexcept
Definition rc_ptr.h:498
std::size_t use_count() const noexcept
Definition rc_ptr.h:553
__strong_rc_counter(const __strong_rc_counter &r) noexcept
Definition rc_ptr.h:492
__strong_rc_counter & operator=(__strong_rc_counter &&r) noexcept
Definition rc_ptr.h:527
__strong_rc_counter(T *&__p, __strong_rc_default_alloc_shared_tag< T >, Args &&... args)
Definition rc_ptr.h:412
__strong_rc_counter(const __weak_rc_counter< T > &w)
Definition rc_ptr.h:655
__strong_rc_counter(Y *p, Deleter &&d, Alloc &&a)
Definition rc_ptr.h:390
constexpr __strong_rc_counter() noexcept
Definition rc_ptr.h:338
__strong_rc_counter(T *&__p, __strong_rc_with_alloc_shared_tag< T >, Alloc &&a, Args &&... args)
Definition rc_ptr.h:433
void swap(__strong_rc_counter< Y > &r) noexcept
Definition rc_ptr.h:547
void swap(__weak_rc_counter< Y > &r) noexcept
Definition rc_ptr.h:637
__weak_rc_counter(__weak_rc_counter< Y > &&r) noexcept
Definition rc_ptr.h:598
__weak_rc_counter & operator=(__weak_rc_counter &&r) noexcept
Definition rc_ptr.h:617
__weak_rc_counter(const __weak_rc_counter &r) noexcept
Definition rc_ptr.h:582
__weak_rc_counter(const __strong_rc_counter< Y > &other) noexcept
Definition rc_ptr.h:570
constexpr __weak_rc_counter() noexcept
Definition rc_ptr.h:567
__weak_rc_counter(const __weak_rc_counter< Y > &r) noexcept
Definition rc_ptr.h:591
std::size_t use_count() const noexcept
Definition rc_ptr.h:643
__rc_ptr_counted_data_base * pi_
Definition rc_ptr.h:651
__weak_rc_counter(__weak_rc_counter &&r) noexcept
Definition rc_ptr.h:588
__weak_rc_counter & operator=(const __weak_rc_counter &r) noexcept
Definition rc_ptr.h:602
void swap(__weak_rc_counter &r) noexcept
Definition rc_ptr.h:630
__rc_ptr_counted_data_base * ref_counter() const noexcept
Definition rc_ptr.h:645
strong_rc_ptr< T > shared_from_this()
Definition rc_ptr.h:1249
weak_rc_ptr< T > weak_from_this()
Definition rc_ptr.h:1271
enable_shared_rc_from_this & operator=(const enable_shared_rc_from_this &)=default
strong_rc_ptr< const T > shared_from_this() const
Definition rc_ptr.h:1260
weak_rc_ptr< const T > weak_from_this() const
Definition rc_ptr.h:1273
void __internal_weak_assign(T *__p, const __strong_rc_counter< Y > &__n) const noexcept
Definition rc_ptr.h:1287
enable_shared_rc_from_this(const enable_shared_rc_from_this &)=default
element_type * operator->() const noexcept
Definition rc_ptr.h:710
element_type * get() const noexcept
Definition rc_ptr.h:721
element_type & operator[](std::ptrdiff_t __i) const noexcept
Definition rc_ptr.h:729
element_type * get() const noexcept
Definition rc_ptr.h:740
nostd::remove_extent_t< T > element_type
Definition rc_ptr.h:727
Base class to mantain all shared APIs.
Definition rc_ptr.h:674
element_type & operator*() const noexcept
Definition rc_ptr.h:678
element_type * operator->() const noexcept
Definition rc_ptr.h:688
element_type * get() const noexcept
Definition rc_ptr.h:699
A std::shared_ptr replacement that is more lightweight and do not use atomic operation for reference ...
Definition rc_ptr.h:791
strong_rc_ptr(const weak_rc_ptr< T > &other)
Definition rc_ptr.h:848
strong_rc_ptr & operator=(strong_rc_ptr< Y > &&other) noexcept
Definition rc_ptr.h:915
strong_rc_ptr(strong_rc_ptr< Y > &&other, element_type *ptr) noexcept
Definition rc_ptr.h:843
strong_rc_ptr & operator=(std::unique_ptr< Y, Deleter > &&other)
Definition rc_ptr.h:921
constexpr strong_rc_ptr(std::nullptr_t) noexcept
Definition rc_ptr.h:803
void absl_nullability_compatible
Definition rc_ptr.h:798
strong_rc_ptr(std::unique_ptr< Y, Deleter > &&other)
Definition rc_ptr.h:865
bool owner_equal(weak_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:976
void reset(Y *ptr, Deleter d) noexcept
Definition rc_ptr.h:938
strong_rc_ptr(const weak_rc_ptr< T > &other, std::nothrow_t) noexcept
Definition rc_ptr.h:853
bool unique() const noexcept
Definition rc_ptr.h:956
__strong_rc_counter< element_type > ref_counter_
Definition rc_ptr.h:993
void nullability_compatible_type
Definition rc_ptr.h:797
strong_rc_ptr(const weak_rc_ptr< Y > &other)
Definition rc_ptr.h:859
bool owner_before(strong_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:961
~strong_rc_ptr() noexcept=default
strong_rc_ptr(__strong_rc_with_alloc_shared_tag< T > __tag, Args &&... args)
This is a special constructor for make_strong_rc/allocate_strong_rc.
Definition rc_ptr.h:888
strong_rc_ptr(strong_rc_ptr< Y > &&other) noexcept
Definition rc_ptr.h:833
strong_rc_ptr(std::nullptr_t ptr, Deleter d, Alloc a)
Definition rc_ptr.h:827
strong_rc_ptr & operator=(strong_rc_ptr &&other) noexcept
Definition rc_ptr.h:902
element_type * get() const noexcept
Definition rc_ptr.h:952
strong_rc_ptr(Y *ptr, Deleter d, Alloc a)
Definition rc_ptr.h:819
void swap(strong_rc_ptr &other) noexcept
Definition rc_ptr.h:947
bool owner_before(weak_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:966
strong_rc_ptr(const strong_rc_ptr< Y > &other, element_type *ptr) noexcept
Definition rc_ptr.h:839
element_type * ptr_
Definition rc_ptr.h:992
strong_rc_ptr & operator=(const strong_rc_ptr< Y > &other) noexcept
Definition rc_ptr.h:908
void reset(Y *ptr, Deleter d, Alloc a) noexcept
Definition rc_ptr.h:943
bool owner_equal(strong_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:971
std::size_t owner_hash() const noexcept
Definition rc_ptr.h:980
void reset(Y *ptr) noexcept
Definition rc_ptr.h:929
strong_rc_ptr(Y *ptr) noexcept
Definition rc_ptr.h:806
constexpr strong_rc_ptr() noexcept
Definition rc_ptr.h:801
strong_rc_ptr(__strong_rc_default_alloc_shared_tag< T > __tag, Args &&... args)
This is a special constructor for make_strong_rc/allocate_strong_rc.
Definition rc_ptr.h:877
void reset() noexcept
Definition rc_ptr.h:926
strong_rc_ptr(const strong_rc_ptr< Y > &other) noexcept
Definition rc_ptr.h:830
strong_rc_ptr(Y *ptr, Deleter d)
Definition rc_ptr.h:814
std::size_t use_count() const noexcept
Definition rc_ptr.h:954
strong_rc_ptr(std::nullptr_t ptr, Deleter d)
Definition rc_ptr.h:824
nostd::remove_extent_t< T > element_type
Definition rc_ptr.h:793
A std::weak_ptr replacement that is more lightweight and do not use atomic operation for reference co...
Definition rc_ptr.h:1131
bool owner_before(strong_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:1200
bool expired() const noexcept
Definition rc_ptr.h:1195
nostd::remove_extent_t< T > element_type
Definition rc_ptr.h:1133
element_type * ptr_
Definition rc_ptr.h:1242
void reset() noexcept
Definition rc_ptr.h:1186
void swap(weak_rc_ptr &r) noexcept
Definition rc_ptr.h:1188
weak_rc_ptr(weak_rc_ptr &&other) noexcept
Definition rc_ptr.h:1142
constexpr weak_rc_ptr() noexcept
Definition rc_ptr.h:1136
weak_rc_ptr & operator=(const strong_rc_ptr< Y > &other) noexcept
Definition rc_ptr.h:1180
bool owner_equal(weak_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:1215
weak_rc_ptr & operator=(weak_rc_ptr< Y > &&other) noexcept
Definition rc_ptr.h:1174
weak_rc_ptr(const weak_rc_ptr &) noexcept=default
weak_rc_ptr(const weak_rc_ptr< Y > &other) noexcept
Definition rc_ptr.h:1157
weak_rc_ptr & operator=(weak_rc_ptr &&other) noexcept
Definition rc_ptr.h:1147
std::size_t owner_hash() const noexcept
Definition rc_ptr.h:1219
~weak_rc_ptr()=default
void assign(element_type *__ptr, const __strong_rc_counter< T > &__refcount) noexcept
Definition rc_ptr.h:1228
bool owner_equal(strong_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:1210
__weak_rc_counter< T > ref_counter_
Definition rc_ptr.h:1243
weak_rc_ptr & operator=(const weak_rc_ptr< Y > &other) noexcept
Definition rc_ptr.h:1167
weak_rc_ptr & operator=(const weak_rc_ptr &) noexcept=default
weak_rc_ptr(const strong_rc_ptr< Y > &other) noexcept
Definition rc_ptr.h:1153
weak_rc_ptr(weak_rc_ptr< Y > &&other) noexcept
Definition rc_ptr.h:1162
bool owner_before(weak_rc_ptr< Y > const &r) const noexcept
Definition rc_ptr.h:1205
strong_rc_ptr< T > lock() const noexcept
Definition rc_ptr.h:1197
std::size_t use_count() const noexcept
Definition rc_ptr.h:1193
#define LIBCOPP_UTIL_SYMBOL_VISIBLE
#define LIBCOPP_UTIL_FORCEINLINE
#define LIBCOPP_UTIL_ATTRIBUTE_UNINITIALIZED
intrusive_ptr< T > const_pointer_cast(intrusive_ptr< U > const &p)
struct LIBCOPP_COPP_API_HEAD_ONLY compat_strong_ptr_function_trait
Helper trait class to switch between strong_rc_ptr and std::shared_ptr.
Definition rc_ptr.h:1422
LIBCOPP_COPP_API_HEAD_ONLY void __enable_shared_from_this_with(const __strong_rc_counter< T1 > *__n, const T2 *__py, const enable_shared_rc_from_this< T3 > *__p)
A helper class that used to inject datas for classes that inherit enable_shared_rc_from_this.
Definition rc_ptr.h:749
bool operator==(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b) noexcept
bool operator<(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b) noexcept
bool operator>(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b) noexcept
LIBCOPP_UTIL_SYMBOL_VISIBLE allocated_ptr< Alloc > allocate_guarded(Alloc &a)
Allocate space for a single object using a.
intrusive_ptr< T > static_pointer_cast(intrusive_ptr< U > const &p)
bool operator<=(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b) noexcept
compat_strong_ptr_mode
Helper class to switch between strong_rc_ptr and std::shared_ptr.
Definition rc_ptr.h:1413
bool operator!=(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b) noexcept
bool operator>=(intrusive_ptr< T > const &a, intrusive_ptr< U > const &b) noexcept
nostd::enable_if_t<!::std::is_array< T >::value, strong_rc_ptr< T > > allocate_strong_rc(const Alloc &alloc, TArgs &&... args)
A std::allocate_shared (C++20) replacement for strong_rc_ptr(non-array).
Definition rc_ptr.h:1319
STL namespace.
LIBCOPP_COPP_API_HEAD_ONLY void swap(LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr< T > &a, LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr< T > &b) noexcept
Support std::swap for strong_rc_ptr.
Definition rc_ptr.h:1377
ostream & operator<<(ostream &os, const LIBCOPP_COPP_NAMESPACE_ID::gsl::not_null< T > &val)
Definition not_null.h:258
nostd::common_type_t< left_type, right_type > common_type
Definition rc_ptr.h:1014
Non-standard RAII type for managing pointers obtained from allocators.
static std::shared_ptr< Y > allocate_shared(const Alloc &alloc, TArgs &&... args)
Definition rc_ptr.h:1486
static std::shared_ptr< Y > make_shared(ArgsT &&... args)
Definition rc_ptr.h:1475
static memory::strong_rc_ptr< Y > allocate_shared(const Alloc &alloc, TArgs &&... args)
Definition rc_ptr.h:1441
static memory::strong_rc_ptr< Y > make_shared(ArgsT &&... args)
Definition rc_ptr.h:1436
A simple helper trait class to switch between strong_rc_ptr and std::shared_ptr.
Definition rc_ptr.h:1519
typename compat_strong_ptr_function_trait< PtrMode >::template shared_ptr< T > shared_ptr
Definition rc_ptr.h:1520
typename compat_strong_ptr_function_trait< PtrMode >::template weak_ptr< T > weak_ptr
Definition rc_ptr.h:1521
std::size_t operator()(const LIBCOPP_COPP_NAMESPACE_ID::memory::strong_rc_ptr< T > &s) const noexcept
Definition rc_ptr.h:1389