OGLplus  (0.59.0) a C++ wrapper for rendering APIs

flat_set.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_FLAT_SET_HPP
10 #define EAGINE_FLAT_SET_HPP
11 
12 #include "assert.hpp"
13 #include "types.hpp"
14 #include <algorithm>
15 #include <stdexcept>
16 #include <utility>
17 #include <vector>
18 
19 namespace eagine {
20 //------------------------------------------------------------------------------
21 template <
22  typename Key,
23  typename Compare = std::less<Key>,
24  class Allocator = std::allocator<Key>>
25 class flat_set : private Compare {
26 
27  using _vec_t = std::vector<Key, Allocator>;
28  _vec_t _vec;
29 
30  auto _find_insert_pos(const Key& k) const noexcept {
31  const auto b = _vec.begin();
32  const auto e = _vec.end();
33  const auto p = std::lower_bound(b, e, k, key_comp());
34 
35  return std::pair{p, (p == e) || (k != *p)};
36  }
37 
38  template <typename I>
39  auto _find_insert_pos(I p, const Key& k) const noexcept {
40  auto b = _vec.begin();
41  auto e = _vec.end();
42  if(p == e) {
43  if(_vec.empty() || value_comp()(_vec.back(), k)) {
44  return std::pair{p, true};
45  }
46  p = std::lower_bound(b, e, k, key_comp());
47  }
48  if(k == *p) {
49  return std::pair{p, false};
50  }
51  if(key_comp()(k, *p)) {
52  if(p != b) {
53  p = std::lower_bound(b, p, k, key_comp());
54  }
55  } else {
56  p = std::lower_bound(p, e, k, key_comp());
57  }
58  return std::pair{p, true};
59  }
60 
61  template <typename I>
62  auto _do_insert(I ip, const Key& value) -> I {
63  if(ip.second) {
64  ip.first = _vec.insert(ip.first, value);
65  }
66  return ip;
67  }
68 
69 public:
70  using key_type = Key;
71  using value_type = Key;
72  using size_type = typename _vec_t::size_type;
73  using difference_type = typename _vec_t::difference_type;
74  using iterator = typename _vec_t::const_iterator;
75  using const_iterator = typename _vec_t::const_iterator;
76  using allocator_type = Allocator;
77  using reference = value_type&;
78  using const_reference = const value_type&;
79 
80  flat_set() noexcept = default;
81  flat_set(const flat_set&) = default;
82  flat_set(flat_set&&) noexcept = default;
83  auto operator=(const flat_set&) -> flat_set& = default;
84  auto operator=(flat_set&&) noexcept -> flat_set& = default;
85  ~flat_set() noexcept = default;
86 
87  flat_set(std::initializer_list<Key> il) {
88  assign(il);
89  }
90 
91  flat_set(const std::vector<value_type>& v) {
92  assign(v);
93  }
94 
95  void assign(std::initializer_list<Key> il) {
96  _vec = _vec_t(il);
97  std::sort(_vec.begin(), _vec.end(), value_comp());
98  }
99 
100  void assign(const std::vector<value_type>& v) {
101  _vec = _vec_t(v.begin(), v.end());
102  std::sort(_vec.begin(), _vec.end(), value_comp());
103  }
104 
105  auto key_comp() const noexcept -> const Compare& {
106  return *this;
107  }
108 
109  auto value_comp() const noexcept -> const Compare& {
110  return *this;
111  }
112 
113  auto empty() const noexcept {
114  return _vec.empty();
115  }
116 
117  auto size() const noexcept {
118  return _vec.size();
119  }
120 
121  auto max_size() const noexcept {
122  return _vec.max_size();
123  }
124 
125  auto begin() -> iterator {
126  return _vec.begin();
127  }
128 
129  auto begin() const -> const_iterator {
130  return _vec.begin();
131  }
132 
133  auto end() -> iterator {
134  return _vec.end();
135  }
136 
137  auto end() const -> const_iterator {
138  return _vec.end();
139  }
140 
141  auto lower_bound(const Key& key) const noexcept {
142  return ::std::lower_bound(begin(), end(), key, value_comp());
143  }
144 
145  auto upper_bound(const Key& key) const noexcept {
146  return ::std::upper_bound(begin(), end(), key, value_comp());
147  }
148 
149  auto equal_range(const Key& key) const noexcept {
150  return ::std::equal_range(begin(), end(), key, value_comp());
151  }
152 
153  auto find(const Key& key) const noexcept {
154  auto [p, i] = _find_insert_pos(key);
155  return i ? _vec.end() : p;
156  }
157 
158  auto contains(const Key& key) const noexcept {
159  return !_find_insert_pos(key).second;
160  }
161 
162  auto clear() noexcept {
163  _vec.clear();
164  }
165 
166  auto insert(const value_type& value) -> std::pair<iterator, bool> {
167  auto ip = _find_insert_pos(value);
168  ip = _do_insert(ip, value);
169  return {ip.first, ip.second};
170  }
171 
172  auto insert(iterator p, const value_type& value) -> iterator {
173  const auto ip = _find_insert_pos(p, value);
174  return _do_insert(ip, value).first;
175  }
176 
177  auto erase(iterator p) -> iterator {
178  return _vec.erase(p);
179  }
180 
181  auto erase(iterator f, iterator t) -> iterator {
182  return _vec.erase(f, t);
183  }
184 
185  auto erase(const Key& key) -> size_type {
186  const auto p =
187  std::equal_range(_vec.begin(), _vec.end(), key, key_comp());
188  const auto res = size_type(std::distance(p.first, p.second));
189  EAGINE_ASSERT(res <= 1);
190  _vec.erase(p.first, p.second);
191  return res;
192  }
193 };
194 //------------------------------------------------------------------------------
195 } // namespace eagine
196 
197 #endif
value_type
Value tree value element data type enumeration.
Definition: interface.hpp:27
Common code is placed in this namespace.
Definition: eagine.hpp:21
static constexpr auto distance(const vector< T, N, V > &a, const vector< T, N, V > &b) noexcept
Returns the distance between two vectors.
Definition: vector.hpp:388
static auto find(basic_span< T1, P1, S1 > where, basic_span< T2, P2, S2 > what) -> basic_span< T1, P1, S1 >
Finds the position of the last occurrence of what in a span.
Definition: span_algo.hpp:374
static auto sort(basic_span< T, P, S > spn) -> basic_span< T, P, S >
Sorts the elements of a span.
Definition: span_algo.hpp:609
static constexpr auto contains(basic_span< T1, P1, S1 > spn, basic_span< T2, P2, S2 > what) noexcept -> S1
Indicates if a span contains the contents of what.
Definition: span_algo.hpp:237

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).