vsg  1.1.0
VulkanSceneGraph library
ref_ptr.h
1 #pragma once
2 
3 /* <editor-fold desc="MIT License">
4 
5 Copyright(c) 2018 Robert Osfield
6 
7 Permission 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 
9 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 
11 THE 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 
15 namespace 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  ~ref_ptr()
64  {
65  if (_ptr) _ptr->unref();
66  }
67 
68  void reset()
69  {
70  if (_ptr) _ptr->unref();
71  _ptr = nullptr;
72  }
73 
74  ref_ptr& operator=(T* ptr)
75  {
76  if (ptr == _ptr) return *this;
77 
78  T* temp_ptr = _ptr;
79 
80  _ptr = ptr;
81 
82  if (_ptr) _ptr->ref();
83 
84  // unref the original pointer after ref in case the old pointer object is a parent of the new pointer's object
85  if (temp_ptr) temp_ptr->unref();
86 
87  return *this;
88  }
89 
90  ref_ptr& operator=(const ref_ptr& rhs)
91  {
92  if (rhs._ptr == _ptr) return *this;
93 
94  T* temp_ptr = _ptr;
95 
96  _ptr = rhs._ptr;
97 
98  if (_ptr) _ptr->ref();
99 
100  // unref the original pointer after ref in case the old pointer object is a parent of the new pointer's object
101  if (temp_ptr) temp_ptr->unref();
102 
103  return *this;
104  }
105 
106  template<class R>
107  ref_ptr& operator=(const ref_ptr<R>& rhs)
108  {
109  if (rhs._ptr == _ptr) return *this;
110 
111  T* temp_ptr = _ptr;
112 
113  _ptr = rhs._ptr;
114 
115  if (_ptr) _ptr->ref();
116 
117  // unref the original pointer after ref in case the old pointer object is a parent of the new pointer's object
118  if (temp_ptr) temp_ptr->unref();
119 
120  return *this;
121  }
122 
124  template<class R>
126  {
127  if (rhs._ptr == _ptr) return *this;
128 
129  if (_ptr) _ptr->unref();
130 
131  _ptr = rhs._ptr;
132 
133  rhs._ptr = nullptr;
134 
135  return *this;
136  }
137 
138  template<class R>
139  bool operator<(const ref_ptr<R>& rhs) const { return (_ptr < rhs._ptr); }
140 
141  template<class R>
142  bool operator==(const ref_ptr<R>& rhs) const { return (rhs._ptr == _ptr); }
143 
144  template<class R>
145  bool operator!=(const ref_ptr<R>& rhs) const { return (rhs._ptr != _ptr); }
146 
147  template<class R>
148  bool operator<(const R* rhs) const { return (_ptr < rhs); }
149 
150  template<class R>
151  bool operator==(const R* rhs) const { return (rhs == _ptr); }
152 
153  template<class R>
154  bool operator!=(const R* rhs) const { return (rhs != _ptr); }
155 
156  bool valid() const noexcept { return _ptr != nullptr; }
157 
158  explicit operator bool() const noexcept { return valid(); }
159 
160  // potentially dangerous automatic type conversion, could cause dangling pointer if ref_ptr<> assigned to C pointer and ref_ptr<> destruction causes an object delete.
161  operator T*() const noexcept { return _ptr; }
162 
163  void operator[](int) const = delete;
164 
165  T& operator*() const noexcept { return *_ptr; }
166 
167  T* operator->() const noexcept { return _ptr; }
168 
169  T* get() const noexcept { return _ptr; }
170 
171  T* release_nodelete() noexcept
172  {
173  T* temp_ptr = _ptr;
174 
175  if (_ptr) _ptr->unref_nodelete();
176  _ptr = nullptr;
177 
178  return temp_ptr;
179  }
180 
181  void swap(ref_ptr& rhs) noexcept
182  {
183  T* temp_ptr = _ptr;
184  _ptr = rhs._ptr;
185  rhs._ptr = temp_ptr;
186  }
187 
188  template<class R>
189  ref_ptr<R> cast() const { return ref_ptr<R>(_ptr ? _ptr->template cast<R>() : nullptr); }
190 
191  protected:
192  template<class R>
193  friend class ref_ptr;
194 
195  T* _ptr;
196  };
197 
198 } // namespace vsg
Definition: ref_ptr.h:22
ref_ptr & operator=(ref_ptr< R > &&rhs)
move assignment
Definition: ref_ptr.h:125
ref_ptr(ref_ptr< R > &&rhs) noexcept
move constructor
Definition: ref_ptr.h:37