4#include <clingo/util/macro.hh>
12namespace CppClingo::Util {
23template <
class T,
size_t N = 2>
24 requires(std::is_nothrow_destructible_v<T> && std::is_nothrow_move_constructible_v<T>)
47 reserve(other.
size());
48 std::ranges::copy(other, std::back_inserter(*
this));
59 template <std::input_iterator It, std::sentinel_for<It> Is>
void assign(It first, Is last) {
61 if constexpr (std::sized_sentinel_for<Is, It>) {
62 size_t n = std::ranges::distance(first, last);
65 auto ie = std::next(ib, n);
66 std::ranges::uninitialized_copy(first, last, ib, ie);
73 std::ranges::copy(first, last, std::back_inserter(*
this));
82 reserve(other.size());
83 std::ranges::copy(other, std::back_inserter(*
this));
91 if (other.is_small_()) {
92 std::uninitialized_move_n(other.begin_small_(), other.size_small_(), begin_small_());
93 std::ranges::destroy_n(other.begin_small_(), other.size_small_());
94 std::ranges::swap(other.begin_, begin_);
96 std::ranges::swap(begin_, other.begin_);
97 std::ranges::swap(end_large_(), other.end_large_());
98 std::ranges::swap(cap_large_(), other.cap_large_());
108 erase(begin() + n, end());
122 [[nodiscard]]
auto size() const ->
size_t {
124 return size_small_();
126 return std::ranges::distance(begin_large_(), end_large_());
130 [[nodiscard]]
auto empty() const ->
bool {
return size() == 0; }
141 return std::ranges::distance(begin_large_(), cap_large_());
145 [[nodiscard]]
auto begin() ->
iterator {
return is_small_() ? begin_small_() : begin_large_(); }
159 return std::ranges::next(begin(), size_small_());
185 return *std::ranges::next(begin(), i);
191 return *std::ranges::next(begin(), i);
196 if (
auto m = capacity(); m < n) {
201 auto *data = ::operator
new[](
sizeof(
value_type) * n);
202 std::uninitialized_move(begin(), end(),
static_cast<pointer>(data));
205 begin_ =
reinterpret_cast<uintptr_t
>(data);
206 end_large_() = std::ranges::next(begin_large_(), l);
207 cap_large_() = std::ranges::next(begin_large_(), n);
227 return *std::ranges::prev(end());
233 return *std::ranges::prev(end());
239 std::ranges::destroy_at(std::move(std::ranges::next(it), end(), it));
241 size_small_(size_small_() - 1);
243 std::ranges::advance(end_large_(), -1);
251 assert(first <= last);
252 if (
auto n = std::ranges::distance(first, last); n > 0) {
253 std::ranges::destroy(std::move(last, end(), first), end());
255 size_small_(size_small_() - n);
257 std::ranges::advance(end_large_(), -n);
258 std::ranges::advance(last, -n);
268 auto i = std::ranges::distance(cbegin(), loc);
270 auto it = std::next(begin(), i);
271 if (
auto ie = end(), ip = std::ranges::prev(ie); it != ie) {
272 std::ranges::construct_at(ie, std::move(*ip));
273 std::ranges::move_backward(it, ip, ie);
275 std::ranges::construct_at(it, std::forward<U>(args)...);
277 size_small_(size_small_() + 1);
279 std::ranges::advance(end_large_(), 1);
287 std::ranges::construct_at(end(), std::forward<U>(args)...);
289 size_small_(size_small_() + 1);
291 std::advance(end_large_(), 1);
302 std::destroy_at(std::prev(end()));
304 size_small_(size_small_() - 1);
306 std::advance(end_large_(), -1);
324 [[nodiscard]]
auto begin_large_() const -> pointer {
326 return reinterpret_cast<T *
>(begin_);
328 [[nodiscard]]
auto end_large_() -> pointer & {
332 [[nodiscard]]
auto end_large_() const -> pointer {
336 [[nodiscard]]
auto cap_large_() const -> pointer {
340 [[nodiscard]]
auto cap_large_() -> pointer & {
344 [[nodiscard]]
auto begin_small_() -> pointer {
346 return reinterpret_cast<T *
>(buf_);
348 [[nodiscard]]
auto is_small_() const ->
bool {
return (begin_ & 1) != 0; }
349 [[nodiscard]]
auto size_small_() const ->
size_t {
return begin_ >> 1; }
350 [[nodiscard]]
auto size_small_(
size_t n) { begin_ = (n << 1) | 1; }
354 [[nodiscard]]
auto check_() const ->
bool {
356 return size_small_() <= N;
358 return begin_large_() <= end_large_() && end_large_() <= cap_large_();
362 void destroy_() noexcept {
363 std::destroy(begin(), end());
365 ::operator
delete[](begin_large_());
369 friend auto operator<=>(small_vector
const &lhs, small_vector
const &rhs) {
371 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
374 friend auto operator==(small_vector
const &lhs, small_vector
const &rhs) {
return std::ranges::equal(lhs, rhs); }
376 CLINGO_IGNORE_UNION_B
377 uintptr_t begin_ = 1;
381 alignas(value_type)
unsigned char buf_[N *
sizeof(value_type)];
388 CLINGO_IGNORE_UNION_E
A vector that misuses the begin, end and capacity pointers to store elements.
Definition small_vector.hh:26
T const * const_pointer
The const pointer type.
Definition small_vector.hh:41
auto cend() const -> const_iterator
Get a const iterator to the end of the vector.
Definition small_vector.hh:171
void assign(It first, Is last)
Assign the vector.
Definition small_vector.hh:59
auto cbegin() const -> const_iterator
Get a const iterator to the beginning of the vector.
Definition small_vector.hh:154
void pop_back()
Pop the last element.
Definition small_vector.hh:300
void reserve(size_t n)
Reserve space for at least n elements.
Definition small_vector.hh:195
auto begin() const -> const_iterator
Get a const iterator to the beginning of the vector.
Definition small_vector.hh:148
~small_vector() noexcept
Deconstruct the vector.
Definition small_vector.hh:321
auto front() -> reference
Get the first element in the vector.
Definition small_vector.hh:213
auto erase(iterator first, iterator last) -> iterator
Erase the given range of elements.
Definition small_vector.hh:250
void resize(size_t n)
Resize to the given size.
Definition small_vector.hh:106
void push_back(value_type const &x)
Append an element after the last element.
Definition small_vector.hh:297
auto capacity() const -> size_t
Get the capacity of the vector.
Definition small_vector.hh:137
auto data() const -> const_iterator
Get a const pointer to the stored C array.
Definition small_vector.hh:177
auto operator=(small_vector &&other) noexcept -> small_vector &
Move assign the vector.
Definition small_vector.hh:88
T & reference
The reference type.
Definition small_vector.hh:35
auto front() const -> const_reference
Get the first element in the vector.
Definition small_vector.hh:219
auto operator[](size_t i) const -> const_reference
Get the element at the given index.
Definition small_vector.hh:189
T value_type
The value type.
Definition small_vector.hh:29
small_vector(It begin, Is end)
Initialize vector from an iterator range.
Definition small_vector.hh:54
small_vector()=default
Construct an empty vector.
auto end() const -> const_iterator
Get a const iterator to the end of the vector.
Definition small_vector.hh:165
void emplace(const_iterator loc, U &&...args)
Emplace an element before the given iterator.
Definition small_vector.hh:266
T const & const_reference
The const reference type.
Definition small_vector.hh:37
T const * const_iterator
The const iterator type.
Definition small_vector.hh:33
auto begin() -> iterator
Get an iterator to the beginning of the vector.
Definition small_vector.hh:145
auto data() -> iterator
Get a pointer to the stored C array.
Definition small_vector.hh:174
void emplace_back(U &&...args)
Emplace an element after the last element.
Definition small_vector.hh:285
auto end() -> iterator
Get an iterator to the end of the vector.
Definition small_vector.hh:157
auto back() -> reference
Get the last element in the vector.
Definition small_vector.hh:225
auto operator[](size_t i) -> reference
Get the element at the given index.
Definition small_vector.hh:183
small_vector(small_vector const &other)
Copy construct the vector.
Definition small_vector.hh:46
T * pointer
The pointer type.
Definition small_vector.hh:39
auto operator=(small_vector const &other) -> small_vector &
Copy assign the vector.
Definition small_vector.hh:79
auto erase(iterator it) -> iterator
Erase the given element.
Definition small_vector.hh:237
small_vector(small_vector &&other) noexcept
Move construct the vector.
Definition small_vector.hh:51
T * iterator
The iterator type.
Definition small_vector.hh:31
auto back() const -> const_reference
Get the last element in the vector.
Definition small_vector.hh:231
auto empty() const -> bool
Check if the vector is empty.
Definition small_vector.hh:130
auto size() const -> size_t
Get the size of the vector.
Definition small_vector.hh:122
auto cdata() const -> const_iterator
Get a const pointer to the stored C array.
Definition small_vector.hh:180
void clear() noexcept
Clear the vector.
Definition small_vector.hh:314