88namespace ARLib {
99template <typename T>
1010class SharedPtr {
11- T* m_storage = nullptr ;
12- RefCountBase<T>* m_count = nullptr ;
11+ T* m_storage = nullptr ;
12+ RefCountBase<>* m_count = nullptr ;
13+
14+ template <typename U>
15+ friend class SharedPtr ;
1316 void decrease_instance_count_ () {
1417 if (m_count == nullptr ) return ;
15- m_count->decref ();
18+ m_count->decref <T> ();
1619 if (m_count->count () == 0 ) {
1720 delete m_count;
1821 m_count = nullptr ;
1922 }
2023 }
21-
22- SharedPtr (WeakPtr<T>& weak) {
24+ SharedPtr (WeakPtr<T>& weak) {
2325 m_storage = weak.m_storage ;
2426 m_count = weak.m_count ;
2527 m_count->incref ();
@@ -39,24 +41,59 @@ class SharedPtr {
3941 other.m_count = nullptr ;
4042 return *this ;
4143 }
44+ template <DerivedFrom<T> U>
45+ SharedPtr (SharedPtr<U>&& other) noexcept : m_storage(other.m_storage), m_count(other.m_count) {
46+ other.m_storage = nullptr ;
47+ other.m_count = nullptr ;
48+ }
49+ template <DerivedFrom<T> U>
50+ SharedPtr& operator =(SharedPtr<U>&& other) noexcept {
51+ decrease_instance_count_ ();
52+ m_storage = other.m_storage ;
53+ m_count = other.m_count ;
54+ other.m_storage = nullptr ;
55+ other.m_count = nullptr ;
56+ return *this ;
57+ }
4258 SharedPtr (nullptr_t ) = delete ;
43- SharedPtr (T* ptr) : m_storage(ptr), m_count(new RefCountBase<T >{ m_storage }) {
59+ SharedPtr (T* ptr) : m_storage(ptr), m_count(new RefCountBase<>{ m_storage }) {
4460 HARD_ASSERT (ptr, " Pointer passed to SharedPtr must not be null" );
4561 }
4662 SharedPtr (T&& storage) {
4763 m_storage = new T{ move (storage) };
48- m_count = new RefCountBase<T>{ m_storage };
64+ m_count = new RefCountBase<>{ m_storage };
65+ }
66+ template <DerivedFrom<T> U>
67+ SharedPtr (U* ptr) : m_storage(ptr), m_count(new RefCountBase<>{ m_storage }) {
68+ HARD_ASSERT (ptr, " Pointer passed to SharedPtr must not be null" );
69+ }
70+ template <DerivedFrom<T> U>
71+ SharedPtr (U&& storage) {
72+ m_storage = new U{ move (storage) };
73+ m_count = new RefCountBase<>{ m_storage };
4974 }
5075 SharedPtr (const SharedPtr& other) {
5176 m_storage = other.m_storage ;
5277 m_count = other.m_count ;
5378 if (m_storage == nullptr && m_count == nullptr ) return ;
5479 m_count->incref ();
5580 }
81+ template <DerivedFrom<T> U>
82+ SharedPtr (const SharedPtr<U>& other) {
83+ m_storage = other.m_storage ;
84+ m_count = other.m_count ;
85+ if (m_storage == nullptr && m_count == nullptr ) return ;
86+ m_count->incref ();
87+ }
5688 template <typename ... Args>
5789 SharedPtr (EmplaceT<T>, Args&&... args) {
5890 m_storage = new T{ Forward<Args>(args)... };
59- m_count = new RefCountBase<T>{ m_storage };
91+ m_count = new RefCountBase<>{ m_storage };
92+ }
93+ template <DerivedFrom<T> U, typename ... Args>
94+ SharedPtr (EmplaceT<U>, Args&&... args) {
95+ m_storage = new U{ Forward<Args>(args)... };
96+ m_count = new RefCountBase<>{ m_storage };
6097 }
6198 SharedPtr& operator =(const SharedPtr& other) {
6299 if (this == &other) return *this ;
@@ -67,10 +104,20 @@ class SharedPtr {
67104 m_count->incref ();
68105 return *this ;
69106 }
107+ template <DerivedFrom<T> U>
108+ SharedPtr& operator =(const SharedPtr<U>& other) {
109+ if (this == &other) return *this ;
110+ reset ();
111+ m_storage = other.m_storage ;
112+ m_count = other.m_count ;
113+ if (m_storage == nullptr || m_count == nullptr ) return *this ;
114+ m_count->incref ();
115+ return *this ;
116+ }
70117 bool operator ==(const SharedPtr& other) const { return m_storage == other.m_storage ; }
71118 bool operator ==(const T* other_ptr) const { return m_storage == other_ptr; }
72119 T* release () {
73- T* ptr = m_count->release_storage ();
120+ T* ptr = m_count->release_storage <T> ();
74121 decrease_instance_count_ ();
75122 m_count = nullptr ;
76123 m_storage = nullptr ;
@@ -89,6 +136,22 @@ class SharedPtr {
89136 WeakPtr<T> weakptr () const { return WeakPtr{ m_storage, m_count }; }
90137 T* get () { return m_storage; }
91138 const T* get () const { return m_storage; }
139+ template <DerivedFrom<T> U>
140+ U* get () {
141+ return static_cast <U*>(m_storage);
142+ }
143+ template <DerivedFrom<T> U>
144+ const U* get () const {
145+ return static_cast <const T*>(m_storage);
146+ }
147+ template <DerivedFrom<T> U>
148+ U& as () {
149+ return *get<U>();
150+ }
151+ template <DerivedFrom<T> U>
152+ const U& as () const {
153+ return *get<U>();
154+ }
92155 auto refcount () const { return m_count ? m_count->count () : 0ul ; }
93156 bool exists () const { return m_storage != nullptr ; }
94157 T* operator ->() { return m_storage; }
@@ -97,21 +160,19 @@ class SharedPtr {
97160 const T& operator *() const { return *m_storage; }
98161 ~SharedPtr () { decrease_instance_count_ (); }
99162};
100-
101163template <typename T>
102164SharedPtr<T> WeakPtr<T>::lock() {
103165 return SharedPtr{ *this };
104166}
105-
106167template <typename T>
107168class SharedPtr <T[]> {
108- using RefCount = RefCountBase<T, true >;
169+ using RefCount = RefCountBase<true >;
109170 T* m_storage = nullptr ;
110171 RefCount* m_count = nullptr ;
111172 size_t m_size = 0ull ;
112173 void decrease_instance_count_ () {
113174 if (m_count == nullptr ) return ;
114- m_count->decref ();
175+ m_count->decref <T> ();
115176 if (m_count->count () == 0 ) {
116177 delete m_count;
117178 m_count = nullptr ;
@@ -154,7 +215,7 @@ class SharedPtr<T[]> {
154215 }
155216 bool operator ==(const SharedPtr& other) const { return m_storage == other.m_storage ; }
156217 T* release () {
157- T* ptr = m_count->release_storage ();
218+ T* ptr = m_count->release_storage <T> ();
158219 decrease_instance_count_ ();
159220 m_count = nullptr ;
160221 m_storage = nullptr ;
0 commit comments