fennec
Loading...
Searching...
No Matches
generic.h
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 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 General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
30
31#ifndef FENNEC_CONTAINERS_GENERIC_H
32#define FENNEC_CONTAINERS_GENERIC_H
33
35#include <fennec/rtti/type.h>
36
37namespace fennec
38{
39
42struct generic {
43
44// Definitions =========================================================================================================
45private:
46
47 // based on GCC
48 enum op_ : uint8_t {
49 op_clone,
50 op_destroy,
51 op_type,
52 };
53
54 using manager_t = void* (*)(uint8_t, void*);
55
56
57// Constructors ========================================================================================================
58public:
59
62 generic()
63 : _handle(nullptr)
64 , _manage(nullptr) {
65 }
66
70 generic(const generic& gen)
71 : _handle(nullptr)
72 , _manage(gen._manage) {
73 if (_manage) {
74 _handle = _manage(op_clone, gen._handle);
75 }
76 }
77
81 generic(generic&& gen)
82 : _handle(gen._handle)
83 , _manage(gen._manage) {
84 gen._handle = nullptr;
85 gen._manage = nullptr;
86 }
87
92 template<typename T>
93 generic(T&& x)
94 : _handle(new T(fennec::forward<T>(x)))
95 , _manage(_manage_impl<T>) {
96 }
97
103 template<typename T, typename...ArgsT>
104 generic(type_identity<T>, ArgsT&&...args)
105 : _handle(new T(fennec::forward<ArgsT>(args)...))
106 , _manage(_manage_impl<T>) {
107 }
108
112 reset();
113 }
114
115
116// Properties ==========================================================================================================
117
118 type type() const {
119 return *static_cast<fennec::type*>(_manage(op_type, nullptr));
120 }
121
122 bool has_value() const {
123 return _handle != nullptr;
124 }
125
126
127// Assignment ==========================================================================================================
128
129 generic& operator=(const generic& gen) {
130 if (this == &gen) { // self-assignment case
131 return *this;
132 }
133
134 reset();
135 _manage = gen._manage;
136 _handle = _manage(op_clone, gen._handle);
137 return *this;
138 }
139
140 generic& operator=(generic&& gen) noexcept {
141 swap(gen);
142 return *this;
143 }
144
145
146// Utility =============================================================================================================
147
148 template<typename T>
149 generic& operator=(T&& x) {
150 reset();
151 _handle = new T(fennec::forward<T>(x));
152 _manage = _manage_impl<T>();
153 return *this;
154 }
155
156 template<typename T, typename...ArgsT>
157 void emplace(ArgsT&&...args) {
158 reset();
159 _handle = new T(fennec::forward<ArgsT>(args)...);
160 _manage = _manage_impl<T>;
161 }
162
163 void reset() {
164 if (_manage) {
165 _handle = _manage(op_destroy, _handle);
166 _manage = nullptr;
167 }
168 }
169
170 void swap(generic& gen) noexcept {
171 fennec::swap(_handle, gen._handle);
172 fennec::swap(_manage, gen._manage);
173 }
174
175 template<typename T>
176 T& cast() {
177 return *static_cast<T*>(_handle);
178 }
179
180 template<typename T>
181 const T& cast() const {
182 return *static_cast<T*>(_handle);
183 }
184
185private:
186 void* _handle;
187 manager_t _manage;
188
189 template<typename T>
190 static void* _manage_impl(uint8_t op, void* hnd) {
191 static fennec::type t = type::get<T>();
192 T* ptr = hnd;
193
194 switch (op) {
195 case op_clone:
196 return new T(*ptr);
197 case op_destroy:
198 delete ptr;
199 return nullptr;
200 case op_type:
201 return &t;
202 default:
203 return nullptr;
204 }
205 }
206};
207
208}
209
210#endif // FENNEC_CONTAINERS_GENERIC_H
This header contains structures and classes related to allocating blocks of memory.
A struct capable of holding a single object of any type.
Definition generic.h:42
generic()
Default Constructor.
Definition generic.h:62
~generic()
Destructor.
Definition generic.h:111
Base Class for Type Transformations.
Definition type_identity.h:49
::uint8_t uint8_t
Unsigned 8-bit integer.
Definition types.h:272
constexpr T && forward(remove_reference_t< T > &x) noexcept
forwards reference types to extend their lifetime
Definition utility.h:75
constexpr void swap(T &x, T &y) noexcept
Swaps x and y.
Definition utility.h:114