EnTT 4.0.0
Loading...
Searching...
No Matches
table.hpp
1#ifndef ENTT_CONTAINER_TABLE_HPP
2#define ENTT_CONTAINER_TABLE_HPP
3
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"
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(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;
30
31 constexpr table_iterator() noexcept
32 : it{} {}
33
34 constexpr table_iterator(It... from) noexcept
35 : it{from...} {}
36
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)...} {}
41
42 constexpr table_iterator &operator++() noexcept {
43 return (++stl::get<It>(it), ...), *this;
44 }
45
46 constexpr table_iterator operator++(int) noexcept {
47 const table_iterator orig = *this;
48 return ++(*this), orig;
49 }
50
51 constexpr table_iterator &operator--() noexcept {
52 return (--stl::get<It>(it), ...), *this;
53 }
54
55 constexpr table_iterator operator--(int) noexcept {
56 const table_iterator orig = *this;
57 return operator--(), orig;
58 }
59
60 constexpr table_iterator &operator+=(const difference_type value) noexcept {
61 return ((stl::get<It>(it) += value), ...), *this;
62 }
63
64 constexpr table_iterator operator+(const difference_type value) const noexcept {
65 table_iterator copy = *this;
66 return (copy += value);
67 }
68
69 constexpr table_iterator &operator-=(const difference_type value) noexcept {
70 return (*this += -value);
71 }
72
73 constexpr table_iterator operator-(const difference_type value) const noexcept {
74 return (*this + -value);
75 }
76
77 [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
78 return stl::forward_as_tuple(stl::get<It>(it)[value]...);
79 }
80
81 [[nodiscard]] constexpr pointer operator->() const noexcept {
82 return {operator[](0)};
83 }
84
85 [[nodiscard]] constexpr reference operator*() const noexcept {
86 return operator[](0);
87 }
88
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);
92 }
93
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);
97 }
98
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);
102 }
103
104private:
105 stl::tuple<It...> it;
106};
107
108} // namespace internal
110
120template<typename... Container>
122 using container_type = stl::tuple<Container...>;
123
124public:
126 using size_type = stl::size_t;
128 using difference_type = stl::ptrdiff_t;
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...>;
136 using const_reverse_iterator = internal::table_iterator<typename Container::const_reverse_iterator...>;
137
140 : payload{} {
141 }
142
147 explicit basic_table(const Container &...container) noexcept
148 : payload{container...} {
149 ENTT_ASSERT((((stl::get<Container>(payload).size() * sizeof...(Container)) == (stl::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
150 }
151
156 explicit basic_table(Container &&...container) noexcept
157 : payload{stl::move(container)...} {
158 ENTT_ASSERT((((stl::get<Container>(payload).size() * sizeof...(Container)) == (stl::get<Container>(payload).size() + ...)) && ...), "Unexpected container size");
159 }
160
162 basic_table(const basic_table &) = delete;
163
168 basic_table(basic_table &&other) noexcept
169 : payload{stl::move(other.payload)} {}
170
175 explicit basic_table(const auto &allocator)
176 : payload{Container{allocator}...} {}
177
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");
188 }
189
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");
200 }
201
208 template<class Allocator>
209 basic_table(basic_table &&other, const Allocator &allocator)
210 : payload{Container{stl::move(stl::get<Container>(other.payload)), allocator}...} {}
211
213 ~basic_table() = default;
214
220
226 basic_table &operator=(basic_table &&other) noexcept {
227 swap(other);
228 return *this;
229 }
230
235 void swap(basic_table &other) noexcept {
236 using stl::swap;
237 swap(payload, other.payload);
238 }
239
248 void reserve(const size_type cap) {
249 (stl::get<Container>(payload).reserve(cap), ...);
250 }
251
257 [[nodiscard]] size_type capacity() const noexcept {
258 return stl::get<0>(payload).capacity();
259 }
260
263 (stl::get<Container>(payload).shrink_to_fit(), ...);
264 }
265
270 [[nodiscard]] size_type size() const noexcept {
271 return stl::get<0>(payload).size();
272 }
273
278 [[nodiscard]] bool empty() const noexcept {
279 return stl::get<0>(payload).empty();
280 }
281
289 [[nodiscard]] const_iterator cbegin() const noexcept {
290 return {stl::get<Container>(payload).cbegin()...};
291 }
292
294 [[nodiscard]] const_iterator begin() const noexcept {
295 return cbegin();
296 }
297
299 [[nodiscard]] iterator begin() noexcept {
300 return {stl::get<Container>(payload).begin()...};
301 }
302
307 [[nodiscard]] const_iterator cend() const noexcept {
308 return {stl::get<Container>(payload).cend()...};
309 }
310
312 [[nodiscard]] const_iterator end() const noexcept {
313 return cend();
314 }
315
317 [[nodiscard]] iterator end() noexcept {
318 return {stl::get<Container>(payload).end()...};
319 }
320
328 [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
329 return {stl::get<Container>(payload).crbegin()...};
330 }
331
333 [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
334 return crbegin();
335 }
336
338 [[nodiscard]] reverse_iterator rbegin() noexcept {
339 return {stl::get<Container>(payload).rbegin()...};
340 }
341
347 [[nodiscard]] const_reverse_iterator crend() const noexcept {
348 return {stl::get<Container>(payload).crend()...};
349 }
350
352 [[nodiscard]] const_reverse_iterator rend() const noexcept {
353 return crend();
354 }
355
357 [[nodiscard]] reverse_iterator rend() noexcept {
358 return {stl::get<Container>(payload).rend()...};
359 }
360
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()...);
371 } else {
372 return stl::forward_as_tuple(stl::get<Container>(payload).emplace_back(stl::forward<Args>(args))...);
373 }
374 }
375
382 const auto diff = pos - begin();
383 return {stl::get<Container>(payload).erase(stl::get<Container>(payload).begin() + diff)...};
384 }
385
390 void erase(const size_type pos) {
391 ENTT_ASSERT(pos < size(), "Index out of bounds");
392 erase(begin() + static_cast<difference_type>(pos));
393 }
394
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]...);
403 }
404
406 [[nodiscard]] stl::tuple<typename Container::value_type &...> operator[](const size_type pos) {
407 ENTT_ASSERT(pos < size(), "Index out of bounds");
408 return stl::forward_as_tuple(stl::get<Container>(payload)[pos]...);
409 }
410
412 void clear() {
413 (stl::get<Container>(payload).clear(), ...);
414 }
415
416private:
417 container_type payload;
418};
419
420} // namespace entt
421
423#include <utility>
424
425namespace std {
426
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> && ...)> {};
430
431} // namespace std
433
434#endif
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
Definition table.hpp:352
stl::tuple< typename Container::value_type &... > operator[](const size_type pos)
Returns the row data at specified location.
Definition table.hpp:406
size_type capacity() const noexcept
Returns the number of rows that a table has currently allocated space for.
Definition table.hpp:257
basic_table(basic_table &&other, const Allocator &allocator)
Allocator-extended move constructor.
Definition table.hpp:209
size_type size() const noexcept
Returns the number of rows in a table.
Definition table.hpp:270
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.
Definition table.hpp:312
iterator end() noexcept
Returns an iterator to the end.
Definition table.hpp:317
reverse_iterator rend() noexcept
Returns a reverse iterator to the end.
Definition table.hpp:357
void swap(basic_table &other) noexcept
Exchanges the contents with those of a given table.
Definition table.hpp:235
const_iterator begin() const noexcept
Returns an iterator to the beginning.
Definition table.hpp:294
stl::tuple< const typename Container::value_type &... > operator[](const size_type pos) const
Returns the row data at specified location.
Definition table.hpp:400
internal::table_iterator< typename Container::iterator... > iterator
Definition table.hpp:130
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the beginning.
Definition table.hpp:338
~basic_table()=default
Default destructor.
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
Definition table.hpp:347
bool empty() const noexcept
Checks whether a table is empty.
Definition table.hpp:278
basic_table()
Default constructor.
Definition table.hpp:139
iterator erase(const_iterator pos)
Removes a row from a table.
Definition table.hpp:381
basic_table(const auto &allocator)
Constructs the underlying containers using a given allocator.
Definition table.hpp:175
void shrink_to_fit()
Requests the removal of unused capacity.
Definition table.hpp:262
basic_table(const Container &...container, const Allocator &allocator) noexcept
Copy constructs the underlying containers using a given allocator.
Definition table.hpp:185
const_reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
Definition table.hpp:333
basic_table & operator=(basic_table &&other) noexcept
Move assignment operator.
Definition table.hpp:226
void clear()
Clears a table.
Definition table.hpp:412
basic_table(Container &&...container, const Allocator &allocator) noexcept
Move constructs the underlying containers using a given allocator.
Definition table.hpp:197
void erase(const size_type pos)
Removes a row from a table.
Definition table.hpp:390
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:328
internal::table_iterator< typename Container::reverse_iterator... > reverse_iterator
Definition table.hpp:134
void reserve(const size_type cap)
Increases the capacity of a table.
Definition table.hpp:248
iterator begin() noexcept
Returns an iterator to the beginning.
Definition table.hpp:299
stl::tuple< typename Container::value_type &... > emplace(Args &&...args)
Appends a row to the end of a table.
Definition table.hpp:368
basic_table(basic_table &&other) noexcept
Move constructor.
Definition table.hpp:168
basic_table(const Container &...container) noexcept
Copy constructs the underlying containers.
Definition table.hpp:147
basic_table(Container &&...container) noexcept
Move constructs the underlying containers.
Definition table.hpp:156
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition table.hpp:289
internal::table_iterator< typename Container::const_iterator... > const_iterator
Definition table.hpp:132
const_iterator cend() const noexcept
Returns an iterator to the end.
Definition table.hpp:307
internal::table_iterator< typename Container::const_reverse_iterator... > const_reverse_iterator
Definition table.hpp:136
Custom EnTT namespace for the standard template library.
Definition entt.hpp:5
EnTT default namespace.
Definition dense_map.hpp:25
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:168
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.