31 using mapped_type = V;
32 using value_type =
typename Container::value_type;
33 using key_compare = Compare;
36 bool operator()(
const value_type &lhs,
const value_type &rhs)
const {
37 return key_compare()(lhs.first, rhs.first);
41 using allocator_type =
typename Container::allocator_type;
42 using reference =
typename Container::reference;
43 using const_reference =
typename Container::const_reference;
44 using pointer =
typename Container::pointer;
45 using const_pointer =
typename Container::const_pointer;
46 using iterator =
typename Container::iterator;
47 using const_iterator =
typename Container::const_iterator;
48 using reverse_iterator =
typename Container::reverse_iterator;
49 using const_reverse_iterator =
typename Container::const_reverse_iterator;
50 using difference_type =
typename Container::difference_type;
51 using size_type =
typename Container::size_type;
55 template <
typename It>
60 flat_map(std::initializer_list<value_type> il) :
flat_map(il.begin(), il.end()) {}
62 iterator begin() {
return data_.begin(); }
63 iterator end() {
return data_.end(); }
64 const_iterator begin()
const {
return data_.begin(); }
65 const_iterator end()
const {
return data_.end(); }
66 const_iterator cbegin()
const {
return data_.cbegin(); }
67 const_iterator cend()
const {
return data_.cend(); }
68 reverse_iterator rbegin() {
return data_.rbegin(); }
69 reverse_iterator rend() {
return data_.rend(); }
70 const_reverse_iterator rbegin()
const {
return data_.rbegin(); }
71 const_reverse_iterator rend()
const {
return data_.rend(); }
72 const_reverse_iterator crbegin()
const {
return data_.crbegin(); }
73 const_reverse_iterator crend()
const {
return data_.crend(); }
75 bool empty()
const {
return data_.empty(); }
76 size_type size()
const {
return data_.size(); }
77 size_type max_size()
const {
return data_.max_size(); }
78 size_type capacity()
const {
return data_.capacity(); }
79 void reserve(size_type size) { data_.reserve(size); }
80 void shrink_to_fit() { data_.shrink_to_fit(); }
81 size_type bytes_used()
const {
return capacity() *
sizeof(value_type) +
sizeof(data_); }
83 mapped_type &operator[](
const key_type &key) {
84 KeyOrValueCompare comp;
85 auto lower = lower_bound(key);
86 if (lower == end() || comp(key, *lower))
87 return data_.emplace(lower, key, mapped_type())->second;
92 mapped_type &operator[](key_type &&key) {
93 KeyOrValueCompare comp;
94 auto lower = lower_bound(key);
95 if (lower == end() || comp(key, *lower))
96 return data_.emplace(lower, std::move(key), mapped_type())->second;
102 mapped_type &at(
const Key &key) {
103 auto found = lower_bound(key);
104 if (found == end())
throw std::out_of_range(
"key is out of range");
105 return found->second;
108 const mapped_type &at(
const Key &key)
const {
109 auto found = lower_bound(key);
110 if (found == end())
throw std::out_of_range(
"key is out of range");
111 return found->second;
114 std::pair<iterator, bool> insert(value_type &&value) {
return emplace(std::move(value)); }
116 std::pair<iterator, bool> insert(
const value_type &value) {
return emplace(value); }
118 iterator insert(const_iterator hint, value_type &&value) {
119 return emplace_hint(hint, std::move(value));
122 iterator insert(const_iterator hint,
const value_type &value) {
123 return emplace_hint(hint, value);
126 template <
typename It>
127 void insert(It begin, It end) {
130 for (; begin != end && size() == capacity(); ++begin) {
133 if (begin == end)
return;
138 size_type size_before = data_.size();
140 for (
size_t i = capacity(); i > size_before && begin != end; --i, ++begin) {
141 data_.emplace_back(*begin);
147 for (
size_t i = data_.size(); i > size_before; --i) {
154 auto mid = data_.begin() + size_before;
155 std::stable_sort(mid, data_.end(), comp);
156 std::inplace_merge(data_.begin(), mid, data_.end(), comp);
157 data_.erase(std::unique(data_.begin(), data_.end(), std::not_fn(comp)), data_.end());
162 if (data_.size() == size_before) {
163 for (; begin != end; ++begin) {
164 if (emplace(*begin).second) {
172 return insert(begin, end);
175 void insert(std::initializer_list<value_type> il) { insert(il.begin(), il.end()); }
177 iterator erase(iterator it) {
return data_.erase(it); }
179 iterator erase(const_iterator it) {
return erase(iterator_const_cast(it)); }
181 size_type erase(
const key_type &key) {
182 auto found = find(key);
183 if (found == end())
return 0;
188 iterator erase(const_iterator first, const_iterator last) {
189 return data_.erase(iterator_const_cast(first), iterator_const_cast(last));
192 void swap(flat_map &other) { data_.swap(other.data_); }
194 void clear() { data_.clear(); }
196 template <
typename First,
typename... Args>
197 std::pair<iterator, bool> emplace(First &&first, Args &&...args) {
198 KeyOrValueCompare comp;
199 auto lower_bound = std::lower_bound(data_.begin(), data_.end(), first, comp);
200 if (lower_bound == data_.end() || comp(first, *lower_bound))
202 data_.emplace(lower_bound, std::forward<First>(first), std::forward<Args>(args)...),
205 return {lower_bound,
false};
208 std::pair<iterator, bool> emplace() {
return emplace(value_type()); }
210 template <
typename First,
typename... Args>
211 iterator emplace_hint(const_iterator hint, First &&first, Args &&...args) {
212 KeyOrValueCompare comp;
213 if (hint == cend() || comp(first, *hint)) {
214 if (hint == cbegin() || comp(*(hint - 1), first))
215 return data_.emplace(iterator_const_cast(hint), std::forward<First>(first),
216 std::forward<Args>(args)...);
218 return emplace(std::forward<First>(first), std::forward<Args>(args)...).first;
219 }
else if (!comp(*hint, first)) {
220 return begin() + (hint - cbegin());
223 return emplace(std::forward<First>(first), std::forward<Args>(args)...).first;
226 iterator emplace_hint(const_iterator hint) {
return emplace_hint(hint, value_type()); }
228 key_compare key_comp()
const {
return key_compare(); }
229 value_compare value_comp()
const {
return value_compare(); }
231 template <
typename T>
232 iterator find(
const T &key) {
233 return binary_find(begin(), end(), key, KeyOrValueCompare());
235 template <
typename T>
236 const_iterator find(
const T &key)
const {
237 return binary_find(begin(), end(), key, KeyOrValueCompare());
239 template <
typename T>
240 size_type count(
const T &key)
const {
241 return std::binary_search(begin(), end(), key, KeyOrValueCompare()) ? 1 : 0;
243 template <
typename T>
244 iterator lower_bound(
const T &key) {
245 return std::lower_bound(begin(), end(), key, KeyOrValueCompare());
247 template <
typename T>
248 const_iterator lower_bound(
const T &key)
const {
249 return std::lower_bound(begin(), end(), key, KeyOrValueCompare());
251 template <
typename T>
252 iterator upper_bound(
const T &key) {
253 return std::upper_bound(begin(), end(), key, KeyOrValueCompare());
255 template <
typename T>
256 const_iterator upper_bound(
const T &key)
const {
257 return std::upper_bound(begin(), end(), key, KeyOrValueCompare());
259 template <
typename T>
260 std::pair<iterator, iterator> equal_range(
const T &key) {
261 return std::equal_range(begin(), end(), key, KeyOrValueCompare());
263 template <
typename T>
264 std::pair<const_iterator, const_iterator> equal_range(
const T &key)
const {
265 return std::equal_range(begin(), end(), key, KeyOrValueCompare());
267 allocator_type get_allocator()
const {
return data_.get_allocator(); }
269 bool operator==(
const flat_map &other)
const {
return data_ == other.data_; }
270 bool operator!=(
const flat_map &other)
const {
return !(*
this == other); }
271 bool operator<(
const flat_map &other)
const {
return data_ < other.data_; }
272 bool operator>(
const flat_map &other)
const {
return other < *
this; }
273 bool operator<=(
const flat_map &other)
const {
return !(other < *
this); }
274 bool operator>=(
const flat_map &other)
const {
return !(*
this < other); }
279 iterator iterator_const_cast(const_iterator it) {
return begin() + (it - cbegin()); }
281 struct KeyOrValueCompare {
282 template <
typename T,
typename U>
283 bool operator()(
const T &lhs,
const U &rhs)
const {
284 return key_compare()(extract(lhs), extract(rhs));
288 const key_type &extract(
const value_type &v)
const {
return v.first; }
290 template <
typename Key>
291 const Key &extract(
const Key &k)
const {
296 template <
typename It,
typename T,
typename Comp>
297 static It binary_find(It begin, It end,
const T &value,
const Comp &cmp) {
298 auto lower_bound = std::lower_bound(begin, end, value, cmp);
299 if (lower_bound == end || cmp(value, *lower_bound))
return end;