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));
81 reserve(other.size());
82 std::ranges::copy(other, std::back_inserter(*
this));
90 if (other.is_small_()) {
91 std::uninitialized_move_n(other.begin_small_(), other.size_small_(), begin_small_());
92 std::ranges::destroy_n(other.begin_small_(), other.size_small_());
93 std::ranges::swap(other.begin_, begin_);
95 std::ranges::swap(begin_, other.begin_);
96 std::ranges::swap(end_large_(), other.end_large_());
97 std::ranges::swap(cap_large_(), other.cap_large_());
106 erase(begin() + n, end());
116 [[nodiscard]]
auto size() const ->
size_t {
118 return size_small_();
120 return std::ranges::distance(begin_large_(), end_large_());
124 [[nodiscard]]
auto empty() const ->
bool {
return size() == 0; }
131 return std::ranges::distance(begin_large_(), end_large_());
135 [[nodiscard]]
auto begin() ->
iterator {
return is_small_() ? begin_small_() : begin_large_(); }
149 return std::ranges::next(begin(), size_small_());
175 return *std::ranges::next(begin(), i);
181 return *std::ranges::next(begin(), i);
186 if (
auto m = capacity(); m < n) {
191 auto *data = ::operator
new[](
sizeof(
value_type) * n);
192 std::uninitialized_move(begin(), end(),
static_cast<pointer>(data));
195 begin_ =
reinterpret_cast<uintptr_t
>(data);
196 end_large_() = std::ranges::next(begin_large_(), l);
197 cap_large_() = std::ranges::next(begin_large_(), n);
216 return *std::ranges::prev(end());
222 return *std::ranges::prev(end());
228 std::ranges::destroy_at(std::move(std::ranges::next(it), end(), it));
230 size_small_(size_small_() - 1);
232 std::ranges::advance(end_large_(), -1);
239 assert(first <= last);
240 if (
auto n = std::ranges::distance(first, last); n > 0) {
241 std::ranges::destroy(std::move(last, end(), first), end());
243 size_small_(size_small_() - n);
245 std::ranges::advance(end_large_(), -n);
246 std::ranges::advance(last, -n);
255 auto i = std::ranges::distance(cbegin(), loc);
257 auto it = std::next(begin(), i);
258 if (
auto ie = end(), ip = std::ranges::prev(ie); it != ie) {
259 std::ranges::construct_at(ie, std::move(*ip));
260 std::ranges::move_backward(it, ip, ie);
262 std::ranges::construct_at(it, std::forward<U>(args)...);
264 size_small_(size_small_() + 1);
266 std::ranges::advance(end_large_(), 1);
273 std::ranges::construct_at(end(), std::forward<U>(args)...);
275 size_small_(size_small_() + 1);
277 std::advance(end_large_(), 1);
287 std::destroy_at(std::prev(end()));
289 size_small_(size_small_() - 1);
291 std::advance(end_large_(), -1);
307 [[nodiscard]]
auto begin_large_() const -> pointer {
309 return reinterpret_cast<T *
>(begin_);
311 [[nodiscard]]
auto end_large_() -> pointer & {
315 [[nodiscard]]
auto end_large_() const -> pointer {
319 [[nodiscard]]
auto cap_large_() const -> pointer {
323 [[nodiscard]]
auto cap_large_() -> pointer & {
327 [[nodiscard]]
auto begin_small_() -> pointer {
329 return reinterpret_cast<T *
>(buf_);
331 [[nodiscard]]
auto is_small_() const ->
bool {
return (begin_ & 1) != 0; }
332 [[nodiscard]]
auto size_small_() const ->
size_t {
return begin_ >> 1; }
333 [[nodiscard]]
auto size_small_(
size_t n) { begin_ = (n << 1) | 1; }
335 void destroy_() noexcept {
336 std::destroy(begin(), end());
338 ::operator
delete[](begin_large_());
342 friend auto operator<=>(small_vector
const &lhs, small_vector
const &rhs) {
344 return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
347 friend auto operator==(small_vector
const &lhs, small_vector
const &rhs) {
return std::ranges::equal(lhs, rhs); }
349 CLINGO_IGNORE_UNION_B
350 uintptr_t begin_ = 1;
354 alignas(value_type)
unsigned char buf_[N *
sizeof(value_type)];
361 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:161
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:144
void pop_back()
Pop the last element.
Definition small_vector.hh:285
void reserve(size_t n)
Reserve space for at least n elements.
Definition small_vector.hh:185
auto begin() const -> const_iterator
Get a const iterator to the beginning of the vector.
Definition small_vector.hh:138
~small_vector() noexcept
Deconstruct the vector.
Definition small_vector.hh:304
auto front() -> reference
Get the first element in the vector.
Definition small_vector.hh:202
auto erase(iterator first, iterator last) -> iterator
Erase the given range of elements.
Definition small_vector.hh:238
void resize(size_t n)
Resize to the given size.
Definition small_vector.hh:104
void push_back(value_type const &x)
Append an element after the last element.
Definition small_vector.hh:282
auto capacity() const -> size_t
Get the capacity of the vector.
Definition small_vector.hh:127
auto data() const -> const_iterator
Get a const pointer to the stored C array.
Definition small_vector.hh:167
auto operator=(small_vector &&other) noexcept -> small_vector &
Move assign the vector.
Definition small_vector.hh:87
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:208
auto operator[](size_t i) const -> const_reference
Get the element at the given index.
Definition small_vector.hh:179
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:155
void emplace(const_iterator loc, U &&...args)
Emplace an element before the given iterator.
Definition small_vector.hh:253
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:135
auto data() -> iterator
Get a pointer to the stored C array.
Definition small_vector.hh:164
void emplace_back(U &&...args)
Emplace an element after the last element.
Definition small_vector.hh:271
auto end() -> iterator
Get an iterator to the end of the vector.
Definition small_vector.hh:147
auto back() -> reference
Get the last element in the vector.
Definition small_vector.hh:214
auto operator[](size_t i) -> reference
Get the element at the given index.
Definition small_vector.hh:173
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:78
auto erase(iterator it) -> iterator
Erase the given element.
Definition small_vector.hh:226
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:220
auto empty() const -> bool
Check if the vector is empty.
Definition small_vector.hh:124
auto size() const -> size_t
Get the size of the vector.
Definition small_vector.hh:116
auto cdata() const -> const_iterator
Get a const pointer to the stored C array.
Definition small_vector.hh:170
void clear() noexcept
Clear the vector.
Definition small_vector.hh:298