1#ifndef ENTT_CONTAINER_TABLE_HPP
2#define ENTT_CONTAINER_TABLE_HPP
9#include "../config/config.h"
10#include "../core/iterator.hpp"
18template<
typename... It>
21 friend class table_iterator;
24 using value_type =
decltype(std::forward_as_tuple(*std::declval<It>()...));
25 using pointer = input_iterator_pointer<value_type>;
26 using reference = value_type;
27 using difference_type = std::ptrdiff_t;
28 using iterator_category = std::input_iterator_tag;
29 using iterator_concept = std::random_access_iterator_tag;
31 constexpr table_iterator() noexcept
34 constexpr table_iterator(It... from) noexcept
37 template<
typename... Other,
typename = std::enable_if_t<(std::is_constructible_v<It, Other> && ...)>>
38 constexpr table_iterator(
const table_iterator<Other...> &other) noexcept
39 : table_iterator{std::get<Other>(other.it)...} {}
41 constexpr table_iterator &operator++() noexcept {
42 return (++std::get<It>(it), ...), *
this;
45 constexpr table_iterator operator++(
int)
noexcept {
46 const table_iterator orig = *
this;
47 return ++(*this), orig;
50 constexpr table_iterator &operator--() noexcept {
51 return (--std::get<It>(it), ...), *
this;
54 constexpr table_iterator operator--(
int)
noexcept {
55 const table_iterator orig = *
this;
56 return operator--(), orig;
59 constexpr table_iterator &operator+=(
const difference_type value)
noexcept {
60 return ((std::get<It>(it) += value), ...), *
this;
63 constexpr table_iterator
operator+(
const difference_type value)
const noexcept {
64 table_iterator copy = *
this;
65 return (copy += value);
68 constexpr table_iterator &operator-=(
const difference_type value)
noexcept {
69 return (*
this += -value);
72 constexpr table_iterator operator-(
const difference_type value)
const noexcept {
73 return (*
this + -value);
76 [[nodiscard]]
constexpr reference operator[](
const difference_type value)
const noexcept {
77 return std::forward_as_tuple(std::get<It>(it)[value]...);
80 [[nodiscard]]
constexpr pointer operator->() const noexcept {
81 return {operator[](0)};
84 [[nodiscard]]
constexpr reference operator*() const noexcept {
88 template<
typename... Lhs,
typename... Rhs>
89 friend constexpr std::ptrdiff_t operator-(
const table_iterator<Lhs...> &,
const table_iterator<Rhs...> &)
noexcept;
91 template<
typename... Lhs,
typename... Rhs>
92 friend constexpr bool operator==(
const table_iterator<Lhs...> &,
const table_iterator<Rhs...> &)
noexcept;
94 template<
typename... Lhs,
typename... Rhs>
95 friend constexpr bool operator<(
const table_iterator<Lhs...> &,
const table_iterator<Rhs...> &)
noexcept;
101template<
typename... Lhs,
typename... Rhs>
102[[nodiscard]]
constexpr std::ptrdiff_t operator-(
const table_iterator<Lhs...> &lhs,
const table_iterator<Rhs...> &rhs)
noexcept {
103 return std::get<0>(lhs.it) - std::get<0>(rhs.it);
106template<
typename... Lhs,
typename... Rhs>
107[[nodiscard]]
constexpr bool operator==(
const table_iterator<Lhs...> &lhs,
const table_iterator<Rhs...> &rhs)
noexcept {
108 return std::get<0>(lhs.it) == std::get<0>(rhs.it);
111template<
typename... Lhs,
typename... Rhs>
112[[nodiscard]]
constexpr bool operator!=(
const table_iterator<Lhs...> &lhs,
const table_iterator<Rhs...> &rhs)
noexcept {
113 return !(lhs == rhs);
116template<
typename... Lhs,
typename... Rhs>
117[[nodiscard]]
constexpr bool operator<(
const table_iterator<Lhs...> &lhs,
const table_iterator<Rhs...> &rhs)
noexcept {
118 return std::get<0>(lhs.it) < std::get<0>(rhs.it);
121template<
typename... Lhs,
typename... Rhs>
122[[nodiscard]]
constexpr bool operator>(
const table_iterator<Lhs...> &lhs,
const table_iterator<Rhs...> &rhs)
noexcept {
126template<
typename... Lhs,
typename... Rhs>
127[[nodiscard]]
constexpr bool operator<=(
const table_iterator<Lhs...> &lhs,
const table_iterator<Rhs...> &rhs)
noexcept {
131template<
typename... Lhs,
typename... Rhs>
132[[nodiscard]]
constexpr bool operator>=(
const table_iterator<Lhs...> &lhs,
const table_iterator<Rhs...> &rhs)
noexcept {
148template<
typename... Container>
150 using container_type = std::tuple<Container...>;
158 using iterator = internal::table_iterator<
typename Container::iterator...>;
160 using const_iterator = internal::table_iterator<
typename Container::const_iterator...>;
162 using reverse_iterator = internal::table_iterator<
typename Container::reverse_iterator...>;
176 : payload{container...} {
177 ENTT_ASSERT((((std::get<Container>(payload).
size() *
sizeof...(Container)) == (std::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
185 : payload{std::move(container)...} {
186 ENTT_ASSERT((((std::get<Container>(payload).
size() *
sizeof...(Container)) == (std::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
197 : payload{std::move(other.payload)} {}
204 template<
typename Allocator>
206 : payload{Container{allocator}...} {}
214 template<
class Allocator>
215 basic_table(
const Container &...container,
const Allocator &allocator) noexcept
216 : payload{Container{container, allocator}...} {
217 ENTT_ASSERT((((std::get<Container>(payload).
size() *
sizeof...(Container)) == (std::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
226 template<
class Allocator>
227 basic_table(Container &&...container,
const Allocator &allocator) noexcept
228 : payload{Container{std::move(container), allocator}...} {
229 ENTT_ASSERT((((std::get<Container>(payload).
size() *
sizeof...(Container)) == (std::get<Container>(payload).
size() + ...)) && ...),
"Unexpected container size");
238 template<
class Allocator>
240 : payload{Container{std::move(std::
get<Container>(other.payload)), allocator}...} {}
267 swap(payload, other.payload);
279 (std::get<Container>(payload).reserve(cap), ...);
288 return std::get<0>(payload).capacity();
293 (std::get<Container>(payload).shrink_to_fit(), ...);
301 return std::get<0>(payload).size();
308 [[nodiscard]]
bool empty() const noexcept {
309 return std::get<0>(payload).empty();
320 return {std::get<Container>(payload).cbegin()...};
330 return {std::get<Container>(payload).begin()...};
338 return {std::get<Container>(payload).cend()...};
348 return {std::get<Container>(payload).end()...};
359 return {std::get<Container>(payload).crbegin()...};
369 return {std::get<Container>(payload).rbegin()...};
378 return {std::get<Container>(payload).crend()...};
388 return {std::get<Container>(payload).rend()...};
397 template<
typename... Args>
398 std::tuple<
typename Container::value_type &...>
emplace(Args &&...args) {
399 if constexpr(
sizeof...(Args) == 0u) {
400 return std::forward_as_tuple(std::get<Container>(payload).emplace_back()...);
402 return std::forward_as_tuple(std::get<Container>(payload).emplace_back(std::forward<Args>(args))...);
412 const auto diff = pos -
begin();
413 return {std::get<Container>(payload).erase(std::get<Container>(payload).
begin() + diff)...};
421 ENTT_ASSERT(pos <
size(),
"Index out of bounds");
430 [[nodiscard]] std::tuple<
const typename Container::value_type &...>
operator[](
const size_type pos)
const {
431 ENTT_ASSERT(pos <
size(),
"Index out of bounds");
432 return std::forward_as_tuple(std::get<Container>(payload)[pos]...);
437 ENTT_ASSERT(pos <
size(),
"Index out of bounds");
438 return std::forward_as_tuple(std::get<Container>(payload)[pos]...);
443 (std::get<Container>(payload).clear(), ...);
447 container_type payload;
455template<
typename... Container,
typename Allocator>
456struct uses_allocator<entt::basic_table<Container...>, Allocator>
457 : std::bool_constant<(std::uses_allocator_v<Container, Allocator> && ...)> {};
std::ptrdiff_t difference_type
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
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.
std::tuple< const typename Container::value_type &... > operator[](const size_type pos) const
Returns the row data at specified location.
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.
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.
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.
basic_table(basic_table &&other) noexcept
Move constructor.
basic_table(const Container &...container) noexcept
Copy constructs the underlying containers.
basic_table(const Allocator &allocator)
Constructs the underlying containers using a given allocator.
basic_table(Container &&...container) noexcept
Move constructs the underlying containers.
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
std::tuple< typename Container::value_type &... > operator[](const size_type pos)
Returns the row data at specified location.
internal::table_iterator< typename Container::const_iterator... > const_iterator
const_iterator cend() const noexcept
Returns an iterator to the end.
std::tuple< typename Container::value_type &... > emplace(Args &&...args)
Appends a row to the end of a table.
internal::table_iterator< typename Container::const_reverse_iterator... > const_reverse_iterator
constexpr get_t< Type... > get
Variable template for lists of observed elements.
constexpr bool operator<=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator<(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator>=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator>(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.