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
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.
21 template <typename SideKey, typename SideValue>
22 class Side
23 {
24 // Grant BidirectionalMap full access to Side's private members (specifically 'map')
25 // This is crucial for BidirectionalMap to manage consistency across both directions.
26 friend class BidirectionalMap<T, U>;
27
28 public:
32 Side() = default;
33
34 const SideValue& at(const SideKey& key) const {
35 auto it = map.find(key);
36 if (it == map.end()) {
37 throw std::out_of_range("Key not found in BidirectionalMap::Side::at");
38 }
39 return it->second;
40 }
41
42 bool contains(const SideKey& key) const {
43 return map.count(key) > 0;
44 }
45
46 size_t size() const {
47 return map.size();
48 }
49
50 bool empty() const {
51 return map.empty();
52 }
53
54 typename std::unordered_map<SideKey, SideValue>::const_iterator begin() const { return map.begin(); }
55 typename std::unordered_map<SideKey, SideValue>::const_iterator end() const { return map.end(); }
56
57 private:
58 std::unordered_map<SideKey, SideValue> map;
59
61 map.clear();
62 }
63 };
64
65 using LeftSideType = Side<T, U>; // Maps T -> U
66 using RightSideType = Side<U, T>; // Maps U -> T
67
68 BidirectionalMap() = default;
69
70 LeftSideType& get_left() { return left; }
71 const LeftSideType& get_left() const { return left; }
72
74 const RightSideType& get_right() const { return right; }
75
76 void insert(const T& key, const U& value) {
77 auto it_left_key = left.map.find(key);
78 if (it_left_key != left.map.end()) {
79 U old_value = std::move(it_left_key->second);
80 left.map.erase(it_left_key);
81 right.map.erase(old_value);
82 }
83
84 auto it_right_value = right.map.find(value);
85 if (it_right_value != right.map.end()) {
86 T old_key = std::move(it_right_value->second);
87 right.map.erase(it_right_value);
88 left.map.erase(old_key);
89 }
90
91 left.map.insert_or_assign( key, value );
92 right.map.insert_or_assign( value, key );
93 }
94
95 template <typename KT, typename KU>
96 void emplace(KT&& key, KU&& value) {
97 auto it_left_key = left.map.find(key);
98 if (it_left_key != left.map.end()) {
99 right.map.erase(it_left_key->second);
100 left.map.erase(it_left_key);
101 }
102
103 auto it_right_value = right.map.find(value);
104 if (it_right_value != right.map.end()) {
105 left.map.erase(it_right_value->second);
106 right.map.erase(it_right_value);
107 }
108
109 left.map.emplace(key, value);
110 right.map.emplace(std::forward<KU>(value), std::forward<KT>(key));
111 }
112
113 void remove_left(const T& key) {
114 auto it_left = left.map.find(key);
115 if (it_left != left.map.end()) {
116 U value = it_left->second; // Get the associated value before erasing from left.map
117 left.map.erase(it_left); // Remove T -> U mapping
118 right.map.erase(value); // Remove corresponding U -> T mapping
119 }
120 }
121
122 void remove_right(const U& key) {
123 auto it_right = right.map.find(key);
124 if (it_right != right.map.end()) {
125 T value = it_right->second; // Get the associated value (which is T) before erasing from right.map
126 right.map.erase(it_right); // Remove U -> T mapping
127 left.map.erase(value); // Remove corresponding T -> U mapping
128 }
129 }
130
131 void clear() {
132 left.clear_map_only();
133 right.clear_map_only();
134 }
135
136 void reserve(size_t n) {
137 left.map.reserve(n);
138 right.map.reserve(n);
139 }
140
141private:
144};
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)