Skip to content

Instantly share code, notes, and snippets.

@milasudril
Created August 6, 2022 10:18
Show Gist options
  • Save milasudril/034893541a4874c4b8a49c91ea1b04ac to your computer and use it in GitHub Desktop.
Save milasudril/034893541a4874c4b8a49c91ea1b04ac to your computer and use it in GitHub Desktop.
Structure of array class
#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