1#ifndef ENTT_CONTAINER_TABLE_HPP
2#define ENTT_CONTAINER_TABLE_HPP
4#include "../config/config.h"
5#include "../core/iterator.hpp"
6#include "../stl/concepts.hpp"
7#include "../stl/cstddef.hpp"
8#include "../stl/iterator.hpp"
9#include "../stl/tuple.hpp"
10#include "../stl/utility.hpp"
18template<
typename... It>
21 friend class table_iterator;
24 using value_type =
decltype(stl::forward_as_tuple(*stl::declval<It>()...));
25 using pointer = input_iterator_pointer<value_type>;
26 using reference = value_type;
27 using difference_type = stl::ptrdiff_t;
28 using iterator_category = stl::input_iterator_tag;
29 using iterator_concept = stl::random_access_iterator_tag;
31 constexpr table_iterator() noexcept
34 constexpr table_iterator(It... from) noexcept
37 template<
typename... Other>
38 requires (stl::constructible_from<It, Other> && ...)
39 constexpr table_iterator(
const table_iterator<Other...> &other) noexcept
40 : table_iterator{stl::get<Other>(other.it)...} {}
42 constexpr table_iterator &operator++() noexcept {
43 return (++stl::get<It>(it), ...), *
this;
46 constexpr table_iterator operator++(
int)
noexcept {
47 const table_iterator orig = *
this;
48 return ++(*this), orig;
51 constexpr table_iterator &operator--() noexcept {
52 return (--stl::get<It>(it), ...), *
this;
55 constexpr table_iterator operator--(
int)
noexcept {
56 const table_iterator orig = *
this;
57 return operator--(), orig;
60 constexpr table_iterator &operator+=(
const difference_type value)
noexcept {
61 return ((stl::get<It>(it) += value), ...), *
this;
64 constexpr table_iterator
operator+(
const difference_type value)
const noexcept {
65 table_iterator copy = *
this;
66 return (copy += value);
69 constexpr table_iterator &operator-=(
const difference_type value)
noexcept {
70 return (*
this += -value);
73 constexpr table_iterator operator-(
const difference_type value)
const noexcept {
74 return (*
this + -value);
77 [[nodiscard]]
constexpr reference operator[](
const difference_type value)
const noexcept {
78 return stl::forward_as_tuple(stl::get<It>(it)[value]...);
81 [[nodiscard]]
constexpr pointer operator->() const noexcept {
82 return {operator[](0)};
85 [[nodiscard]]
constexpr reference operator*() const noexcept {
89 template<
typename... Other>
90 [[nodiscard]]
constexpr stl::ptrdiff_t operator-(
const table_iterator<Other...> &other)
const noexcept {
91 return stl::get<0>(it) - stl::get<0>(other.it);
94 template<
typename... Other>
95 [[nodiscard]]
constexpr bool operator==(
const table_iterator<Other...> &other)
const noexcept {
96 return stl::get<0>(it) == stl::get<0>(other.it);
99 template<
typename... Other>
100 [[nodiscard]]
constexpr auto operator<=>(
const table_iterator<Other...> &other)
const noexcept {
101 return stl::get<0>(it) <=> stl::get<0>(other.it);
105 stl::tuple<It...> it;
120template<
typename... Container>
122 using container_type = stl::tuple<Container...>;
130 using iterator = internal::table_iterator<
typename Container::iterator...>;
132 using const_iterator = internal::table_iterator<
typename Container::const_iterator...>;
134 using reverse_iterator = internal::table_iterator<
typename Container::reverse_iterator...>;
148 : payload{container...} {
149 ENTT_ASSERT((((stl::get<Container>(payload).
size() *
sizeof...(Container)) == (stl::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
157 : payload{stl::move(container)...} {
158 ENTT_ASSERT((((stl::get<Container>(payload).
size() *
sizeof...(Container)) == (stl::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
169 : payload{stl::move(other.payload)} {}
176 : payload{Container{allocator}...} {}
184 template<
class Allocator>
185 basic_table(
const Container &...container,
const Allocator &allocator) noexcept
186 : payload{Container{container, allocator}...} {
187 ENTT_ASSERT((((stl::get<Container>(payload).
size() *
sizeof...(Container)) == (stl::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
196 template<
class Allocator>
197 basic_table(Container &&...container,
const Allocator &allocator) noexcept
198 : payload{Container{stl::move(container), allocator}...} {
199 ENTT_ASSERT((((stl::get<Container>(payload).
size() *
sizeof...(Container)) == (stl::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
208 template<
class Allocator>
210 : payload{Container{
stl::move(
stl::
get<Container>(other.payload)), allocator}...} {}
237 swap(payload, other.payload);
249 (stl::get<Container>(payload).reserve(cap), ...);
258 return stl::get<0>(payload).capacity();
263 (stl::get<Container>(payload).shrink_to_fit(), ...);
271 return stl::get<0>(payload).size();
278 [[nodiscard]]
bool empty() const noexcept {
279 return stl::get<0>(payload).empty();
290 return {stl::get<Container>(payload).cbegin()...};
300 return {stl::get<Container>(payload).begin()...};
308 return {stl::get<Container>(payload).cend()...};
318 return {stl::get<Container>(payload).end()...};
329 return {stl::get<Container>(payload).crbegin()...};
339 return {stl::get<Container>(payload).rbegin()...};
348 return {stl::get<Container>(payload).crend()...};
358 return {stl::get<Container>(payload).rend()...};
367 template<
typename... Args>
368 stl::tuple<
typename Container::value_type &...>
emplace(Args &&...args) {
369 if constexpr(
sizeof...(Args) == 0u) {
370 return stl::forward_as_tuple(stl::get<Container>(payload).emplace_back()...);
372 return stl::forward_as_tuple(stl::get<Container>(payload).emplace_back(stl::forward<Args>(args))...);
382 const auto diff = pos -
begin();
383 return {stl::get<Container>(payload).erase(stl::get<Container>(payload).
begin() + diff)...};
391 ENTT_ASSERT(pos <
size(),
"Index out of bounds");
400 [[nodiscard]] stl::tuple<
const typename Container::value_type &...>
operator[](
const size_type pos)
const {
401 ENTT_ASSERT(pos <
size(),
"Index out of bounds");
402 return stl::forward_as_tuple(stl::get<Container>(payload)[pos]...);
407 ENTT_ASSERT(pos <
size(),
"Index out of bounds");
408 return stl::forward_as_tuple(stl::get<Container>(payload)[pos]...);
413 (stl::get<Container>(payload).clear(), ...);
417 container_type payload;
427template<
typename... Container,
typename Allocator>
428struct uses_allocator<entt::basic_table<Container...>, Allocator>
429 : entt::stl::bool_constant<(entt::stl::uses_allocator_v<Container, Allocator> && ...)> {};
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
stl::tuple< typename Container::value_type &... > operator[](const size_type pos)
Returns the row data at specified location.
size_type capacity() const noexcept
Returns the number of rows that a table has currently allocated space for.
basic_table(basic_table &&other, const Allocator &allocator)
Allocator-extended move constructor.
size_type size() const noexcept
Returns the number of rows in a table.
basic_table & operator=(const basic_table &)=delete
Default copy assignment operator, deleted on purpose.
const_iterator end() const noexcept
Returns an iterator to the end.
iterator end() noexcept
Returns an iterator to the end.
reverse_iterator rend() noexcept
Returns a reverse iterator to the end.
void swap(basic_table &other) noexcept
Exchanges the contents with those of a given table.
const_iterator begin() const noexcept
Returns an iterator to the beginning.
stl::tuple< const typename Container::value_type &... > operator[](const size_type pos) const
Returns the row data at specified location.
internal::table_iterator< typename Container::iterator... > iterator
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the beginning.
~basic_table()=default
Default destructor.
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
bool empty() const noexcept
Checks whether a table is empty.
basic_table()
Default constructor.
iterator erase(const_iterator pos)
Removes a row from a table.
basic_table(const auto &allocator)
Constructs the underlying containers using a given allocator.
void shrink_to_fit()
Requests the removal of unused capacity.
basic_table(const Container &...container, const Allocator &allocator) noexcept
Copy constructs the underlying containers using a given allocator.
const_reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
basic_table & operator=(basic_table &&other) noexcept
Move assignment operator.
void clear()
Clears a table.
basic_table(Container &&...container, const Allocator &allocator) noexcept
Move constructs the underlying containers using a given allocator.
void erase(const size_type pos)
Removes a row from a table.
basic_table(const basic_table &)=delete
Default copy constructor, deleted on purpose.
const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator to the beginning.
internal::table_iterator< typename Container::reverse_iterator... > reverse_iterator
void reserve(const size_type cap)
Increases the capacity of a table.
iterator begin() noexcept
Returns an iterator to the beginning.
stl::tuple< typename Container::value_type &... > emplace(Args &&...args)
Appends a row to the end of a table.
basic_table(basic_table &&other) noexcept
Move constructor.
basic_table(const Container &...container) noexcept
Copy constructs the underlying containers.
basic_table(Container &&...container) noexcept
Move constructs the underlying containers.
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
internal::table_iterator< typename Container::const_iterator... > const_iterator
const_iterator cend() const noexcept
Returns an iterator to the end.
stl::ptrdiff_t difference_type
internal::table_iterator< typename Container::const_reverse_iterator... > const_reverse_iterator
Custom EnTT namespace for the standard template library.
constexpr get_t< Type... > get
Variable template for lists of observed elements.
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.