Vulkan Schnee 0.0.1 (22840dc8)
High-performance rendering engine
Loading...
Searching...
No Matches
BidirectionalMap.h
1#pragma once
2#include <unordered_map>
3#include <stdexcept>
4#include <utility>
5
15template <typename T, typename U>
17{
18public:
19 // The Side class is a nested template, providing a read-only view.
20 // It does NOT have an 'other' pointer, as bidirectional logic is handled by the parent.
26 template <typename SideKey, typename SideValue>
27 class Side
28 {
29 // Grant BidirectionalMap full access to Side's private members (specifically 'map')
30 // This is crucial for BidirectionalMap to manage consistency across both directions.
31 friend class BidirectionalMap<T, U>;
32
33 public:
37 Side() = default;
38
45 const SideValue& at(const SideKey& key) const {
46 auto it = map.find(key);
47 if (it == map.end()) {
48 throw std::out_of_range("Key not found in BidirectionalMap::Side::at");
49 }
50 return it->second;
51 }
52
58 bool contains(const SideKey& key) const {
59 return map.count(key) > 0;
60 }
61
66 size_t size() const {
67 return map.size();
68 }
69
74 bool empty() const {
75 return map.empty();
76 }
77
82 typename std::unordered_map<SideKey, SideValue>::const_iterator begin() const { return map.begin(); }
83
88 typename std::unordered_map<SideKey, SideValue>::const_iterator end() const { return map.end(); }
89
90 private:
91 std::unordered_map<SideKey, SideValue> map;
92
94 map.clear();
95 }
96 };
97
100
104 BidirectionalMap() = default;
105
111
116 const LeftSideType& get_left() const { return left; }
117
123
128 const RightSideType& get_right() const { return right; }
129
135 void insert(const T& key, const U& value) {
136 auto it_left_key = left.map.find(key);
137 if (it_left_key != left.map.end()) {
138 U old_value = std::move(it_left_key->second);
139 left.map.erase(it_left_key);
140 right.map.erase(old_value);
141 }
142
143 auto it_right_value = right.map.find(value);
144 if (it_right_value != right.map.end()) {
145 T old_key = std::move(it_right_value->second);
146 right.map.erase(it_right_value);
147 left.map.erase(old_key);
148 }
149
150 left.map.insert_or_assign( key, value );
151 right.map.insert_or_assign( value, key );
152 }
153
161 template <typename KT, typename KU>
162 void emplace(KT&& key, KU&& value) {
163 auto it_left_key = left.map.find(key);
164 if (it_left_key != left.map.end()) {
165 right.map.erase(it_left_key->second);
166 left.map.erase(it_left_key);
167 }
168
169 auto it_right_value = right.map.find(value);
170 if (it_right_value != right.map.end()) {
171 left.map.erase(it_right_value->second);
172 right.map.erase(it_right_value);
173 }
174
175 left.map.emplace(key, value);
176 right.map.emplace(std::forward<KU>(value), std::forward<KT>(key));
177 }
178
183 void remove_left(const T& key) {
184 auto it_left = left.map.find(key);
185 if (it_left != left.map.end()) {
186 U value = it_left->second; // Get the associated value before erasing from left.map
187 left.map.erase(it_left); // Remove T -> U mapping
188 right.map.erase(value); // Remove corresponding U -> T mapping
189 }
190 }
191
196 void remove_right(const U& key) {
197 auto it_right = right.map.find(key);
198 if (it_right != right.map.end()) {
199 T value = it_right->second; // Get the associated value (which is T) before erasing from right.map
200 right.map.erase(it_right); // Remove U -> T mapping
201 left.map.erase(value); // Remove corresponding T -> U mapping
202 }
203 }
204
208 void clear() {
209 left.clear_map_only();
210 right.clear_map_only();
211 }
212
217 void reserve(size_t n) {
218 left.map.reserve(n);
219 right.map.reserve(n);
220 }
221
222private:
225};
Read-only view for one direction of the map.
const SideValue & at(const SideKey &key) const
Gets the value associated with a key.
Side()=default
Default constructor.
bool contains(const SideKey &key) const
Checks whether a key exists on this side.
bool empty() const
Checks whether this side has no mappings.
size_t size() const
Gets the number of mappings on this side.
std::unordered_map< T, U > map
std::unordered_map< SideKey, SideValue >::const_iterator end() const
Gets an iterator past the last mapping on this side.
std::unordered_map< SideKey, SideValue >::const_iterator begin() const
Gets an iterator to the first mapping on this side.
LeftSideType & get_left()
Gets the left-to-right view.
void emplace(KT &&key, KU &&value)
Constructs or replaces a one-to-one mapping in place.
RightSideType right
Side< U, T > RightSideType
Read-only view that maps U to T.
Side< T, U > LeftSideType
Read-only view that maps T to U.
void insert(const T &key, const U &value)
Inserts or replaces a one-to-one mapping.
const LeftSideType & get_left() const
Gets the left-to-right view.
void reserve(size_t n)
Reserves storage for mappings on both sides.
void remove_right(const U &key)
Removes a mapping by right-side key.
RightSideType & get_right()
Gets the right-to-left view.
BidirectionalMap()=default
Creates an empty bidirectional map.
const RightSideType & get_right() const
Gets the right-to-left view.
void clear()
Removes all mappings from both sides.
void remove_left(const T &key)
Removes a mapping by left-side key.