9 #ifndef EAGINE_FLAT_MAP_HPP
10 #define EAGINE_FLAT_MAP_HPP
21 template <
typename Key,
typename Val,
typename Cmp>
22 struct flat_map_value_compare : Cmp {
24 constexpr
auto key_comp() const noexcept -> const Cmp& {
28 template <
typename L,
typename R>
29 constexpr
auto operator()(
30 const std::pair<L, Val>& a,
31 const std::pair<R, Val>& b)
const noexcept ->
bool {
32 return key_comp()(a.first, b.first);
37 operator()(
const std::pair<K, Val>& a,
const Key& b)
const noexcept {
38 return key_comp()(a.first, b);
43 operator()(
const Key& a,
const std::pair<K, Val>& b)
const noexcept {
44 return key_comp()(a, b.first);
48 template <
typename Key,
typename Val,
typename Cmp>
49 struct flat_map_ops : flat_map_value_compare<Key, Val, Cmp> {
52 constexpr
auto value_comp() const noexcept
53 -> const flat_map_value_compare<Key, Val, Cmp>& {
58 static auto empty(I b, I e) noexcept {
63 static auto size(I b, I e) noexcept {
69 auto lower_bound(I b, I e,
const Key& key)
const noexcept {
70 return ::std::lower_bound(b, e, key, value_comp());
74 auto upper_bound(I b, I e,
const Key& key)
const noexcept {
75 return ::std::upper_bound(b, e, key, value_comp());
79 auto equal_range(I b, I e,
const Key& key)
const noexcept {
80 return ::std::equal_range(b, e, key, value_comp());
84 auto find(I b, I e,
const Key& key)
const noexcept {
85 b = lower_bound(b, e, key);
86 if((b != e) && value_comp()(key, *b)) {
93 auto at(I b, I e,
const Key& key)
const ->
auto& {
96 throw std::out_of_range(
"Invalid flat map key");
101 template <
typename I>
102 auto get(I b, I e,
const Key& key)
const noexcept ->
auto& {
104 EAGINE_ASSERT(b != e);
109 template <
typename Key,
typename Val,
typename Cmp,
typename Derived>
110 class flat_map_view_crtp : flat_map_ops<Key, Val, Cmp> {
112 auto _self() const noexcept -> const Derived& {
113 return *
static_cast<const Derived*
>(
this);
115 auto _self() noexcept -> Derived& {
116 return *
static_cast<Derived*
>(
this);
119 auto _b() const noexcept {
120 return _self().begin();
123 return _self().begin();
126 auto _e() const noexcept {
127 return _self().end();
130 return _self().end();
134 using _ops_t = flat_map_ops<Key, Val, Cmp>;
136 constexpr
auto _ops() const noexcept -> const _ops_t& {
141 using key_type = Key;
142 using mapped_type = Val;
147 using key_compare = Cmp;
148 using value_compare = flat_map_value_compare<Key, Val, Cmp>;
150 auto key_comp() const noexcept -> const key_compare& {
151 return _ops().value_comp().key_comp();
154 auto value_comp() const noexcept -> const value_compare& {
155 return _ops().value_comp();
158 auto empty() const noexcept {
159 return _ops().empty(_b(), _e());
163 return _ops().size(_b(), _e());
166 auto find(
const Key& key) {
167 return _ops().find(_b(), _e(), key);
170 auto find(
const Key& key)
const {
171 return _ops().find(_b(), _e(), key);
174 auto lower_bound(
const Key& key) {
175 return _ops().lower_bound(_b(), _e(), key);
178 auto lower_bound(
const Key& key)
const {
179 return _ops().lower_bound(_b(), _e(), key);
182 auto upper_bound(
const Key& key) {
183 return _ops().upper_bound(_b(), _e(), key);
186 auto upper_bound(
const Key& key)
const {
187 return _ops().upper_bound(_b(), _e(), key);
190 auto equal_range(
const Key& key) {
191 return _ops().equal_range(_b(), _e(), key);
194 auto equal_range(
const Key& key)
const {
195 return _ops().equal_range(_b(), _e(), key);
198 auto at(
const Key& key) -> Val& {
199 return _ops().at(_b(), _e(), key);
202 auto at(
const Key& key)
const ->
const Val& {
203 return _ops().at(_b(), _e(), key);
210 typename Cmp = std::less<Key>,
211 typename Allocator = std::allocator<std::pair<Key, Val>>>
213 :
public flat_map_view_crtp<Key, Val, Cmp, flat_map<Key, Val, Cmp, Allocator>> {
216 flat_map_view_crtp<Key, Val, Cmp, flat_map<Key, Val, Cmp, Allocator>>;
220 typename Allocator::template rebind<std::pair<Key, Val>>::other;
222 using _vec_t = std::vector<std::pair<Key, Val>, _alloc_t>;
225 auto _find_insert_pos(
const Key& k) noexcept {
226 const auto b = _vec.begin();
227 const auto e = _vec.end();
228 const auto p = _ops().lower_bound(b, e, k);
230 return std::pair{p, (p == e) || (k != p->first)};
233 template <
typename I>
234 auto _find_insert_pos(I p,
const Key& k) {
235 auto b = _vec.begin();
238 if(_vec.empty() || value_comp()(_vec.back(), k)) {
239 return std::pair{p,
true};
241 p = _ops().lower_bound(b, e, k);
244 return std::pair{p,
false};
246 if(key_comp()(k, p->first)) {
248 p = _ops().lower_bound(b, p, k);
251 p = _ops().lower_bound(p, e, k);
253 return std::pair{p,
true};
256 template <
typename I,
typename... Args>
257 auto _do_emplace(I ip,
const Key& key, Args&&... args) -> I {
260 _vec.emplace(ip.first, key, Val{std::forward<Args>(args)...});
265 template <
typename I,
typename V>
266 auto _do_insert(I ip,
const V& value) -> I {
268 ip.first = _vec.insert(ip.first, value);
274 using typename _base::key_compare;
275 using typename _base::key_type;
276 using typename _base::mapped_type;
278 using size_type =
typename _vec_t::size_type;
279 using difference_type =
typename _vec_t::difference_type;
280 using iterator =
typename _vec_t::iterator;
281 using const_iterator =
typename _vec_t::const_iterator;
282 using allocator_type = Allocator;
284 using _base::key_comp;
285 using _base::lower_bound;
286 using _base::value_comp;
288 flat_map() noexcept = default;
289 flat_map(const flat_map&) = default;
290 flat_map(flat_map&&) noexcept = default;
291 auto operator=(const flat_map&) -> flat_map& = default;
292 auto operator=(flat_map&&) noexcept -> flat_map& = default;
293 ~flat_map() noexcept = default;
295 flat_map(std::initializer_list<std::pair<Key, Val>> il) {
299 flat_map(
const std::vector<value_type>& v) {
303 void assign(std::initializer_list<std::pair<Key, Val>> il) {
305 std::sort(_vec.begin(), _vec.end(), value_comp());
308 void assign(
const std::vector<value_type>& v) {
309 _vec = _vec_t(v.begin(), v.end());
310 std::sort(_vec.begin(), _vec.end(), value_comp());
313 auto empty() const ->
bool {
317 auto size() const -> size_type {
321 auto max_size() const -> size_type {
322 return _vec.max_size();
325 auto reserve(size_type sz) ->
auto& {
330 auto clear() ->
auto& {
335 auto begin() -> iterator {
339 auto begin() const -> const_iterator {
343 auto end() -> iterator {
347 auto end() const -> const_iterator {
351 auto operator[](
const Key& key) ->
auto& {
352 auto ip = _find_insert_pos(key);
353 ip = _do_emplace(ip, key);
354 return ip.first->second;
357 template <
typename... Args>
358 auto emplace(
const Key& key, Args&&... args) -> std::pair<iterator, bool> {
359 auto ip = _find_insert_pos(key);
360 ip = _do_emplace(ip, key, std::forward<Args>(args)...);
364 template <
typename... Args>
365 auto try_emplace(
const Key& key, Args&&... args)
366 -> std::pair<iterator, bool> {
367 auto ip = _find_insert_pos(key);
368 ip = _do_emplace(ip, key, std::forward<Args>(args)...);
372 auto insert(
const value_type& value) -> std::pair<iterator, bool> {
373 auto ip = _find_insert_pos(value.first);
374 ip = _do_insert(ip, value);
375 return {ip.first, ip.second};
378 auto insert(iterator p,
const value_type& value) -> iterator {
379 const auto ip = _find_insert_pos(p, value.first);
380 return _do_insert(ip, value).first;
383 auto erase(iterator p) -> iterator {
384 return _vec.erase(p);
387 auto erase(iterator f, iterator t) -> iterator {
388 return _vec.erase(f, t);
391 auto erase(
const Key& key) -> size_type {
392 const auto p = _ops().equal_range(_vec.begin(), _vec.end(), key);
393 const auto res = size_type(
std::distance(p.first, p.second));
394 EAGINE_ASSERT(res <= 1);
395 _vec.erase(p.first, p.second);
399 template <
typename Predicate>
400 auto erase_if(
const Predicate& predicate) -> size_type {
401 const auto p = std::remove_if(_vec.begin(), _vec.end(), predicate);
403 _vec.erase(p, _vec.end());
410 #endif // EAGINE_FLAT_MAP_HPP