fennec
Loading...
Searching...
No Matches
map.h
Go to the documentation of this file.
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_MAP_H
32#define FENNEC_CONTAINERS_MAP_H
33
36
37namespace fennec
38{
39
40/* Ramblings
41 *
42 * Definitions:
43 * user = Programmer using this data structure
44 *
45 * The STL maps are very contrived. Some of its functionality encourages younger programmers to use
46 * the exception model. Ideally, I would like this structure to never throw an error with typical use.
47 *
48 * The array access operator is, in my opinion, poorly implemented. I do not think that this operator should handle
49 * insertions and should handle access only. This is the only data structure in STL that has this behavior, no other
50 * data structure modifies contents by inherently calling operator[].
51 *
52 * Currently, I am considering implementing this as the following:
53 * Access will be handled only via operator[]. Return value will be a pointer which forces user validation.
54 * Insertions will be handled only via an insert/emplace function.
55 * Deletions will be handled only via an erase function.
56*/
57
79template<typename KeyT, typename ValueT, typename Hash = hash<KeyT>, typename Alloc = allocator<pair<KeyT, ValueT>>>
80struct map {
81
82// Definitions =========================================================================================================
83public:
84 struct key_hash;
85 struct key_equals;
86 using key_t = KeyT;
87 using value_t = ValueT;
89 using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>;
90 using hash_t = Hash;
92 using iterator = set_t::iterator;
93
94 // We only want to hash the key
95 struct key_hash : hash_t {
96 constexpr size_t operator()(const elem_t& p) const {
97 return hash_t::operator()(p.first);
98 }
99 };
100
101 // We only want to compare the keys
102 struct key_equals : equality<KeyT> {
103 constexpr bool operator()(const elem_t& a, const elem_t& b) const {
104 return equality<KeyT>::operator()(a.first, b.first);
105 }
106 };
107
108
109// Constructors & Destructor ===========================================================================================
110
113
116 constexpr map() = default;
117
120 constexpr ~map() = default;
121
123
124
125// Properties ==========================================================================================================
126
129
132 constexpr size_t size() const {
133 return _set.size();
134 }
135
138 constexpr size_t empty() const {
139 return _set.size();
140 }
141
144 constexpr size_t capacity() const {
145 return _set.capacity();
146 }
147
149
150
151// Access ==============================================================================================================
152
155
160 constexpr value_t* operator[](const KeyT& key) {
161 auto it = _set.at(this->_find(key));
162 return it ? &it->second : nullptr;
163 }
164
169 constexpr const value_t* operator[](const KeyT& key) const {
170 auto it = _set.at(this->_find(key));
171 return it ? &it->second : nullptr;
172 }
173
179 template<typename...ArgsT>
180 constexpr value_t* operator[](ArgsT&&...args) {
181 auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
182 return it ? &it->second : nullptr;
183 }
184
190 template<typename...ArgsT>
191 constexpr const value_t* operator[](ArgsT&&...args) const {
192 auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
193 return it ? &it->second : nullptr;
194 }
195
197
198
199// Modifiers ===========================================================================================================
200
203
207 constexpr void insert(elem_t&& pair) {
208 this->_insert(fennec::forward<elem_t>(pair));
209 }
210
214 template<typename...ArgsT>
215 constexpr void emplace(const KeyT& key, ArgsT&&...args) {
216 this->_insert(key, fennec::forward<ArgsT>(args)...);
217 }
218
222 template<typename...ArgsT>
223 constexpr void emplace(ArgsT&&...args) {
224 this->_insert(fennec::forward<ArgsT>(args)...);
225 }
226
230 constexpr void erase(KeyT&& key) {
231 _set.erase(this->_find(fennec::forward<KeyT>(key)));
232 }
233
237 constexpr void erase(const KeyT& key) {
238 _set.erase(this->_find(key));
239 }
240
245 template<typename...ArgsT>
246 constexpr void erase(ArgsT&&...args) {
247 _set.erase(this->_find(fennec::forward<ArgsT>(args)...));
248 }
249
252 void clear() {
253 _set.clear();
254 }
255
257
258
259// Iteration ===========================================================================================================
260
263
267 constexpr iterator begin() {
268 return _set.begin();
269 }
270
271
275 constexpr iterator end() {
276 return _set.end();
277 }
278
280
281
282private:
283 set_t _set;
284
285 template<typename...ArgsT>
286 set_t::iterator _find(ArgsT&&...args) const {
287 union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
288 pair<KeyT, char[sizeof(ValueT)]> root;
290
291 ~U() {
292 fennec::destruct(&root);
293 }
294 } trick = {
295 .root = { KeyT(fennec::forward<ArgsT>(args)...), 0 }
296 };
297 return _set.find(trick.val);
298 }
299
300 template<typename...ArgsT>
301 constexpr void _insert(ArgsT&&...args) {
302 elem_t elem(fennec::forward<ArgsT>(args)...);
303 auto it = this->_find(elem.first);
304 if (it != _set.end()) {
305 _set.at(it)->second = fennec::move(elem.second);
306 } else {
307 _set.insert(fennec::move(elem));
308 }
309 }
310};
311
312}
313
314#endif // FENNEC_CONTAINERS_MAP_H
A header containing the definition for a container holding a pair of values.
A header containing the definition for a set of unique values.
typename _rebind< Alloc, TypeT >::type rebind
Rebinds the allocator type to produce an element type of type TypeT
Definition allocator.h:134
Data Structure defining a mapping of key to value .
Definition map.h:80
constexpr iterator begin()
C++ Iterator Specification begin()
Definition map.h:267
constexpr const value_t * operator[](ArgsT &&...args) const
Argument Key Const Access Operator.
Definition map.h:191
constexpr value_t * operator[](ArgsT &&...args)
Argument Key Access Operator.
Definition map.h:180
constexpr size_t empty() const
Definition map.h:138
constexpr size_t capacity() const
Definition map.h:144
set_t::iterator iterator
Iterator type.
Definition map.h:92
void clear()
Clears the map destructing all elements.
Definition map.h:252
constexpr size_t size() const
Definition map.h:132
constexpr void insert(elem_t &&pair)
Key-Value Insertion.
Definition map.h:207
typename allocator_traits< Alloc >::template rebind< elem_t > alloc_t
Rebinds the allocator type to nodes.
Definition map.h:89
constexpr map()=default
Default Constructor, initializes empty map.
constexpr void erase(ArgsT &&...args)
Argument Erase.
Definition map.h:246
constexpr void emplace(ArgsT &&...args)
Key-Value Insertion.
Definition map.h:223
constexpr void erase(KeyT &&key)
Erase a key.
Definition map.h:230
constexpr value_t * operator[](const KeyT &key)
Key Access Operator.
Definition map.h:160
KeyT key_t
The key type.
Definition map.h:86
Hash hash_t
The hash type.
Definition map.h:90
ValueT value_t
The value type.
Definition map.h:87
constexpr ~map()=default
Destructor, Destructs all elements and releases the allocation.
constexpr void emplace(const KeyT &key, ArgsT &&...args)
Key-Value Insertion.
Definition map.h:215
constexpr void erase(const KeyT &key)
Erase a key.
Definition map.h:237
pair< KeyT, ValueT > elem_t
then node type
Definition map.h:88
constexpr iterator end()
C++ Iterator Specification end()
Definition map.h:275
set< elem_t, key_hash, key_equals, alloc_t > set_t
The underlying set.
Definition map.h:91
constexpr const value_t * operator[](const KeyT &key) const
Key Const Access Operator.
Definition map.h:169
Struct for holding a pair of values.
Definition pair.h:48
TypeT1 second
The second value in the pair.
Definition pair.h:53
TypeT0 first
The first value in the pair.
Definition pair.h:52
constexpr size_t size() const
Definition set.h:180
constexpr size_t capacity() const
Definition set.h:192
constexpr elem_t * at(const iterator &it)
Iterator Access.
Definition set.h:265
constexpr iterator begin() const
Definition set.h:364
constexpr iterator end() const
Definition set.h:374
constexpr void erase(iterator it)
Element Erase.
Definition set.h:317
constexpr remove_reference_t< T > && move(T &&x) noexcept
produces an x-value type to indicate x may be "moved"
Definition utility.h:92