Created
August 6, 2022 10:18
-
-
Save milasudril/034893541a4874c4b8a49c91ea1b04ac to your computer and use it in GitHub Desktop.
Structure of array class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
#include <cstddef> | |
#include <memory> | |
#include <span> | |
#include <algorithm> | |
template<size_t I = 0, class... Tp, class F> | |
void for_each_apply(std::tuple<Tp...>& t, F&& f) | |
{ | |
f(std::get<I>(t), std::integral_constant<size_t, I>{}); | |
if constexpr(I + 1 != sizeof...(Tp)) | |
{ | |
for_each_apply<I + 1>(t, std::forward<F>(f)); | |
} | |
} | |
template<size_t I = 0, class... Tp, class F> | |
void for_each_apply(std::tuple<Tp...> const& t, F&& f) | |
{ | |
f(std::get<I>(t), std::integral_constant<size_t, I>{}); | |
if constexpr(I + 1 != sizeof...(Tp)) | |
{ | |
for_each_apply<I + 1>(t, std::forward<F>(f)); | |
} | |
} | |
template<class IndexType, class ... Types> | |
class multi_array | |
{ | |
public: | |
using value_type = std::tuple<Types...>; | |
template<IndexType Index> | |
auto get() const | |
{ | |
return std::span{std::get<static_cast<size_t>(Index)>(m_pointers).get(), m_length}; | |
} | |
size_t size() const { return m_length; } | |
void push_back(value_type&& val) | |
{ | |
if(m_length == m_capacity) | |
{ | |
reserve(std::max(static_cast<size_t>(1), 2*m_capacity)); | |
} | |
scatter(m_length, std::move(val)); | |
++m_length; | |
} | |
void scatter(size_t index, value_type&& val) | |
{ | |
for_each_apply(m_pointers, [index, &val](auto& element, auto tuple_index) mutable { | |
constexpr auto i = tuple_index.value; | |
element[index] = std::move(std::get<i>(val)); | |
}); | |
} | |
value_type gather(size_t index) const | |
{ | |
value_type ret; | |
for_each_apply(m_pointers, [index, &ret](auto const& element, auto tuple_index) mutable { | |
constexpr auto i = tuple_index.value; | |
std::get<i>(ret) = element[index]; | |
}); | |
return ret; | |
} | |
void reserve(size_t new_size) | |
{ | |
for_each_apply(m_pointers, [new_size, current_length = m_length]<class T>(T& element, auto){ | |
auto new_buff = std::make_unique<typename T::element_type[]>(new_size); | |
std::copy_n(element.get(), current_length, new_buff.get()); | |
element = std::move(new_buff); | |
}); | |
m_capacity = new_size; | |
} | |
private: | |
std::tuple<std::unique_ptr<Types[]>...> m_pointers; | |
size_t m_length{0}; | |
size_t m_capacity{0}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment