Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
BidirectionalMap.h
Go to the documentation of this file.
1#pragma once
2#include <unordered_map>
3#include <stdexcept>
4#include <utility>
5
6template <typename T, typename U>
8{
9public:
10 // The Side class is a nested template, providing a read-only view.
11 // It does NOT have an 'other' pointer, as bidirectional logic is handled by the parent.
12 template <typename SideKey, typename SideValue>
13 class Side
14 {
15 // Grant BidirectionalMap full access to Side's private members (specifically 'map')
16 // This is crucial for BidirectionalMap to manage consistency across both directions.
17 friend class BidirectionalMap<T, U>;
18
19 public:
23 Side() = default;
24
25 const SideValue& at(const SideKey& key) const {
26 auto it = map.find(key);
27 if (it == map.end()) {
28 throw std::out_of_range("Key not found in BidirectionalMap::Side::at");
29 }
30 return it->second;
31 }
32
33 bool contains(const SideKey& key) const {
34 return map.count(key) > 0;
35 }
36
37 size_t size() const {
38 return map.size();
39 }
40
41 bool empty() const {
42 return map.empty();
43 }
44
45 typename std::unordered_map<SideKey, SideValue>::const_iterator begin() const { return map.begin(); }
46 typename std::unordered_map<SideKey, SideValue>::const_iterator end() const { return map.end(); }
47
48 private:
49 std::unordered_map<SideKey, SideValue> map;
50
52 map.clear();
53 }
54 };
55
56 using LeftSideType = Side<T, U>; // Maps T -> U
57 using RightSideType = Side<U, T>; // Maps U -> T
58
59 BidirectionalMap() = default;
60
61 LeftSideType& get_left() { return left; }
62 const LeftSideType& get_left() const { return left; }
63
65 const RightSideType& get_right() const { return right; }
66
67 void insert(const T& key, const U& value) {
68 auto it_left_key = left.map.find(key);
69 if (it_left_key != left.map.end()) {
70 U old_value = std::move(it_left_key->second);
71 left.map.erase(it_left_key);
72 right.map.erase(old_value);
73 }
74
75 auto it_right_value = right.map.find(value);
76 if (it_right_value != right.map.end()) {
77 T old_key = std::move(it_right_value->second);
78 right.map.erase(it_right_value);
79 left.map.erase(old_key);
80 }
81
82 left.map.insert_or_assign( key, value );
83 right.map.insert_or_assign( value, key );
84 }
85
86 template <typename KT, typename KU>
87 void emplace(KT&& key, KU&& value) {
88 auto it_left_key = left.map.find(key);
89 if (it_left_key != left.map.end()) {
90 right.map.erase(it_left_key->second);
91 left.map.erase(it_left_key);
92 }
93
94 auto it_right_value = right.map.find(value);
95 if (it_right_value != right.map.end()) {
96 left.map.erase(it_right_value->second);
97 right.map.erase(it_right_value);
98 }
99
100 left.map.emplace(key, value);
101 right.map.emplace(std::forward<KU>(value), std::forward<KT>(key));
102 }
103
104 void remove_left(const T& key) {
105 auto it_left = left.map.find(key);
106 if (it_left != left.map.end()) {
107 U value = it_left->second; // Get the associated value before erasing from left.map
108 left.map.erase(it_left); // Remove T -> U mapping
109 right.map.erase(value); // Remove corresponding U -> T mapping
110 }
111 }
112
113 void remove_right(const U& key) {
114 auto it_right = right.map.find(key);
115 if (it_right != right.map.end()) {
116 T value = it_right->second; // Get the associated value (which is T) before erasing from right.map
117 right.map.erase(it_right); // Remove U -> T mapping
118 left.map.erase(value); // Remove corresponding T -> U mapping
119 }
120 }
121
122 void clear() {
123 left.clear_map_only();
124 right.clear_map_only();
125 }
126
127 void reserve(size_t n) {
128 left.map.reserve(n);
129 right.map.reserve(n);
130 }
131
132private:
135};
const SideValue & at(const SideKey &key) const
Side()=default
Default constructor.
bool contains(const SideKey &key) const
std::unordered_map< T, U > map
std::unordered_map< SideKey, SideValue >::const_iterator end() const
std::unordered_map< SideKey, SideValue >::const_iterator begin() const
LeftSideType & get_left()
void emplace(KT &&key, KU &&value)
RightSideType right
Side< U, T > RightSideType
Side< T, U > LeftSideType
void insert(const T &key, const U &value)
const LeftSideType & get_left() const
void reserve(size_t n)
void remove_right(const U &key)
RightSideType & get_right()
BidirectionalMap()=default
const RightSideType & get_right() const
void remove_left(const T &key)