Translated using Weblate (Russian)
[oweals/minetest.git] / src / irr_ptr.h
1 /*
2 Minetest
3 Copyright (C) 2018 numzero, Lobachevskiy Vitaliy <numzer0@yandex.ru>
4
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.
9
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.
14
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.
18 */
19
20 #pragma once
21 #include <type_traits>
22 #include "irrlichttypes.h"
23 #include "IReferenceCounted.h"
24
25 /** Shared pointer for IrrLicht objects.
26  *
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  *
31  * It should *never* be used for engine-managed objects, including
32  * those created with @c addTexture and similar methods.
33  */
34 template <class ReferenceCounted,
35                 class = typename std::enable_if<std::is_base_of<IReferenceCounted,
36                                 ReferenceCounted>::value>::type>
37 class irr_ptr
38 {
39         ReferenceCounted *value = nullptr;
40
41         /** Drops stored pointer replacing it with the given one.
42          * @note Copy semantics: reference counter *is* increased.
43          */
44         void grab(ReferenceCounted *object)
45         {
46                 if (object)
47                         object->grab();
48                 reset(object);
49         }
50
51 public:
52         irr_ptr() {}
53
54         irr_ptr(std::nullptr_t) noexcept {}
55
56         irr_ptr(const irr_ptr &b) noexcept { grab(b.get()); }
57
58         irr_ptr(irr_ptr &&b) noexcept { reset(b.release()); }
59
60         template <typename B, class = typename std::enable_if<std::is_convertible<B *,
61                                               ReferenceCounted *>::value>::type>
62         irr_ptr(const irr_ptr<B> &b) noexcept
63         {
64                 grab(b.get());
65         }
66
67         template <typename B, class = typename std::enable_if<std::is_convertible<B *,
68                                               ReferenceCounted *>::value>::type>
69         irr_ptr(irr_ptr<B> &&b) noexcept
70         {
71                 reset(b.release());
72         }
73
74         /** Constructs a shared pointer out of a plain one
75          * @note Move semantics: reference counter is *not* increased.
76          */
77         explicit irr_ptr(ReferenceCounted *object) noexcept { reset(object); }
78
79         ~irr_ptr() { reset(); }
80
81         irr_ptr &operator=(const irr_ptr &b) noexcept
82         {
83                 grab(b.get());
84                 return *this;
85         }
86
87         irr_ptr &operator=(irr_ptr &&b) noexcept
88         {
89                 reset(b.release());
90                 return *this;
91         }
92
93         template <typename B, class = typename std::enable_if<std::is_convertible<B *,
94                                               ReferenceCounted *>::value>::type>
95         irr_ptr &operator=(const irr_ptr<B> &b) noexcept
96         {
97                 grab(b.get());
98                 return *this;
99         }
100
101         template <typename B, class = typename std::enable_if<std::is_convertible<B *,
102                                               ReferenceCounted *>::value>::type>
103         irr_ptr &operator=(irr_ptr<B> &&b) noexcept
104         {
105                 reset(b.release());
106                 return *this;
107         }
108
109         ReferenceCounted &operator*() const noexcept { return *value; }
110         ReferenceCounted *operator->() const noexcept { return value; }
111         explicit operator ReferenceCounted *() const noexcept { return value; }
112         explicit operator bool() const noexcept { return !!value; }
113
114         /** Returns the stored pointer.
115          */
116         ReferenceCounted *get() const noexcept { return value; }
117
118         /** Returns the stored pointer, erasing it from this class.
119          * @note Move semantics: reference counter is not changed.
120          */
121         ReferenceCounted *release() noexcept
122         {
123                 ReferenceCounted *object = value;
124                 value = nullptr;
125                 return object;
126         }
127
128         /** Drops stored pointer replacing it with the given one.
129          * @note Move semantics: reference counter is *not* increased.
130          */
131         void reset(ReferenceCounted *object = nullptr) noexcept
132         {
133                 if (value)
134                         value->drop();
135                 value = object;
136         }
137 };