3 Copyright (C) 2018 numzero, Lobachevskiy Vitaliy <numzer0@yandex.ru>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <type_traits>
22 #include "irrlichttypes.h"
23 #include "IReferenceCounted.h"
25 /** Shared pointer for IrrLicht objects.
27 * It should only be used for user-managed objects, i.e. those created with
28 * the @c new operator or @c create* functions, like:
29 * `irr_ptr<scene::IMeshBuffer> buf{new scene::SMeshBuffer()};`
30 * The reference counting is *not* balanced as new objects have reference
31 * count set to one, and the @c irr_ptr constructor (and @c reset) assumes
32 * ownership of that reference.
34 * It shouldn’t be used for engine-managed objects, including those created
35 * with @c addTexture and similar methods. Constructing @c irr_ptr directly
36 * from such object is a bug and may lead to a crash. Indirect construction
37 * is possible though; see the @c grab free function for details and use cases.
39 template <class ReferenceCounted,
40 class = typename std::enable_if<std::is_base_of<IReferenceCounted,
41 ReferenceCounted>::value>::type>
44 ReferenceCounted *value = nullptr;
49 irr_ptr(std::nullptr_t) noexcept {}
51 irr_ptr(const irr_ptr &b) noexcept { grab(b.get()); }
53 irr_ptr(irr_ptr &&b) noexcept { reset(b.release()); }
55 template <typename B, class = typename std::enable_if<std::is_convertible<B *,
56 ReferenceCounted *>::value>::type>
57 irr_ptr(const irr_ptr<B> &b) noexcept
62 template <typename B, class = typename std::enable_if<std::is_convertible<B *,
63 ReferenceCounted *>::value>::type>
64 irr_ptr(irr_ptr<B> &&b) noexcept
69 /** Constructs a shared pointer out of a plain one to control object lifetime.
70 * @param object The object, usually returned by some @c create* function.
71 * @note Move semantics: reference counter is *not* increased.
72 * @warning Never wrap any @c add* function with this!
74 explicit irr_ptr(ReferenceCounted *object) noexcept { reset(object); }
76 ~irr_ptr() { reset(); }
78 irr_ptr &operator=(const irr_ptr &b) noexcept
84 irr_ptr &operator=(irr_ptr &&b) noexcept
90 template <typename B, class = typename std::enable_if<std::is_convertible<B *,
91 ReferenceCounted *>::value>::type>
92 irr_ptr &operator=(const irr_ptr<B> &b) noexcept
98 template <typename B, class = typename std::enable_if<std::is_convertible<B *,
99 ReferenceCounted *>::value>::type>
100 irr_ptr &operator=(irr_ptr<B> &&b) noexcept
106 ReferenceCounted &operator*() const noexcept { return *value; }
107 ReferenceCounted *operator->() const noexcept { return value; }
108 explicit operator ReferenceCounted *() const noexcept { return value; }
109 explicit operator bool() const noexcept { return !!value; }
111 /** Returns the stored pointer.
113 ReferenceCounted *get() const noexcept { return value; }
115 /** Returns the stored pointer, erasing it from this class.
116 * @note Move semantics: reference counter is not changed.
118 ReferenceCounted *release() noexcept
120 ReferenceCounted *object = value;
125 /** Drops stored pointer replacing it with the given one.
126 * @note Move semantics: reference counter is *not* increased.
128 void reset(ReferenceCounted *object = nullptr) noexcept
135 /** Drops stored pointer replacing it with the given one.
136 * @note Copy semantics: reference counter *is* increased.
138 void grab(ReferenceCounted *object) noexcept
147 // ^ dislikes long lines
149 /** Constructs a shared pointer as a *secondary* reference to an object
151 * This function is intended to make a temporary reference to an object which
152 * is owned elsewhere so that it is not destroyed too early. To achieve that
153 * it does balanced reference counting, i.e. reference count is increased
154 * in this function and decreased when the returned pointer is destroyed.
156 template <class ReferenceCounted>
157 irr_ptr<ReferenceCounted> grab(ReferenceCounted *object) noexcept
159 irr_ptr<ReferenceCounted> ptr;
164 template <typename ReferenceCounted>
165 bool operator==(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
167 return a.get() == b.get();
170 template <typename ReferenceCounted>
171 bool operator==(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
176 template <typename ReferenceCounted>
177 bool operator==(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept
182 template <typename ReferenceCounted>
183 bool operator!=(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
185 return a.get() != b.get();
188 template <typename ReferenceCounted>
189 bool operator!=(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
194 template <typename ReferenceCounted>
195 bool operator!=(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept