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

3 days ago
#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...>;