1#ifndef KOUTIL_CONTAINER_MULTI_VECTOR_H
2#define KOUTIL_CONTAINER_MULTI_VECTOR_H
34 template <
typename T,
typename Allocator = std::allocator<T>>
class single_vector {
37 : m_data(Allocator().allocate(n))
40 std::uninitialized_fill_n(m_data, n, T());
44 : m_data(Allocator().allocate(n))
47 std::uninitialized_fill_n(m_data, n, value);
53 : m_data(Allocator().allocate(other.m_capacity))
54 , m_capacity(other.m_capacity)
55 , m_size(other.m_size) {
56 std::uninitialized_copy_n(other.
m_data, other.
m_size, m_data);
60 if (m_capacity != 0) {
61 std::destroy_n(m_data, m_size);
62 Allocator().deallocate(m_data, m_capacity);
67 : m_data(other.m_data)
68 , m_capacity(other.m_capacity)
69 , m_size(other.m_size) {
72 other.m_data =
nullptr;
76 if (m_capacity != 0) {
77 std::destroy_n(m_data, m_size);
78 Allocator().deallocate(m_data, m_capacity);
81 m_size = other.m_size;
82 m_capacity = other.m_capacity;
83 m_data = other.m_data;
87 other.m_data =
nullptr;
97 std::destroy_n(m_data, m_size);
99 auto alloc = Allocator();
101 alloc.deallocate(m_data, m_capacity);
106 std::uninitialized_copy_n(other.
m_data, other.
m_size, m_data);
117 std::swap(m_data, other.
m_data);
118 std::swap(m_size, other.
m_size);
123 try_update_capacity();
125 m_data[m_size] = value;
130 try_update_capacity();
132 m_data[m_size] = std::move(value);
137 try_update_capacity();
139 m_data[m_size] = T(std::forward<
decltype(arg)>(arg));
142 return m_data[m_size - 1];
146 assert(element <= m_data + m_size && element >= m_data);
149 if (m_data + m_size == element) {
151 return m_data + m_size;
155 if (m_size == m_capacity / 2) {
159 const auto index =
static_cast<std::size_t
>(element - m_data);
161 realloc_without(m_capacity, index);
163 return m_data + index;
173 void resize(std::size_t n,
const T& value) {
179 if (m_capacity >= n) {
180 std::uninitialized_fill_n(m_data + m_size, m_capacity - m_size, value);
182 realloc_with_value(n, value);
188 if (n <= m_capacity) {
195 T&
at(std::size_t i) {
return m_data[i]; }
197 [[nodiscard]]
const T&
at(std::size_t i)
const {
return m_data[i]; }
201 [[nodiscard]]
const T*
data()
const {
return m_data; }
203 [[nodiscard]] std::size_t
size()
const {
return m_size; }
207 const T*
begin()
const {
return m_data; }
209 T*
end() {
return m_data + m_size; }
211 const T*
end()
const {
return m_data + m_size; }
215 std::size_t m_capacity = 0;
216 std::size_t m_size = 0;
219 if (m_capacity == 0) {
222 return m_capacity * 2;
227 if (m_size + 1 <= m_capacity) {
230 realloc(next_capacity());
234 const std::size_t old_capacity = m_capacity;
235 m_capacity = capacity;
237 auto alloc = Allocator();
238 auto* new_data =
new (alloc.allocate(m_capacity)) T[m_capacity];
240 std::uninitialized_move(m_data, m_data + m_size, new_data);
242 std::destroy_n(m_data, m_size);
243 alloc.deallocate(m_data, old_capacity);
249 std::uninitialized_fill_n(m_data + m_size, m_capacity - m_size, value);
253 const std::size_t old_capacity = m_capacity;
254 m_capacity = capacity;
256 auto alloc = Allocator();
257 T* new_data =
nullptr;
259 if (m_capacity != 0) {
260 new_data =
new (alloc.allocate(m_capacity)) T[m_capacity];
261 std::uninitialized_move_n(m_data, index, new_data);
262 std::uninitialized_move_n(m_data + index + 1, m_size - index, new_data);
265 std::destroy_n(m_data, m_size + 1);
266 alloc.deallocate(m_data, old_capacity);
278 template <type::types_concept T, type::types_container Container>
281 template <type::types_concept T, type::types_transform Transform>
289 static constexpr auto helper_seq = std::make_index_sequence<types::size>();
297 template <
bool is_const>
class iterator;
327 explicit multi_vector(std::size_t count) { init_vector_default(count); }
333 template <std::
size_t I>
decltype(
auto) get_container() {
335 static_assert(!std::is_same_v<type::types_get_t<all_types, I>,
void>,
"This type was removed");
339 constexpr std::size_t index = view::size - count_void;
343 auto& container = std::get<index>(m_storage);
345 if constexpr (std::is_same_v<element, bool>) {
346 return std::span<bool>(container.begin(), container.end());
348 return std::span { container };
352 template <std::
size_t I>
decltype(
auto) get_container()
const {
354 static_assert(!std::is_same_v<type::types_get_t<all_types, I>,
void>,
"This type was removed");
358 constexpr std::size_t index = view::size - count_void;
362 const auto& container = std::get<index>(m_storage);
364 if constexpr (std::is_same_v<element, bool>) {
365 return std::span<bool>(container.begin(), container.end());
367 return std::span { container };
376 value_ref_t front() {
386 const_value_ref_t front()
const {
398 return at(size() - 1);
406 const_value_ref_t back()
const {
408 return at(size() - 1);
417 value_ref_t at(std::size_t pos) {
418 assert(pos < size());
419 return get_all(pos, helper_seq);
428 const_value_ref_t at(std::size_t pos)
const {
429 assert(pos < size());
430 return get_all(pos, helper_seq);
439 value_ref_t operator[](std::size_t pos) {
return at(pos); }
447 const_value_ref_t operator[](std::size_t pos)
const {
return at(pos); }
454 [[nodiscard]] std::size_t size()
const {
return std::get<0>(m_storage).size(); }
461 [[nodiscard]]
bool empty()
const {
return size() == 0; }
466 void clear() { clear_all(helper_seq); }
473 void swap(multi_vector& other) { std::swap(other.m_storage, m_storage); }
480 void resize(std::size_t size) { resize_all(size, helper_seq); }
488 void resize(std::size_t size,
const value_t& value) { resize_all_with(size, value, helper_seq); }
495 void reserve(std::size_t size) { reserve_impl(size, helper_seq); }
500 void pop_back() { pop_back_impl(helper_seq); }
509 template <
typename... Args>
510 requires(
sizeof...(Args) == types::size)
512 return emplace_back_impl(helper_seq, std::forward<
decltype(args)>(args)...);
520 void push_back(
const value_t& value) { push_back_impl(value, helper_seq); }
527 void push_back(value_t&& value) { push_back_impl(std::move(value), helper_seq); }
532 void shrink_to_fit() { shrink_to_fit_impl(helper_seq); }
540 iterator_t erase(const_iterator_t pos) {
543 const auto dist =
static_cast<std::size_t
>(pos - begin());
544 if (dist >= size()) {
547 return iterator_t {
this, dist };
556 iterator_t begin() {
return iterator_t {
this, 0 }; }
563 const_iterator_t begin()
const {
return const_iterator_t {
this, 0 }; }
570 const_iterator_t cbegin()
const {
return const_iterator_t {
this, 0 }; }
577 iterator_t end() {
return iterator_t {
this, size() }; }
584 const_iterator_t end()
const {
return const_iterator_t {
this, size() }; }
591 const_iterator_t cend()
const {
return const_iterator_t {
this, size() }; }
603 template <std::
size_t I = 0>
void init_vector(std::size_t count,
const value_t& value) {
608 if constexpr (I + 1 < types::size) {
609 init_vector<I + 1>(count, value);
619 template <std::
size_t I = 0>
void init_vector_default(std::size_t count) {
622 std::get<I>(m_storage) = single_vector<vector_element>(count);
624 if constexpr (I + 1 < types::size) {
625 init_vector_default<I + 1>(count);
636 template <std::
size_t I>
auto& get_single(std::size_t pos) {
return std::get<I>(m_storage).at(pos); }
645 template <std::
size_t I>
const auto& get_single(std::size_t pos)
const {
return std::get<I>(m_storage).at(pos); }
654 template <std::size_t... I> value_ref_t get_all(std::size_t pos, std::index_sequence<I...> ) {
655 return { get_single<I>(pos)... };
665 template <std::size_t... I> const_value_ref_t get_all(std::size_t pos, std::index_sequence<I...> )
const {
666 return { get_single<I>(pos)... };
674 template <std::size_t... I>
void clear_all(std::index_sequence<I...> ) {
675 (std::get<I>(m_storage).clear(), ...);
684 template <std::size_t... I>
void resize_all(std::size_t size, std::index_sequence<I...> ) {
685 (std::get<I>(m_storage).resize(size), ...);
695 template <std::size_t... I>
696 void resize_all_with(std::size_t size,
const value_t& value, std::index_sequence<I...> ) {
697 (std::get<I>(m_storage).resize(size, std::get<I>(value)), ...);
705 template <std::size_t... I>
void pop_back_impl(std::index_sequence<I...> ) {
706 (std::get<I>(m_storage).pop_back(), ...);
716 template <
typename Value, std::size_t... I>
717 void push_back_impl(Value&& value, std::index_sequence<I...> ) {
718 (std::get<I>(m_storage).push_back(std::get<I>(std::forward<
decltype(value)>(value))), ...);
729 template <
typename... Args, std::size_t... I>
730 value_ref_t emplace_back_impl(std::index_sequence<I...> , Args&&... args) {
731 return std::forward_as_tuple(std::get<I>(m_storage).emplace_back(std::forward<
decltype(args)>(args))...);
739 template <std::size_t... I>
void shrink_to_fit_impl(std::index_sequence<I...> ) {
740 (std::get<I>(m_storage).shrink_to_fit(), ...);
749 template <std::size_t... I>
void reserve_impl(std::size_t size, std::index_sequence<I...> ) {
750 (std::get<I>(m_storage).reserve(size), ...);
759 template <std::
size_t I = 0>
void erase_impl(const_iterator_t pos) {
760 auto& vec = std::get<I>(m_storage);
761 vec.erase(vec.begin() + pos.m_index);
763 if constexpr (I + 1 < types::size) {
764 erase_impl<I + 1>(pos);
775template <is_multi_vector_element... T>
777template <bool is_const>
780 using vec_ptr_t = std::conditional_t<is_const, const multi_vector*, multi_vector*>;
783 using value_type = std::conditional_t<is_const, const_value_ref_t, value_ref_t>;
800 return m_ref->at(m_index);
850 return m_ref->at(m_index + n);
866 std::size_t m_index = 0;
Nested iterator class for multi_vector.
Definition multi_vector.h:778
bool operator!=(const iterator &other) const =default
bool operator==(const iterator &other) const =default
iterator(iterator &&)=default
difference_type operator-(const iterator &other) const
Definition multi_vector.h:823
bool operator<=(const iterator &other) const
Definition multi_vector.h:858
std::ptrdiff_t difference_type
Definition multi_vector.h:786
value_type operator*()
Definition multi_vector.h:797
iterator & operator++()
Definition multi_vector.h:803
iterator & operator--()
Definition multi_vector.h:816
std::conditional_t< is_const, const_value_ref_t, value_ref_t > value_type
Definition multi_vector.h:783
const_value_type operator*() const
Definition multi_vector.h:795
const_value_type operator[](difference_type n) const
Definition multi_vector.h:845
iterator & operator+=(difference_type n)
Definition multi_vector.h:831
iterator & operator-=(difference_type n)
Definition multi_vector.h:836
iterator operator++(int)
Definition multi_vector.h:814
bool operator>=(const iterator &other) const
Definition multi_vector.h:862
std::random_access_iterator_tag iterator_category
Definition multi_vector.h:787
bool operator<(const iterator &other) const
Definition multi_vector.h:856
const_value_ref_t const_value_type
Definition multi_vector.h:784
iterator & operator--(int)
Definition multi_vector.h:821
bool operator>(const iterator &other) const
Definition multi_vector.h:860
std::conditional_t< is_const, const multi_vector *, multi_vector * > vec_ptr_t
Definition multi_vector.h:780
value_type operator[](difference_type n)
Definition multi_vector.h:847
iterator operator+(difference_type n) const
Definition multi_vector.h:841
iterator operator-(difference_type n) const
Definition multi_vector.h:843
value_type reference
Definition multi_vector.h:785
iterator & operator=(const iterator &)=default
iterator(const iterator &)=default
std::size_t m_index
Definition multi_vector.h:866
iterator(vec_ptr_t vec, std::size_t index)
Definition multi_vector.h:868
iterator & operator=(iterator &&)=default
Definition multi_vector.h:34
void push_back(const T &value)
Definition multi_vector.h:122
void clear()
Definition multi_vector.h:114
T * begin()
Definition multi_vector.h:205
std::size_t size() const
Definition multi_vector.h:203
void realloc_with_value(std::size_t capacity, const T &value={})
Definition multi_vector.h:247
single_vector & operator=(single_vector &&other)
Definition multi_vector.h:75
T * data()
Definition multi_vector.h:199
const T * begin() const
Definition multi_vector.h:207
T * erase(const T *element)
Definition multi_vector.h:145
T & at(std::size_t i)
Definition multi_vector.h:195
T * m_data
Definition multi_vector.h:214
void realloc_without(std::size_t capacity, std::size_t index)
Definition multi_vector.h:252
T * end()
Definition multi_vector.h:209
single_vector(std::size_t n)
Definition multi_vector.h:36
const T & at(std::size_t i) const
Definition multi_vector.h:197
void swap(single_vector &other)
Definition multi_vector.h:116
void realloc(std::size_t capacity)
Definition multi_vector.h:233
void resize(std::size_t n)
Definition multi_vector.h:171
single_vector & operator=(const single_vector &other)
Definition multi_vector.h:92
void pop_back()
Definition multi_vector.h:166
~single_vector()
Definition multi_vector.h:59
void reserve(std::size_t n)
Definition multi_vector.h:187
std::size_t m_capacity
Definition multi_vector.h:215
std::size_t next_capacity() const
Definition multi_vector.h:218
void try_update_capacity()
Definition multi_vector.h:226
void push_back(T &&value)
Definition multi_vector.h:129
void resize(std::size_t n, const T &value)
Definition multi_vector.h:173
std::size_t m_size
Definition multi_vector.h:216
const T * end() const
Definition multi_vector.h:211
const T * data() const
Definition multi_vector.h:201
single_vector(single_vector &&other)
Definition multi_vector.h:66
T & emplace_back(Arg &&arg)
Definition multi_vector.h:136
single_vector(const single_vector &other)
Definition multi_vector.h:52
single_vector(std::size_t n, const T &value)
Definition multi_vector.h:43
Class representing a multi_vector.
Definition multi_vector.h:32
transform_types_t< to_containers_t< types, single_vector_container >, transforms::tuple > storage_t
Definition multi_vector.h:287
transform_types_t< transform_types_t< types, transforms::reference >, transforms::tuple > value_ref_t
Definition multi_vector.h:301
transform_types_t< transform_types_t< types, transforms::constant_reference >, transforms::tuple > const_value_ref_t
Definition multi_vector.h:302
transform_types_t< types, transforms::tuple > value_t
Definition multi_vector.h:304
type::types_to_containers_t< T, Container > to_containers_t
Definition multi_vector.h:279
types used_types
Definition multi_vector.h:299
multi_vector(multi_vector &&)=default
type::types_transform_t< T, Transform > transform_types_t
Definition multi_vector.h:282
type::types_remove_t< all_types, void > types
Definition multi_vector.h:285
multi_vector(const multi_vector &)=default
Concept to check if a type is a valid multi_vector element.
Definition multi_vector.h:23
Definition comptime_map.h:11
detail::types_get_impl< Types, I >::type types_get_t
Alias for getting a type by index in a types list.
Definition types.h:381
detail::types_to_containers< Types, Container >::type types_to_containers_t
Alias for transforming a types list to a containers list.
Definition types.h:413
detail::types_remove< Types, T >::type types_remove_t
Definition types.h:438
detail::types_transform_impl< Types, Transform >::type types_transform_t
Alias for transforming a types list using a transform template.
Definition types.h:404
detail::types_view< N, Types >::type types_view_t
Definition types.h:440
Definition multi_vector.h:271
A namespace containing container templates for types lists.
Definition types.h:132
A template structure to count occurrences of a specific type in a types list.
Definition types.h:146
A structure representing a variadic list of types.
Definition types.h:20