emilib
list_map.hpp
1 // By Emil Ernerfeldt 2014-2016
2 // LICENSE:
3 // This software is dual-licensed to the public domain and under the following
4 // license: you are granted a perpetual, irrevocable license to copy, modify,
5 // publish, and distribute this file as you see fit.
6 
7 #pragma once
8 
9 #include <vector>
10 #include <utility>
11 
12 namespace emilib {
13 
15 template<typename T>
17 {
18  constexpr bool operator()(const T &lhs, const T &rhs) const
19  {
20  return lhs == rhs;
21  }
22 };
23 
25 template<typename KeyT, typename ValueT, typename EqT = ListMapEqualTo<KeyT>>
26 class ListMap
27 {
28 public:
29  using Pair = std::pair<KeyT, ValueT>;
30  using List = std::vector<Pair>;
31 
32  using size_type = size_t;
33  using value_type = Pair;
34  using reference = Pair&;
35  using const_reference = const Pair&;
36  using iterator = typename List::iterator;
37  using const_iterator = typename List::const_iterator;
38 
39  iterator begin() { return _list.begin(); }
40  iterator end() { return _list.end(); }
41  const_iterator begin() const { return _list.begin(); }
42  const_iterator end() const { return _list.end(); }
43 
44  size_t size() const { return _list.size(); }
45  bool empty() const { return _list.empty(); }
46 
47  iterator find(const KeyT& key)
48  {
49  iterator e=end();
50  for (iterator it=begin(); it!=e; ++it) {
51  if (_eq(it->first, key)) {
52  return it;
53  }
54  }
55  return e;
56  }
57 
58  const_iterator find(const KeyT& key) const
59  {
60  const_iterator e=end();
61  for (const_iterator it=begin(); it!=e; ++it) {
62  if (_eq(it->first, key)) {
63  return it;
64  }
65  }
66  return e;
67  }
68 
69  size_t count(const KeyT& key) const
70  {
71  return find(key) == end() ? 0 : 1;
72  }
73 
74  ValueT& operator[](const KeyT& key)
75  {
76  iterator e=end();
77  for (iterator it=begin(); it!=e; ++it) {
78  if (_eq(it->first, key)) {
79  return it->second;
80  }
81  }
82  _list.push_back(Pair(key, ValueT()));
83  return _list.back().second;
84  }
85 
86  const ValueT& at(const KeyT& key) const
87  {
88  auto it = find(key);
89  if (it == end()) { throw std::domain_error("No such key in ListMap"); }
90  return it->second;
91  }
92 
93  bool insert(const Pair& p)
94  {
95  const_iterator e=end();
96  for (const_iterator it=begin(); it!=e; ++it) {
97  if (_eq(it->first, p.first)) {
98  return false; // like std::map we do not insert if we already have it
99  }
100  }
101  _list.push_back(p);
102  return true;
103  }
104 
105  void insert_or_assign(const KeyT& key, ValueT&& value)
106  {
107  const_iterator e=end();
108  for (const_iterator it=begin(); it!=e; ++it) {
109  if (_eq(it->first, key)) {
110  it->second = std::move(value);
111  return;
112  }
113  }
114  _list.push_back(std::make_pair(key, std::move(value)));
115  }
116 
117  iterator erase(iterator it)
118  {
119  *it = _list.back();
120  _list.pop_back();
121  return it;
122  }
123 
124  void erase(const KeyT& key)
125  {
126  iterator e=end();
127  for (iterator it=begin(); it!=e; ++it) {
128  if (_eq(it->first, key)) {
129  erase(it);
130  return;
131  }
132  }
133  }
134 
137  {
138  _list.shrink_to_fit();
139  }
140 
141  void clear() { _list.clear(); }
142 
143 private:
144  List _list;
145  EqT _eq;
146 };
147 
148 } // namespace emilib
Linear lookup map for quick lookups among few values.
Definition: list_map.hpp:26
void shrink_to_fit()
Frees unnecessary memory.
Definition: list_map.hpp:136
like std::equal_to but no need to #include <functional>
Definition: list_map.hpp:16
Definition: coroutine.hpp:18