CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
IndexedMultimap.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Map.hpp"
4#include "SmallFlatMap.hpp"
5
9
10namespace CeresEngine {
11
12 template<typename Key, typename Value, typename Container> class BasicIndexedMultimap : private Container {
13 using super = Container;
14
15 public:
16 using key_type = typename super::key_type;
17 using mapped_type = typename super::mapped_type;
18 using value_type = typename super::value_type;
19 using size_type = typename super::size_type;
20 using difference_type = typename super::difference_type;
21 using key_compare = typename super::key_compare;
22 using allocator_type = typename super::allocator_type;
23 using reference = typename super::reference;
24 using const_reference = typename super::const_reference;
25 using pointer = typename super::pointer;
26 using const_pointer = typename super::const_pointer;
27 using iterator = typename super::iterator;
28 using const_iterator = typename super::const_iterator;
29 using reverse_iterator = typename super::reverse_iterator;
30 using const_reverse_iterator = typename super::const_reverse_iterator;
31
32 using super::begin;
33 using super::end;
34
35 using super::cbegin;
36 using super::cend;
37
38 using super::rbegin;
39 using super::rend;
40
41 using super::crbegin;
42 using super::crend;
43
44 using super::equal_range;
45 using super::lower_bound;
46 using super::upper_bound;
47
48 using super::clear;
49 using super::contains;
50 using super::empty;
51 using super::erase;
52 using super::size;
53 using super::swap;
54
57 auto keys() const {
59 return unique(keys(*this));
60 }
61
63 template<typename K = Key> auto values(const K& key) const {
65 return values(wrap(equal_range(key)));
66 }
67
69 template<typename K = Key> auto values(const Key& key) {
71 return values(wrap(equal_range(key)));
72 }
73
82 template<typename K = Key> mapped_type& at(const K& key, size_t index) { return const_cast<mapped_type&>(std::as_const(*this).at(key, index)); }
83
85 template<typename K = Key> const mapped_type& at(const K& key, size_t index) const {
86 const const_iterator lower = lower_bound(key);
88 const size_type currentSize = std::distance(lower, upper);
89
90 if(lower == upper) {
91 throw std::out_of_range("key");
92 }
93
94 if(currentSize < index) {
95 throw std::out_of_range("index");
96 }
97
98 const const_iterator desired = std::next(lower, index);
99 return desired->second;
100 }
101
104 template<typename K = Key> bool contains(const K& key, size_t index) const { return super::count(key) > index; }
105
107 static constexpr bool has_reserve = requires(super & container) { container.reserve(size_type()); };
108
121 {
122 super::reserve(newCapacity);
123 }
124
126 static constexpr bool has_shrink_to_fit = requires(super & container) { container.shrink_to_fit(); };
127
130 {
131 super::shrink_to_fit();
132 }
133
140 template<typename K = Key> void resize(const K& key, size_type newSize, const Value& value = Value()) {
141 const iterator lower = lower_bound(key);
143 const size_type currentSize = std::distance(lower, upper);
144
145 if(currentSize < newSize) {
146 for(const size_type index : range(newSize - currentSize)) {
147 (void)index;
148 upper = super::emplace_hint(upper, key, value);
149 }
150 } else if(currentSize > newSize) {
151 erase(std::prev(upper, currentSize - newSize), upper);
152 }
153 }
154
156 template<typename K = Key> void clear(const K& key) { erase(key); }
157
159 static constexpr bool has_capacity = requires(const super& container) {
160 { container.capacity() } -> std::template same_as<size_type>;
161 };
162
165 {
166 return super::capacity();
167 }
168
172 template<typename K = Key> [[nodiscard]] size_type size(const K& key) const { return super::count(key); }
173
180 template<typename K = Key> [[nodiscard]] iterator erase(const K& key, size_type index) const {
181 const iterator lower = lower_bound(key);
182 const iterator upper = upper_bound(key);
183 const size_type currentSize = std::distance(lower, upper);
184
185 if(lower == upper) {
186 throw std::out_of_range("index");
187 }
188
189 if(currentSize < index) {
190 throw std::out_of_range("index");
191 }
192
193 return erase(std::next(lower, index));
194 }
195
200 template<typename K = Key, typename... Args> mapped_type& emplace_back(const K& key, Args&&... args) {
201 return super::emplace_hint(upper_bound(key), std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(args...))->second;
202 }
203
208 template<typename K = Key> mapped_type& push_back(const K& key, const Value& value) { return super::insert(upper_bound(key), {key, value})->second; }
209
211 template<typename K = Key> mapped_type& push_back(const K& key, Value&& value) {
212 return super::insert(upper_bound(key), {key, std::forward<Value>(value)})->second;
213 }
214
215 template<typename K = Key> const mapped_type& operator()(const K& key, size_type index) const { return at(key, index); }
216
217 template<typename K = Key> mapped_type& operator()(const K& key, size_type index) {
218 ensureSize(key, index + 1u);
219 return at(key, index);
220 }
221
222 private:
226 template<typename K = Key> void ensureSize(const K& key, size_type desiredSize) {
227 if(size(key) < desiredSize) {
228 resize(key, desiredSize + 1);
229 }
230 }
231
232 friend struct std::hash<BasicIndexedMultimap<Key, Value, Container>>;
233 };
234
236 template<typename Key, typename Value, typename Compare = std::less<>, typename RawAllocator = DefaultAllocator>
239
241 template<typename Key, typename Value, size_t N, typename Compare = std::less<>, typename RawAllocator = DefaultAllocator>
243
244} // namespace CeresEngine
245
246template<typename Key, typename Value, typename Container> struct std::hash<CeresEngine::BasicIndexedMultimap<Key, Value, Container>> {
248 [[nodiscard]] size_t operator()(const ValueType& value) { return std::hash<Container>{}(value); }
249};
Definition IndexedMultimap.hpp:12
typename super::difference_type difference_type
Definition IndexedMultimap.hpp:20
typename super::key_compare key_compare
Definition IndexedMultimap.hpp:21
void clear(const K &key)
Clears all values of the given key.
Definition IndexedMultimap.hpp:156
size_type capacity() const
Returns the number of elements that the container has currently allocated space for.
Definition IndexedMultimap.hpp:164
const mapped_type & at(const K &key, size_t index) const
Gets the index-th value for the given key.
Definition IndexedMultimap.hpp:85
typename super::value_type value_type
Definition IndexedMultimap.hpp:18
Container super
Definition IndexedMultimap.hpp:13
auto keys() const
Gets a range that iterates over all the keys on the map.
Definition IndexedMultimap.hpp:57
typename super::mapped_type mapped_type
Definition IndexedMultimap.hpp:17
static constexpr bool has_capacity
Determines if the container has the capacity() method available.
Definition IndexedMultimap.hpp:159
mapped_type & emplace_back(const K &key, Args &&... args)
Emplaces a new element for key at the end of container.
Definition IndexedMultimap.hpp:200
mapped_type & operator()(const K &key, size_type index)
Definition IndexedMultimap.hpp:217
typename super::const_pointer const_pointer
Definition IndexedMultimap.hpp:26
auto values(const Key &key)
Gets a range that iterates over all values of the given key.
Definition IndexedMultimap.hpp:69
bool contains(const K &key, size_t index) const
Returns true if the container contains an element at index with key equivalent to key,...
Definition IndexedMultimap.hpp:104
size_type size(const K &key) const
Computes the number of elements for the given key.
Definition IndexedMultimap.hpp:172
typename super::pointer pointer
Definition IndexedMultimap.hpp:25
mapped_type & push_back(const K &key, Value &&value)
Pushes a new element for key at the end of container.
Definition IndexedMultimap.hpp:211
typename super::reference reference
Definition IndexedMultimap.hpp:23
const mapped_type & operator()(const K &key, size_type index) const
Definition IndexedMultimap.hpp:215
static constexpr bool has_reserve
Determines if the container has the reserve() method available.
Definition IndexedMultimap.hpp:107
mapped_type & push_back(const K &key, const Value &value)
Pushes a new element for key at the end of container.
Definition IndexedMultimap.hpp:208
mapped_type & at(const K &key, size_t index)
Gets the index-th value for the given key.
Definition IndexedMultimap.hpp:82
auto values(const K &key) const
Gets a range that iterates over all values of the given key.
Definition IndexedMultimap.hpp:63
typename super::key_type key_type
Definition IndexedMultimap.hpp:16
typename super::reverse_iterator reverse_iterator
Definition IndexedMultimap.hpp:29
void shrink_to_fit()
Tries to reduce memory usage by freeing unused memory.
Definition IndexedMultimap.hpp:129
void reserve(size_type newCapacity)
Tries to increase capacity by allocating additional memory.
Definition IndexedMultimap.hpp:120
typename super::const_iterator const_iterator
Definition IndexedMultimap.hpp:28
typename super::size_type size_type
Definition IndexedMultimap.hpp:19
typename super::const_reference const_reference
Definition IndexedMultimap.hpp:24
typename super::iterator iterator
Definition IndexedMultimap.hpp:27
void resize(const K &key, size_type newSize, const Value &value=Value())
Resizes the container and ensures that there are exactly newSize items on the given key.
Definition IndexedMultimap.hpp:140
typename super::allocator_type allocator_type
Definition IndexedMultimap.hpp:22
iterator erase(const K &key, size_type index) const
Erases the element at the given index for the given key.
Definition IndexedMultimap.hpp:180
typename super::const_reverse_iterator const_reverse_iterator
Definition IndexedMultimap.hpp:30
static constexpr bool has_shrink_to_fit
Determines if the container has the shrink_to_fit() method available.
Definition IndexedMultimap.hpp:126
void ensureSize(const K &key, size_type desiredSize)
Ensures that the vector has a size of at least desiredSize on the given key.
Definition IndexedMultimap.hpp:226
Definition Application.hpp:19
auto range()
Returns an iterator that increases it's value from 0 to end by 1 for each step.
Definition Iterator.hpp:350
auto values(Container &container)
Returns an iterable object that iterates over the values of a map-like container.
Definition Iterator.hpp:400
auto wrap(IB &&a, IE &&b, Context &&context)
Wraps two iterators into a single-use container with begin/end methods to match the C++ iterator conv...
Definition Iterator.hpp:296
auto keys(Container &container)
Returns an iterable object that iterates over the keys of a map-like container.
Definition Iterator.hpp:380
@ Key
The event is of type KeyEvent.
auto unique(Container &container)
Returns an iterable object that iterates over all unique values on the container.
Definition Iterator.hpp:473
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25