You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
334 lines
11 KiB
334 lines
11 KiB
#pragma once
|
|
|
|
#include "../stl_alias.hpp"
|
|
|
|
namespace detail
|
|
{
|
|
#define recursive_func_caller(func_name, called_func, ...) \
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); \
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<type, rest...>>>, \
|
|
"try fetching properties from void type in type list."); \
|
|
if constexpr (type_index == type_index_) \
|
|
data.called_func(__VA_ARGS__); \
|
|
else \
|
|
base_type::template func_name<type_index_>(__VA_ARGS__)
|
|
|
|
#define recursive_func_caller_return(func_name, called_func, ...) \
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); \
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<type, rest...>>>, \
|
|
"try fetching properties from void type in type list."); \
|
|
if constexpr (type_index == type_index_) \
|
|
return data.called_func(__VA_ARGS__); \
|
|
else \
|
|
return base_type::template func_name<type_index_>(__VA_ARGS__)
|
|
|
|
#define recursive_func_caller_void(func_name, ...) \
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); \
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<void, rest...>>>, \
|
|
"try fetching properties from void type in type list."); \
|
|
base_type::template func_name<type_index_>(__VA_ARGS__)
|
|
|
|
#define recursive_func_caller_return_void(func_name, ...) \
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); \
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<void, rest...>>>, \
|
|
"try fetching properties from void type in type list."); \
|
|
return base_type::template func_name<type_index_>(__VA_ARGS__)
|
|
|
|
template <size_t type_index, typename type, typename... rest>
|
|
struct compressed_vector_tuple_impl : public compressed_vector_tuple_impl<type_index + 1, rest...> {
|
|
template <size_t type_index_>
|
|
bool empty() const
|
|
{
|
|
recursive_func_caller_return(empty, empty);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
size_t size() const
|
|
{
|
|
recursive_func_caller_return(size, size);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void reserve(size_t new_cap)
|
|
{
|
|
recursive_func_caller(reserve, reserve, new_cap);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void resize(size_t new_sz)
|
|
{
|
|
recursive_func_caller(resize, resize, new_sz);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void clear()
|
|
{
|
|
recursive_func_caller(clear, clear);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void shrink_to_fit()
|
|
{
|
|
recursive_func_caller(shrink_to_fit, shrink_to_fit);
|
|
}
|
|
|
|
template <size_t type_index_, typename... Args>
|
|
auto &emplace_back(Args &&...args)
|
|
{
|
|
recursive_func_caller_return(emplace_back, emplace_back, std::forward<Args>(args)...);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &fetch(size_t index)
|
|
{
|
|
recursive_func_caller_return(fetch, operator[], index);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &fetch(size_t index) const
|
|
{
|
|
recursive_func_caller_return(fetch, operator[], index);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &raw()
|
|
{
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range.");
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<type, rest...>>>,
|
|
"try fetching properties from void type in type list.");
|
|
if constexpr (type_index == type_index_)
|
|
return data;
|
|
else
|
|
return base_type::template raw<type_index_>();
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &raw() const
|
|
{
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range.");
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<type, rest...>>>,
|
|
"try fetching properties from void type in type list.");
|
|
if constexpr (type_index == type_index_)
|
|
return data;
|
|
else
|
|
return base_type::template raw<type_index_>();
|
|
}
|
|
|
|
protected:
|
|
using base_type = compressed_vector_tuple_impl<type_index + 1, rest...>;
|
|
stl_vector_mp<type> data{};
|
|
};
|
|
|
|
template <size_t type_index, typename... rest>
|
|
struct compressed_vector_tuple_impl<type_index, void, rest...> : public compressed_vector_tuple_impl<type_index + 1, rest...> {
|
|
template <size_t type_index_>
|
|
bool empty() const
|
|
{
|
|
recursive_func_caller_return_void(empty);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
size_t size() const
|
|
{
|
|
recursive_func_caller_return_void(size);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void reserve(size_t new_cap)
|
|
{
|
|
recursive_func_caller_void(reserve, new_cap);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void resize(size_t new_sz)
|
|
{
|
|
recursive_func_caller_void(resize, new_sz);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void clear()
|
|
{
|
|
recursive_func_caller_void(clear);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void shrink_to_fit()
|
|
{
|
|
recursive_func_caller_void(shrink_to_fit);
|
|
}
|
|
|
|
template <size_t type_index_, typename... Args>
|
|
auto &emplace_back(Args &&...args)
|
|
{
|
|
recursive_func_caller_return_void(emplace_back, std::forward<Args>(args)...);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &fetch(size_t index)
|
|
{
|
|
recursive_func_caller_return_void(fetch, index);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &fetch(size_t index) const
|
|
{
|
|
recursive_func_caller_return_void(fetch, index);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &raw()
|
|
{
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range.");
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<void, rest...>>>,
|
|
"try fetching properties from void type in type list.");
|
|
|
|
return base_type::template raw<type_index_>();
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &raw() const
|
|
{
|
|
static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range.");
|
|
static_assert(!std::is_void_v<std::tuple_element_t<type_index_ - type_index, std::tuple<void, rest...>>>,
|
|
"try fetching properties from void type in type list.");
|
|
|
|
return base_type::template raw<type_index_>();
|
|
}
|
|
|
|
protected:
|
|
using base_type = compressed_vector_tuple_impl<type_index + 1, rest...>;
|
|
};
|
|
|
|
#undef recursive_func_caller
|
|
#undef recursive_func_caller_return
|
|
#undef recursive_func_caller_void
|
|
#undef recursive_func_caller_return_void
|
|
|
|
template <size_t type_index, typename type>
|
|
struct compressed_vector_tuple_impl<type_index, type> {
|
|
template <size_t type_index_>
|
|
bool empty() const
|
|
{
|
|
return data.empty();
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
size_t size() const
|
|
{
|
|
return data.size();
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void reserve(size_t new_cap)
|
|
{
|
|
data.reserve(new_cap);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void resize(size_t new_sz)
|
|
{
|
|
data.resize(new_sz);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void clear()
|
|
{
|
|
data.clear();
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
void shrink_to_fit()
|
|
{
|
|
data.shrink_to_fit();
|
|
}
|
|
|
|
template <size_t type_index_, typename... Args>
|
|
auto &emplace_back(Args &&...args)
|
|
{
|
|
return data.emplace_back(std::forward<Args>(args)...);
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &fetch(size_t index)
|
|
{
|
|
return data[index];
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &fetch(size_t index) const
|
|
{
|
|
return data[index];
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &raw()
|
|
{
|
|
return data;
|
|
}
|
|
|
|
template <size_t type_index_>
|
|
auto &raw() const
|
|
{
|
|
return data;
|
|
}
|
|
|
|
protected:
|
|
stl_vector_mp<type> data{};
|
|
};
|
|
|
|
template <size_t type_index>
|
|
struct compressed_vector_tuple_impl<type_index, void> {
|
|
};
|
|
|
|
template <typename... types>
|
|
struct compressed_vector_tuple_ : public compressed_vector_tuple_impl<0, types...> {
|
|
bool empty() const { return static_cast<const base_type *>(this)->template empty<0>(); }
|
|
|
|
size_t size() const { return static_cast<const base_type *>(this)->template size<0>(); }
|
|
|
|
void reserve_all(size_t new_cap) { broadcast_reserve<0>(new_cap); }
|
|
|
|
void resize_all(size_t new_sz) { broadcast_resize<0>(new_sz); }
|
|
|
|
void clear_all() { broadcast_clear<0>(); }
|
|
|
|
void shrink_to_fit_all() { broadcast_shrink<0>(); }
|
|
|
|
protected:
|
|
template <size_t type_index>
|
|
static constexpr bool can_operate = !std::is_void_v<std::tuple_element_t<type_index, std::tuple<types...>>>;
|
|
|
|
template <size_t index>
|
|
void broadcast_reserve(size_t new_cap)
|
|
{
|
|
if constexpr (can_operate<index>) static_cast<base_type *>(this)->template reserve<index>(new_cap);
|
|
if constexpr (index < sizeof...(types) - 1) this->template broadcast_reserve<index + 1>(new_cap);
|
|
}
|
|
|
|
template <size_t index>
|
|
void broadcast_resize(size_t new_sz)
|
|
{
|
|
if constexpr (can_operate<index>) static_cast<base_type *>(this)->template resize<index>(new_sz);
|
|
if constexpr (index < sizeof...(types) - 1) this->template broadcast_resize<index + 1>(new_sz);
|
|
}
|
|
|
|
template <size_t index>
|
|
void broadcast_clear()
|
|
{
|
|
if constexpr (can_operate<index>) static_cast<base_type *>(this)->template clear<index>();
|
|
if constexpr (index < sizeof...(types) - 1) this->template broadcast_clear<index + 1>();
|
|
}
|
|
|
|
template <size_t index>
|
|
void broadcast_shrink()
|
|
{
|
|
if constexpr (can_operate<index>) static_cast<base_type *>(this)->template shrink_to_fit<index>();
|
|
if constexpr (index < sizeof...(types) - 1) this->template broadcast_shrink<index + 1>();
|
|
}
|
|
|
|
using base_type = compressed_vector_tuple_impl<0, types...>;
|
|
};
|
|
} // namespace detail
|
|
|
|
template <typename... types>
|
|
using compressed_vector_tuple = detail::compressed_vector_tuple_<types...>;
|