EnTT 3.15.0
Loading...
Searching...
No Matches
table.hpp
1#ifndef ENTT_CONTAINER_TABLE_HPP
2#define ENTT_CONTAINER_TABLE_HPP
3
4#include <cstddef>
5#include <iterator>
6#include <tuple>
7#include <type_traits>
8#include <utility>
9#include "../config/config.h"
10#include "../core/iterator.hpp"
11#include "fwd.hpp"
12
13namespace entt {
14
16namespace internal {
17
18template<typename... It>
19class table_iterator {
20 template<typename...>
21 friend class table_iterator;
22
23public:
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;
30
31 constexpr table_iterator() noexcept
32 : it{} {}
33
34 constexpr table_iterator(It... from) noexcept
35 : it{from...} {}
36
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)...} {}
40
41 constexpr table_iterator &operator++() noexcept {
42 return (++std::get<It>(it), ...), *this;
43 }
44
45 constexpr table_iterator operator++(int) noexcept {
46 const table_iterator orig = *this;
47 return ++(*this), orig;
48 }
49
50 constexpr table_iterator &operator--() noexcept {
51 return (--std::get<It>(it), ...), *this;
52 }
53
54 constexpr table_iterator operator--(int) noexcept {
55 const table_iterator orig = *this;
56 return operator--(), orig;
57 }
58
59 constexpr table_iterator &operator+=(const difference_type value) noexcept {
60 return ((std::get<It>(it) += value), ...), *this;
61 }
62
63 constexpr table_iterator operator+(const difference_type value) const noexcept {
64 table_iterator copy = *this;
65 return (copy += value);
66 }
67
68 constexpr table_iterator &operator-=(const difference_type value) noexcept {
69 return (*this += -value);
70 }
71
72 constexpr table_iterator operator-(const difference_type value) const noexcept {
73 return (*this + -value);
74 }
75
76 [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
77 return std::forward_as_tuple(std::get<It>(it)[value]...);
78 }
79
80 [[nodiscard]] constexpr pointer operator->() const noexcept {
81 return {operator[](0)};
82 }
83
84 [[nodiscard]] constexpr reference operator*() const noexcept {
85 return operator[](0);
86 }
87
88 template<typename... Lhs, typename... Rhs>
89 friend constexpr std::ptrdiff_t operator-(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept;
90
91 template<typename... Lhs, typename... Rhs>
92 friend constexpr bool operator==(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept;
93
94 template<typename... Lhs, typename... Rhs>
95 friend constexpr bool operator<(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept;
96
97private:
98 std::tuple<It...> it;
99};
100
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);
104}
105
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);
109}
110
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);
114}
115
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);
119}
120
121template<typename... Lhs, typename... Rhs>
122[[nodiscard]] constexpr bool operator>(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
123 return rhs < lhs;
124}
125
126template<typename... Lhs, typename... Rhs>
127[[nodiscard]] constexpr bool operator<=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
128 return !(lhs > rhs);
129}
130
131template<typename... Lhs, typename... Rhs>
132[[nodiscard]] constexpr bool operator>=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept {
133 return !(lhs < rhs);
134}
135
136} // namespace internal
138
148template<typename... Container>
150 using container_type = std::tuple<Container...>;
151
152public:
154 using size_type = std::size_t;
156 using difference_type = std::ptrdiff_t;
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...>;
164 using const_reverse_iterator = internal::table_iterator<typename Container::const_reverse_iterator...>;
165
168 : payload{} {
169 }
170
175 explicit basic_table(const Container &...container) noexcept
176 : payload{container...} {
177 ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
178 }
179
184 explicit basic_table(Container &&...container) noexcept
185 : payload{std::move(container)...} {
186 ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
187 }
188
190 basic_table(const basic_table &) = delete;
191
196 basic_table(basic_table &&other) noexcept
197 : payload{std::move(other.payload)} {}
198
204 template<typename Allocator>
205 explicit basic_table(const Allocator &allocator)
206 : payload{Container{allocator}...} {}
207
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");
218 }
219
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");
230 }
231
238 template<class Allocator>
239 basic_table(basic_table &&other, const Allocator &allocator)
240 : payload{Container{std::move(std::get<Container>(other.payload)), allocator}...} {}
241
243 ~basic_table() = default;
244
250
256 basic_table &operator=(basic_table &&other) noexcept {
257 swap(other);
258 return *this;
259 }
260
265 void swap(basic_table &other) noexcept {
266 using std::swap;
267 swap(payload, other.payload);
268 }
269
278 void reserve(const size_type cap) {
279 (std::get<Container>(payload).reserve(cap), ...);
280 }
281
287 [[nodiscard]] size_type capacity() const noexcept {
288 return std::get<0>(payload).capacity();
289 }
290
293 (std::get<Container>(payload).shrink_to_fit(), ...);
294 }
295
300 [[nodiscard]] size_type size() const noexcept {
301 return std::get<0>(payload).size();
302 }
303
308 [[nodiscard]] bool empty() const noexcept {
309 return std::get<0>(payload).empty();
310 }
311
319 [[nodiscard]] const_iterator cbegin() const noexcept {
320 return {std::get<Container>(payload).cbegin()...};
321 }
322
324 [[nodiscard]] const_iterator begin() const noexcept {
325 return cbegin();
326 }
327
329 [[nodiscard]] iterator begin() noexcept {
330 return {std::get<Container>(payload).begin()...};
331 }
332
337 [[nodiscard]] const_iterator cend() const noexcept {
338 return {std::get<Container>(payload).cend()...};
339 }
340
342 [[nodiscard]] const_iterator end() const noexcept {
343 return cend();
344 }
345
347 [[nodiscard]] iterator end() noexcept {
348 return {std::get<Container>(payload).end()...};
349 }
350
358 [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
359 return {std::get<Container>(payload).crbegin()...};
360 }
361
363 [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
364 return crbegin();
365 }
366
368 [[nodiscard]] reverse_iterator rbegin() noexcept {
369 return {std::get<Container>(payload).rbegin()...};
370 }
371
377 [[nodiscard]] const_reverse_iterator crend() const noexcept {
378 return {std::get<Container>(payload).crend()...};
379 }
380
382 [[nodiscard]] const_reverse_iterator rend() const noexcept {
383 return crend();
384 }
385
387 [[nodiscard]] reverse_iterator rend() noexcept {
388 return {std::get<Container>(payload).rend()...};
389 }
390
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()...);
401 } else {
402 return std::forward_as_tuple(std::get<Container>(payload).emplace_back(std::forward<Args>(args))...);
403 }
404 }
405
412 const auto diff = pos - begin();
413 return {std::get<Container>(payload).erase(std::get<Container>(payload).begin() + diff)...};
414 }
415
420 void erase(const size_type pos) {
421 ENTT_ASSERT(pos < size(), "Index out of bounds");
422 erase(begin() + static_cast<difference_type>(pos));
423 }
424
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]...);
433 }
434
436 [[nodiscard]] std::tuple<typename Container::value_type &...> operator[](const size_type pos) {
437 ENTT_ASSERT(pos < size(), "Index out of bounds");
438 return std::forward_as_tuple(std::get<Container>(payload)[pos]...);
439 }
440
442 void clear() {
443 (std::get<Container>(payload).clear(), ...);
444 }
445
446private:
447 container_type payload;
448};
449
450} // namespace entt
451
453namespace std {
454
455template<typename... Container, typename Allocator>
456struct uses_allocator<entt::basic_table<Container...>, Allocator>
457 : std::bool_constant<(std::uses_allocator_v<Container, Allocator> && ...)> {};
458
459} // namespace std
461
462#endif
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
Definition table.hpp:382
size_type capacity() const noexcept
Returns the number of rows that a table has currently allocated space for.
Definition table.hpp:287
basic_table(basic_table &&other, const Allocator &allocator)
Allocator-extended move constructor.
Definition table.hpp:239
size_type size() const noexcept
Returns the number of rows in a table.
Definition table.hpp:300
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.
Definition table.hpp:430
const_iterator end() const noexcept
Returns an iterator to the end.
Definition table.hpp:342
iterator end() noexcept
Returns an iterator to the end.
Definition table.hpp:347
reverse_iterator rend() noexcept
Returns a reverse iterator to the end.
Definition table.hpp:387
void swap(basic_table &other) noexcept
Exchanges the contents with those of a given table.
Definition table.hpp:265
const_iterator begin() const noexcept
Returns an iterator to the beginning.
Definition table.hpp:324
internal::table_iterator< typename Container::iterator... > iterator
Definition table.hpp:158
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the beginning.
Definition table.hpp:368
~basic_table()=default
Default destructor.
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
Definition table.hpp:377
bool empty() const noexcept
Checks whether a table is empty.
Definition table.hpp:308
basic_table()
Default constructor.
Definition table.hpp:167
iterator erase(const_iterator pos)
Removes a row from a table.
Definition table.hpp:411
void shrink_to_fit()
Requests the removal of unused capacity.
Definition table.hpp:292
basic_table(const Container &...container, const Allocator &allocator) noexcept
Copy constructs the underlying containers using a given allocator.
Definition table.hpp:215
const_reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
Definition table.hpp:363
basic_table & operator=(basic_table &&other) noexcept
Move assignment operator.
Definition table.hpp:256
void clear()
Clears a table.
Definition table.hpp:442
basic_table(Container &&...container, const Allocator &allocator) noexcept
Move constructs the underlying containers using a given allocator.
Definition table.hpp:227
void erase(const size_type pos)
Removes a row from a table.
Definition table.hpp:420
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.
Definition table.hpp:358
internal::table_iterator< typename Container::reverse_iterator... > reverse_iterator
Definition table.hpp:162
void reserve(const size_type cap)
Increases the capacity of a table.
Definition table.hpp:278
iterator begin() noexcept
Returns an iterator to the beginning.
Definition table.hpp:329
basic_table(basic_table &&other) noexcept
Move constructor.
Definition table.hpp:196
basic_table(const Container &...container) noexcept
Copy constructs the underlying containers.
Definition table.hpp:175
basic_table(const Allocator &allocator)
Constructs the underlying containers using a given allocator.
Definition table.hpp:205
basic_table(Container &&...container) noexcept
Move constructs the underlying containers.
Definition table.hpp:184
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition table.hpp:319
std::tuple< typename Container::value_type &... > operator[](const size_type pos)
Returns the row data at specified location.
Definition table.hpp:436
internal::table_iterator< typename Container::const_iterator... > const_iterator
Definition table.hpp:160
const_iterator cend() const noexcept
Returns an iterator to the end.
Definition table.hpp:337
std::tuple< typename Container::value_type &... > emplace(Args &&...args)
Appends a row to the end of a table.
Definition table.hpp:398
internal::table_iterator< typename Container::const_reverse_iterator... > const_reverse_iterator
Definition table.hpp:164
EnTT default namespace.
Definition dense_map.hpp:22
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:167
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.