HybridMap.h
Go to the documentation of this file.
1 #pragma once
2 #include <algorithm>
3 #include <map>
4 #include <ostream>
5 #include <string>
6 #include <utility>
7 #include <vector>
8 
9 namespace lanelet {
10 
11 namespace detail {
12 template <typename ArrayT, ArrayT Arr>
13 class ArrayView {
14  public:
15  static constexpr auto begin() { return std::begin(Arr); }
16  static constexpr auto end() { return std::end(Arr); }
17 
18  static constexpr auto findValue(const decltype(Arr[0].second)& val) {
19  auto it = begin();
20  for (; it != end(); ++it) {
21  if (it->second == val) {
22  break;
23  }
24  }
25  return it;
26  }
27  static constexpr auto findKey(const decltype(Arr[0].first)& val) {
28  auto it = begin();
29  for (; it != end(); ++it) {
30  if (strcmp(it->first, val) == 0) {
31  break;
32  }
33  }
34  return it;
35  }
36 };
37 
38 template <typename Iterator, typename Map>
39 std::vector<Iterator> copyIterators(const std::vector<Iterator>& oldV, const Map& oldM, Map& newM) {
40  std::vector<Iterator> newV(oldV.size(), newM.end());
41  for (auto i = 0u; i < oldV.size(); ++i) {
42  if (oldV[i] != oldM.end()) {
43  newV[i] = newM.find(oldV[i]->first);
44  }
45  }
46  return newV;
47 }
48 
49 template <typename Iterator, typename Vector>
50 void replaceIterator(Vector& v, const Iterator& replace, const Iterator& by) {
51  for (auto& elem : v) {
52  if (elem == replace) {
53  elem = by;
54  }
55  }
56 }
57 } // namespace detail
58 
66 template <typename ValueT, typename PairArrayT, PairArrayT PairArray>
67 class HybridMap {
69 
70  public:
71  using Map = std::map<std::string, ValueT>;
72  using Vec = std::vector<typename Map::iterator>;
73  using Enum = std::decay_t<decltype(PairArray[0].second)>;
74 
75  using key_type = typename Map::key_type; // NOLINT
76  using mapped_type = typename Map::mapped_type; // NOLINT
77  using iterator = typename Map::iterator; // NOLINT
78  using const_iterator = typename Map::const_iterator; // NOLINT
79  using value_type = typename Map::value_type; // NOLINT
80  using difference_type = typename Map::difference_type; // NOLINT
81  using size_type = typename Map::size_type; // NOLINT
82  HybridMap() noexcept = default;
83  HybridMap(HybridMap&& rhs) noexcept : m_(std::move(rhs.m_)), v_{std::move(rhs.v_)} {
84  // move invalidates no iterators except end
85  detail::replaceIterator(v_, rhs.m_.end(), m_.end());
86  }
87  HybridMap& operator=(HybridMap&& rhs) noexcept {
88  m_ = std::move(rhs.m_);
89  v_ = std::move(rhs.v_);
90  // move invalidates no iterators except end
91  detail::replaceIterator(v_, rhs.m_.end(), m_.end());
92  return *this;
93  }
94  HybridMap(const HybridMap& rhs) : m_{rhs.m_}, v_{detail::copyIterators(rhs.v_, rhs.m_, m_)} {}
95  HybridMap& operator=(const HybridMap& rhs) {
96  m_ = rhs.m_;
97  v_ = detail::copyIterators(rhs.v_, rhs.m_, m_);
98  return *this;
99  }
100  HybridMap(const std::initializer_list<std::pair<const std::string, ValueT>>& list) {
101  for (const auto& item : list) {
102  insert(item);
103  }
104  }
105  template <typename InputIterator>
106  HybridMap(InputIterator begin, InputIterator end) {
107  for (; begin != end; ++begin) {
108  insert(*begin);
109  }
110  }
111 
112  ~HybridMap() noexcept = default;
113 
114  iterator find(const key_type& k) { return m_.find(k); }
116  const auto pos = static_cast<size_t>(k);
117  return v_.size() < pos + 1 ? m_.end() : v_[pos];
118  }
119  const_iterator find(const key_type& k) const { return m_.find(k); }
121  const auto pos = static_cast<size_t>(k);
122  return v_.size() < pos + 1 ? m_.end() : v_[pos];
123  }
124 
125  iterator begin() { return m_.begin(); }
126  iterator end() { return m_.end(); }
127  const_iterator begin() const { return m_.begin(); }
128  const_iterator end() const { return m_.end(); }
129 
130  std::pair<iterator, bool> insert(const value_type& v) {
131  auto it = m_.insert(v);
132  if (it.second) {
133  updateV(it.first);
134  }
135  return it;
136  }
137 
139  auto it = m_.insert(hint, v);
140  updateV(it);
141  return it;
142  }
143 
145  auto itV = std::find(v_.begin(), v_.end(), pos);
146  if (itV != v_.end()) {
147  *itV = m_.end();
148  }
149  return m_.erase(pos);
150  }
151 
152  size_type erase(const std::string& k) {
153  auto it = find(k);
154  if (it == end()) {
155  return 0;
156  }
157  erase(it);
158  return 1;
159  }
160 
161  ValueT& operator[](const key_type& k) {
162  auto it = find(k);
163  if (it == m_.end()) {
164  it = insert({k, mapped_type()}).first;
165  }
166  return it->second;
167  }
168  ValueT& operator[](const Enum& k) {
169  auto it = find(k);
170  auto end = m_.end();
171  if (it == end) {
172  auto attr = Array::findValue(k);
173  it = insert({attr->first, mapped_type()}).first;
174  }
175  return it->second;
176  }
177 
178  const ValueT& at(const key_type& k) const {
179  auto it = find(k);
180  if (it == m_.end()) {
181  throw std::out_of_range(std::string("Could not find ") + k);
182  }
183  return it->second;
184  }
185  const ValueT& at(const Enum& k) const {
186  auto it = find(k);
187  if (it == m_.end()) {
188  throw std::out_of_range(std::string("Could not find ") + std::to_string(static_cast<int>(k)));
189  }
190  return it->second;
191  }
192 
193  ValueT& at(const key_type& k) {
194  auto it = find(k);
195  if (it == m_.end()) {
196  throw std::out_of_range(std::string("Could not find ") + k);
197  }
198  return it->second;
199  }
200  ValueT& at(const Enum& k) {
201  auto it = find(k);
202  if (it == m_.end()) {
203  throw std::out_of_range(std::string("Could not find ") + std::to_string(static_cast<int>(k)));
204  }
205  return it->second;
206  }
207 
208  void clear() { m_.clear(), v_.clear(); }
209 
210  bool empty() const { return m_.empty(); }
211  size_t size() const { return m_.size(); }
212 
213  auto key_comp() const { return m_.key_comp(); } // NOLINT
214  auto value_comp() const { return m_.key_comp(); } // NOLINT
215 
216  bool operator==(const HybridMap& other) const { return this->m_ == other.m_; }
217  bool operator!=(const HybridMap& other) const { return !(*this == other); }
218 
219  private:
220  void updateV(iterator it) {
221  auto attr = Array::findKey(it->first.c_str());
222  if (attr != std::end(PairArray)) { // NOLINT
223  const auto pos = static_cast<size_t>(attr->second);
224  if (v_.size() < pos + 1) {
225  v_.resize(pos + 1, m_.end());
226  }
227  v_[pos] = it;
228  }
229  }
232 };
233 
234 template <typename Value, typename Enum, const std::pair<const char*, const Enum> Lookup[]>
235 std::ostream& operator<<(std::ostream& stream, HybridMap<Value, Enum, Lookup> map) {
236  stream << "{";
237  for (const auto& elem : map) {
238  stream << "{" << elem.first << ": " << elem.second << "}";
239  }
240  return stream << "}";
241 }
242 } // namespace lanelet
bool operator!=(const HybridMap &other) const
Definition: HybridMap.h:217
iterator begin()
Definition: HybridMap.h:125
std::vector< Iterator > copyIterators(const std::vector< Iterator > &oldV, const Map &oldM, Map &newM)
Definition: HybridMap.h:39
iterator end()
Definition: HybridMap.h:126
auto find(ContainerT &&c, const ValueT &val)
Definition: Utilities.h:186
A hybrid map is just like a normal map with keys as string, but elements can also be accessed using a...
Definition: HybridMap.h:67
ValueT & at(const key_type &k)
Definition: HybridMap.h:193
static constexpr auto findValue(const decltype(Arr[0].second)&val)
Definition: HybridMap.h:18
static constexpr auto begin()
Definition: HybridMap.h:15
iterator find(Enum k)
Definition: HybridMap.h:115
std::pair< iterator, bool > insert(const value_type &v)
Definition: HybridMap.h:130
iterator find(const key_type &k)
Definition: HybridMap.h:114
ValueT & operator[](const key_type &k)
Definition: HybridMap.h:161
const ValueT & at(const key_type &k) const
Definition: HybridMap.h:178
iterator insert(const_iterator hint, const value_type &v)
Definition: HybridMap.h:138
const_iterator end() const
Definition: HybridMap.h:128
iterator erase(const_iterator pos)
Definition: HybridMap.h:144
size_type erase(const std::string &k)
Definition: HybridMap.h:152
static constexpr auto findKey(const decltype(Arr[0].first)&val)
Definition: HybridMap.h:27
HybridMap(const HybridMap &rhs)
Definition: HybridMap.h:94
bool empty() const
Definition: HybridMap.h:210
const_iterator find(Enum k) const
Definition: HybridMap.h:120
const_iterator find(const key_type &k) const
Definition: HybridMap.h:119
HybridMap & operator=(HybridMap &&rhs) noexcept
Definition: HybridMap.h:87
auto key_comp() const
Definition: HybridMap.h:213
HybridMap(const std::initializer_list< std::pair< const std::string, ValueT >> &list)
Definition: HybridMap.h:100
const ValueT & at(const Enum &k) const
Definition: HybridMap.h:185
HybridMap & operator=(const HybridMap &rhs)
Definition: HybridMap.h:95
size_t size() const
Definition: HybridMap.h:211
ValueT & operator[](const Enum &k)
Definition: HybridMap.h:168
auto value_comp() const
Definition: HybridMap.h:214
void replaceIterator(Vector &v, const Iterator &replace, const Iterator &by)
Definition: HybridMap.h:50
const_iterator begin() const
Definition: HybridMap.h:127
bool operator==(const HybridMap &other) const
Definition: HybridMap.h:216
ValueT & at(const Enum &k)
Definition: HybridMap.h:200
HybridMap(InputIterator begin, InputIterator end)
Definition: HybridMap.h:106
void updateV(iterator it)
Definition: HybridMap.h:220
static constexpr auto end()
Definition: HybridMap.h:16


lanelet2_core
Author(s): Fabian Poggenhans
autogenerated on Tue Jun 6 2023 02:23:32