-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBidirectionalMap.mpp
More file actions
113 lines (94 loc) · 2.75 KB
/
BidirectionalMap.mpp
File metadata and controls
113 lines (94 loc) · 2.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
module;
#include <CppUtils/System/Compiler.hpp>
export module CppUtils.Container.BidirectionalMap;
import std;
namespace std
{
template<class First, class Second>
struct hash<std::pair<First, Second>>
{
[[nodiscard]] inline auto operator()(const std::pair<First, Second>& pair) const -> std::size_t
{
auto hash1 = std::hash<First>{}(pair.first);
auto hash2 = std::hash<Second>{}(pair.second);
return hash1 ^ (hash2 << 1);
}
};
}
export namespace CppUtils::Container
{
template<class Lhs, class Rhs>
struct BidirectionalMap final
{
using Set = std::unordered_set<std::pair<Lhs, Rhs>>;
public:
inline BidirectionalMap() = default;
explicit inline BidirectionalMap(std::initializer_list<typename Set::value_type> values):
values{values}
{}
[[nodiscard]] constexpr inline auto begin(this auto&& self) -> decltype(auto)
{
return std::begin(self.values);
}
[[nodiscard]] constexpr inline auto cbegin() const -> decltype(auto)
{
return std::cbegin(values);
}
[[nodiscard]] constexpr inline auto end(this auto&& self) -> decltype(auto)
{
return std::end(self.values);
}
[[nodiscard]] constexpr inline auto cend() const -> decltype(auto)
{
return std::cend(values);
}
[[nodiscard]] inline constexpr auto empty() const noexcept -> bool
{
return std::empty(values);
}
[[nodiscard]] inline constexpr auto size() const noexcept -> std::size_t
{
return std::size(values);
}
inline auto clear() noexcept -> void
{
values.clear();
}
inline auto insert(Set::value_type&& value) -> void
{
values.insert(value);
}
[[nodiscard]] inline auto findLeft(const Lhs& lhs) -> decltype(auto)
{
return std::find_if(std::cbegin(values), std::cend(values), [&lhs](auto&& pair) -> bool { return pair.first == lhs; });
}
[[nodiscard]] inline auto findRight(const Rhs& rhs) -> decltype(auto)
{
return std::find_if(std::cbegin(values), std::cend(values), [&rhs](auto&& pair) -> bool { return pair.second == rhs; });
}
[[nodiscard]] inline auto left(const Lhs& lhs) -> decltype(auto)
{
if (auto it = findLeft(lhs); it == std::cend(values))
throw std::runtime_error{"Missing key in BidirectionalMap"};
else
return it->second;
}
[[nodiscard]] inline auto right(const Rhs& rhs) -> decltype(auto)
{
if (auto it = findRight(rhs); it == std::cend(values))
throw std::runtime_error{"Missing key in BidirectionalMap"};
else
return it->first;
}
inline auto eraseLeft(const Lhs& lhs) noexcept -> void
{
std::erase_if(values, [&lhs](auto&& pair) -> bool { return pair.first == lhs; });
}
inline auto eraseRight(const Rhs& rhs) noexcept -> void
{
std::erase_if(values, [&rhs](auto&& pair) -> bool { return pair.second == rhs; });
}
private:
Set values;
};
}