vsg: include/vsg/core/ref_ptr.h Source File

vsg 1.1.13 VulkanSceneGraph library

Loading...
Searching...
No Matches
ref_ptr.h
1#pragma once
2
3/* <editor-fold desc="MIT License">
4
5Copyright(c) 2018 Robert Osfield
6
7Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
13</editor-fold> */
14
15namespace vsg
16{
17
20 template<class T>
21 class ref_ptr
22 {
23 public:
24 using element_type = T;
25
26 ref_ptr() noexcept :
27 _ptr(nullptr) {}
28
29 ref_ptr(const ref_ptr& rhs) noexcept :
30 _ptr(rhs._ptr)
31 {
32 if (_ptr) _ptr->ref();
33 }
34
36 template<class R>
37 ref_ptr(ref_ptr<R>&& rhs) noexcept :
38 _ptr(rhs._ptr)
39 {
40 rhs._ptr = nullptr;
41 }
42
43 template<class R>
44 ref_ptr(const ref_ptr<R>& ptr) noexcept :
45 _ptr(ptr._ptr)
46 {
47 if (_ptr) _ptr->ref();
48 }
49
50 explicit ref_ptr(T* ptr) noexcept :
51 _ptr(ptr)
52 {
53 if (_ptr) _ptr->ref();
54 }
55
56 template<class R>
57 explicit ref_ptr(R* ptr) noexcept :
58 _ptr(ptr)
59 {
60 if (_ptr) _ptr->ref();
61 }
62
63 // std::nullptr_t requires extra header
64 ref_ptr(decltype(nullptr)) noexcept :
65 ref_ptr() {}
66
67 ~ref_ptr()
68 {
69 if (_ptr) _ptr->unref();
70 }
71
72 void reset()
73 {
74 if (_ptr) _ptr->unref();
75 _ptr = nullptr;
76 }
77
78 ref_ptr& operator=(T* ptr)
79 {
80 if (ptr == _ptr) return *this;
81
82 T* temp_ptr = _ptr;
83
84 _ptr = ptr;
85
86 if (_ptr) _ptr->ref();
87
88 // unref the original pointer after ref in case the old pointer object is a parent of the new pointer's object
89 if (temp_ptr) temp_ptr->unref();
90
91 return *this;
92 }
93
94 ref_ptr& operator=(const ref_ptr& rhs)
95 {
96 if (rhs._ptr == _ptr) return *this;
97
98 T* temp_ptr = _ptr;
99
100 _ptr = rhs._ptr;
101
102 if (_ptr) _ptr->ref();
103
104 // unref the original pointer after ref in case the old pointer object is a parent of the new pointer's object
105 if (temp_ptr) temp_ptr->unref();
106
107 return *this;
108 }
109
110 template<class R>
111 ref_ptr& operator=(const ref_ptr<R>& rhs)
112 {
113 if (rhs._ptr == _ptr) return *this;
114
115 T* temp_ptr = _ptr;
116
117 _ptr = rhs._ptr;
118
119 if (_ptr) _ptr->ref();
120
121 // unref the original pointer after ref in case the old pointer object is a parent of the new pointer's object
122 if (temp_ptr) temp_ptr->unref();
123
124 return *this;
125 }
126
128 template<class R>
129 ref_ptr& operator=(ref_ptr<R>&& rhs)
130 {
131 if (rhs._ptr == _ptr) return *this;
132
133 if (_ptr) _ptr->unref();
134
135 _ptr = rhs._ptr;
136
137 rhs._ptr = nullptr;
138
139 return *this;
140 }
141
142 template<class R>
143 bool operator<(const ref_ptr<R>& rhs) const { return (_ptr < rhs._ptr); }
144
145 template<class R>
146 bool operator==(const ref_ptr<R>& rhs) const { return (rhs._ptr == _ptr); }
147
148 template<class R>
149 bool operator!=(const ref_ptr<R>& rhs) const { return (rhs._ptr != _ptr); }
150
151 template<class R>
152 bool operator<(const R* rhs) const { return (_ptr < rhs); }
153
154 template<class R>
155 bool operator==(const R* rhs) const { return (rhs == _ptr); }
156
157 template<class R>
158 bool operator!=(const R* rhs) const { return (rhs != _ptr); }
159
160 bool valid() const noexcept { return _ptr != nullptr; }
161
162 explicit operator bool() const noexcept { return valid(); }
163
164 // potentially dangerous automatic type conversion, could cause dangling pointer if ref_ptr<> assigned to C pointer and ref_ptr<> destruction causes an object delete.
165 operator T*() const noexcept { return _ptr; }
166
167 void operator[](int) const = delete;
168
169 T& operator*() const noexcept { return *_ptr; }
170
171 T* operator->() const noexcept { return _ptr; }
172
173 T* get() const noexcept { return _ptr; }
174
175 T* release_nodelete() noexcept
176 {
177 T* temp_ptr = _ptr;
178
179 if (_ptr) _ptr->unref_nodelete();
180 _ptr = nullptr;
181
182 return temp_ptr;
183 }
184
185 void swap(ref_ptr& rhs) noexcept
186 {
187 T* temp_ptr = _ptr;
188 _ptr = rhs._ptr;
189 rhs._ptr = temp_ptr;
190 }
191
192 template<class R>
193 ref_ptr<R> cast() const { return ref_ptr<R>(_ptr ? _ptr->template cast<R>() : nullptr); }
194
195 protected:
196 template<class R>
197 friend class ref_ptr;
198
199 T* _ptr;
200 };
201
202} // namespace vsg
vsg::ref_ptr
Definition ref_ptr.h:22
vsg::ref_ptr::operator=
ref_ptr & operator=(ref_ptr< R > &&rhs)
move assignment
Definition ref_ptr.h:129
vsg::ref_ptr::ref_ptr
ref_ptr(ref_ptr< R > &&rhs) noexcept
move constructor
Definition ref_ptr.h:37