GCC Code Coverage Report


Directory: ./
File: IndirectMap.hpp
Date: 2026-03-21 20:51:59
Exec Total Coverage
Lines: 18 18 100.0%
Functions: 9 12 75.0%
Branches: 2 4 50.0%

Line Branch Exec Source
1 #pragma once
2
3 #include <boost/iterator/transform_iterator.hpp>
4
5 template <typename M>
6 class IndirectMap {
7 public:
8 using key_type = typename M::key_type;
9 using mapped_type =
10 typename std::pointer_traits<typename M::mapped_type>::element_type;
11 using value_type = typename std::pair<const key_type&, mapped_type&>;
12 using const_value_type =
13 typename std::pair<const key_type&, const mapped_type&>;
14 using size_type = typename M::size_type;
15 using difference_type = typename M::difference_type;
16 using key_compare = typename M::key_compare;
17 using reference = value_type&;
18
19 using value_compare = typename M::value_compare;
20 class value_transform;
21
22 using iterator =
23 boost::transform_iterator<value_transform, typename M::iterator>;
24 using const_iterator =
25 boost::transform_iterator<value_transform, typename M::const_iterator>;
26 using reverse_iterator =
27 boost::transform_iterator<value_transform, typename M::reverse_iterator>;
28 using const_reverse_iterator =
29 boost::transform_iterator<value_transform, typename M::const_reverse_iterator>;
30
31 M base{};
32 bool operator==(const IndirectMap& other) const noexcept;
33 bool operator<(const IndirectMap& other) const noexcept;
34
35 mapped_type& at(const key_type& key);
36 [[nodiscard]] const mapped_type& at(const key_type& key) const;
37
38 mapped_type& operator[](const key_type& key);
39 mapped_type& operator[](key_type&& key);
40
41 iterator begin();
42 [[nodiscard]] const_iterator begin() const;
43 [[nodiscard]] const_iterator cbegin() const noexcept;
44
45 iterator end() noexcept;
46 [[nodiscard]] const_iterator end() const noexcept;
47 [[nodiscard]] const_iterator cend() const noexcept;
48
49 reverse_iterator rbegin();
50 [[nodiscard]] const_reverse_iterator rbegin() const;
51 [[nodiscard]] const_reverse_iterator crbegin() const noexcept;
52
53 reverse_iterator rend();
54 [[nodiscard]] const_reverse_iterator rend() const;
55 [[nodiscard]] const_reverse_iterator crend() const noexcept;
56
57 [[nodiscard]] bool empty() const;
58 [[nodiscard]] size_type size() const;
59 void clear();
60
61 [[nodiscard]] size_type count(const key_type& key) const;
62 iterator find(const key_type& key);
63 [[nodiscard]] bool contains(const key_type& key) const;
64 std::pair<iterator, iterator> equal_range(const key_type& key);
65 iterator lower_bound(const key_type& key);
66 [[nodiscard]] const_iterator lower_bound(const key_type& key) const;
67 iterator upper_bound(const key_type& key);
68 [[nodiscard]] const_iterator upper_bound(const key_type& key) const;
69 };
70
71 ////////////////////////////////////////////////////////////////////////////////
72
73 template <typename M>
74 class IndirectMap<M>::value_transform {
75 public:
76 14 IndirectMap<M>::value_type operator()(typename M::value_type& v) const {
77 14 return {v.first, *v.second};
78 }
79
80 28 IndirectMap<M>::const_value_type operator()(const typename M::value_type& v) const {
81 28 return {v.first, *v.second};
82 }
83 };
84
85 ////////////////////////////////////////////////////////////////////////////////
86
87 template <typename M>
88 1 auto IndirectMap<M>::operator==(const IndirectMap& other) const noexcept -> bool {
89 1 return base == other.base;
90 }
91
92 template <typename M>
93 auto IndirectMap<M>::operator<(const IndirectMap& other) const noexcept -> bool {
94 return base < other.base;
95 }
96
97 template <typename M>
98 auto IndirectMap<M>::at(const key_type& key) -> mapped_type& {
99 return *base.at(key);
100 }
101
102 template <typename M>
103 auto IndirectMap<M>::at(const key_type& key) const -> const mapped_type& {
104 return *base.at(key);
105 }
106
107 template <typename M>
108 auto IndirectMap<M>::operator[](const key_type& key) -> mapped_type& {
109 return *base[key];
110 }
111
112 template <typename M>
113 5 auto IndirectMap<M>::operator[](key_type&& key) -> mapped_type& {
114 10 return *base[std::move(key)];
115 }
116
117 template <typename M>
118 5 auto IndirectMap<M>::begin() -> iterator {
119
1/2
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 return {base.begin(), value_transform{}};
120 }
121
122 template <typename M>
123 10 auto IndirectMap<M>::begin() const -> const_iterator {
124
1/2
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
10 return {base.begin(), value_transform{}};
125 }
126
127 template <typename M>
128 auto IndirectMap<M>::cbegin() const noexcept -> const_iterator {
129 return {base.cbegin(), value_transform{}};
130 }
131
132 template <typename M>
133 5 auto IndirectMap<M>::end() noexcept -> iterator {
134 5 return {base.end(), value_transform{}};
135 }
136
137 template <typename M>
138 10 auto IndirectMap<M>::end() const noexcept -> const_iterator {
139 10 return {base.end(), value_transform{}};
140 }
141
142 template <typename M>
143 auto IndirectMap<M>::cend() const noexcept -> const_iterator {
144 return {base.cend(), value_transform{}};
145 }
146
147 template <typename M>
148 auto IndirectMap<M>::rbegin() -> reverse_iterator {
149 return {base.rbegin(), value_transform{}};
150 }
151
152 template <typename M>
153 auto IndirectMap<M>::rbegin() const -> const_reverse_iterator {
154 return {base.rbegin(), value_transform{}};
155 }
156
157 template <typename M>
158 auto IndirectMap<M>::crbegin() const noexcept -> const_reverse_iterator {
159 return {base.crbegin(), value_transform{}};
160 }
161
162 template <typename M>
163 auto IndirectMap<M>::rend() -> reverse_iterator {
164 return {base.rend(), value_transform{}};
165 }
166
167 template <typename M>
168 auto IndirectMap<M>::rend() const -> const_reverse_iterator {
169 return {base.rend(), value_transform{}};
170 }
171
172 template <typename M>
173 auto IndirectMap<M>::crend() const noexcept -> const_reverse_iterator {
174 return {base.crend(), value_transform{}};
175 }
176
177 template <typename M>
178 auto IndirectMap<M>::empty() const -> bool {
179 return base.empty();
180 }
181
182 template <typename M>
183 1 auto IndirectMap<M>::size() const -> size_type {
184 1 return base.size();
185 }
186
187 template <typename M>
188 void IndirectMap<M>::clear() {
189 base.clear();
190 }
191
192 template <typename M>
193 auto IndirectMap<M>::count(const key_type& key) const -> size_type {
194 return base.count(key);
195 }
196
197 template <typename M>
198 auto IndirectMap<M>::find(const key_type& key) -> iterator {
199 return {base.find(key), value_transform{}};
200 }
201
202 template <typename M>
203 auto IndirectMap<M>::contains(const key_type& key) const -> bool {
204 return base.contains(key);
205 }
206
207 template <typename M>
208 auto IndirectMap<M>::equal_range(const key_type& key)
209 -> std::pair<iterator, iterator> {
210 auto&& result = base.equal_range(key);
211 return {{result.first, value_transform{}},
212 {result.second, value_transform{}}};
213 }
214
215 template <typename M>
216 auto IndirectMap<M>::lower_bound(const key_type& key) -> iterator {
217 return {base.lower_bound(key), value_transform{}};
218 }
219
220 template <typename M>
221 auto IndirectMap<M>::lower_bound(const key_type& key) const -> const_iterator {
222 return {base.lower_bound(key), value_transform{}};
223 }
224
225 template <typename M>
226 auto IndirectMap<M>::upper_bound(const key_type& key) -> iterator {
227 return {base.upper_bound(key), value_transform{}};
228 }
229
230 template <typename M>
231 auto IndirectMap<M>::upper_bound(const key_type& key) const -> const_iterator {
232 return {base.upper_bound(key), value_transform{}};
233 }
234