#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>>, \ "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(__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>>, \ "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(__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>>, \ "try fetching properties from void type in type list."); \ base_type::template func_name(__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>>, \ "try fetching properties from void type in type list."); \ return base_type::template func_name(__VA_ARGS__) template struct compressed_vector_tuple_impl : public compressed_vector_tuple_impl { template bool empty() const { recursive_func_caller_return(empty, empty); } template size_t size() const { recursive_func_caller_return(size, size); } template void reserve(size_t new_cap) { recursive_func_caller(reserve, reserve, new_cap); } template void resize(size_t new_sz) { recursive_func_caller(resize, resize, new_sz); } template void clear() { recursive_func_caller(clear, clear); } template void shrink_to_fit() { recursive_func_caller(shrink_to_fit, shrink_to_fit); } template auto &emplace_back(Args &&...args) { recursive_func_caller_return(emplace_back, emplace_back, std::forward(args)...); } template auto &fetch(size_t index) { recursive_func_caller_return(fetch, operator[], index); } template auto &fetch(size_t index) const { recursive_func_caller_return(fetch, operator[], index); } template auto &raw() { static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); static_assert(!std::is_void_v>>, "try fetching properties from void type in type list."); if constexpr (type_index == type_index_) return data; else return base_type::template raw(); } template auto &raw() const { static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); static_assert(!std::is_void_v>>, "try fetching properties from void type in type list."); if constexpr (type_index == type_index_) return data; else return base_type::template raw(); } protected: using base_type = compressed_vector_tuple_impl; stl_vector_mp data{}; }; template struct compressed_vector_tuple_impl : public compressed_vector_tuple_impl { template bool empty() const { recursive_func_caller_return_void(empty); } template size_t size() const { recursive_func_caller_return_void(size); } template void reserve(size_t new_cap) { recursive_func_caller_void(reserve, new_cap); } template void resize(size_t new_sz) { recursive_func_caller_void(resize, new_sz); } template void clear() { recursive_func_caller_void(clear); } template void shrink_to_fit() { recursive_func_caller_void(shrink_to_fit); } template auto &emplace_back(Args &&...args) { recursive_func_caller_return_void(emplace_back, std::forward(args)...); } template auto &fetch(size_t index) { recursive_func_caller_return_void(fetch, index); } template auto &fetch(size_t index) const { recursive_func_caller_return_void(fetch, index); } template auto &raw() { static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); static_assert(!std::is_void_v>>, "try fetching properties from void type in type list."); return base_type::template raw(); } template auto &raw() const { static_assert(type_index_ < sizeof...(rest) + 1 + type_index, "type index is out of range."); static_assert(!std::is_void_v>>, "try fetching properties from void type in type list."); return base_type::template raw(); } protected: using base_type = compressed_vector_tuple_impl; }; #undef recursive_func_caller #undef recursive_func_caller_return #undef recursive_func_caller_void #undef recursive_func_caller_return_void template struct compressed_vector_tuple_impl { template bool empty() const { return data.empty(); } template size_t size() const { return data.size(); } template void reserve(size_t new_cap) { data.reserve(new_cap); } template void resize(size_t new_sz) { data.resize(new_sz); } template void clear() { data.clear(); } template void shrink_to_fit() { data.shrink_to_fit(); } template auto &emplace_back(Args &&...args) { return data.emplace_back(std::forward(args)...); } template auto &fetch(size_t index) { return data[index]; } template auto &fetch(size_t index) const { return data[index]; } template auto &raw() { return data; } template auto &raw() const { return data; } protected: stl_vector_mp data{}; }; template struct compressed_vector_tuple_impl { }; template struct compressed_vector_tuple_ : public compressed_vector_tuple_impl<0, types...> { bool empty() const { return static_cast(this)->template empty<0>(); } size_t size() const { return static_cast(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 static constexpr bool can_operate = !std::is_void_v>>; template void broadcast_reserve(size_t new_cap) { if constexpr (can_operate) static_cast(this)->template reserve(new_cap); if constexpr (index < sizeof...(types) - 1) this->template broadcast_reserve(new_cap); } template void broadcast_resize(size_t new_sz) { if constexpr (can_operate) static_cast(this)->template resize(new_sz); if constexpr (index < sizeof...(types) - 1) this->template broadcast_resize(new_sz); } template void broadcast_clear() { if constexpr (can_operate) static_cast(this)->template clear(); if constexpr (index < sizeof...(types) - 1) this->template broadcast_clear(); } template void broadcast_shrink() { if constexpr (can_operate) static_cast(this)->template shrink_to_fit(); if constexpr (index < sizeof...(types) - 1) this->template broadcast_shrink(); } using base_type = compressed_vector_tuple_impl<0, types...>; }; } // namespace detail template using compressed_vector_tuple = detail::compressed_vector_tuple_;