tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
array.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2// SPDX-FileCopyrightText: Copyright (C) 2019 Tobias Hienzsch
3
4#ifndef TETL_ARRAY_ARRAY_HPP
5#define TETL_ARRAY_ARRAY_HPP
6
7#include <etl/_config/all.hpp>
8
9#include <etl/_algorithm/equal.hpp>
10#include <etl/_algorithm/fill_n.hpp>
11#include <etl/_algorithm/lexicographical_compare.hpp>
12#include <etl/_algorithm/swap_ranges.hpp>
13#include <etl/_array/c_array.hpp>
14#include <etl/_contracts/check.hpp>
15#include <etl/_cstddef/size_t.hpp>
16#include <etl/_iterator/begin.hpp>
17#include <etl/_iterator/data.hpp>
18#include <etl/_iterator/end.hpp>
19#include <etl/_iterator/prev.hpp>
20#include <etl/_iterator/rbegin.hpp>
21#include <etl/_iterator/rend.hpp>
22#include <etl/_iterator/reverse_iterator.hpp>
23#include <etl/_iterator/size.hpp>
24#include <etl/_tuple/is_tuple_like.hpp>
25#include <etl/_tuple/tuple_element.hpp>
26#include <etl/_tuple/tuple_size.hpp>
27#include <etl/_type_traits/conditional.hpp>
28#include <etl/_type_traits/is_nothrow_swappable.hpp>
29#include <etl/_type_traits/remove_cv.hpp>
30#include <etl/_utility/index_sequence.hpp>
31#include <etl/_utility/move.hpp>
32#include <etl/_utility/unreachable.hpp>
33
34namespace etl {
35/// A container that encapsulates fixed size arrays.
36///
37/// This container is an aggregate type with the same semantics as a
38/// struct holding a C-style array Type[N] as its only non-static data member.
39/// Unlike a C-style array, it doesn't decay to Type* automatically. As an
40/// aggregate type, it can be initialized with aggregate-initialization given at
41/// most N initializers that are convertible to
42/// Type: `array<int, 3> a = {1,2,3};`
43///
44/// \include array.cpp
45///
46/// \headerfile etl/array.hpp
47/// \ingroup array
48template <typename Type, size_t Size>
49struct array {
50 using value_type = Type;
51 using size_type = size_t;
52 using difference_type = ptrdiff_t;
53 using pointer = Type*;
54 using const_pointer = Type const*;
55 using reference = Type&;
56 using const_reference = Type const&;
57 using iterator = Type*;
58 using const_iterator = Type const*;
59 using reverse_iterator = typename etl::reverse_iterator<iterator>;
60 using const_reverse_iterator = typename etl::reverse_iterator<const_iterator>;
61
62 /// Accesses the specified item with range checking.
63 [[nodiscard]] constexpr auto operator[](size_type const pos) noexcept -> reference
64 {
65 if constexpr (Size == 0) {
67 } else {
68 TETL_PRECONDITION_SAFE(pos < Size);
69 return _internal_array_do_not_use_directly[pos];
70 }
71 }
72
73 /// Accesses the specified item with range checking.
74 [[nodiscard]] constexpr auto operator[](size_type const pos) const noexcept -> const_reference
75 {
76 if constexpr (Size == 0) {
78 } else {
79 TETL_PRECONDITION_SAFE(pos < Size);
80 return _internal_array_do_not_use_directly[pos];
81 }
82 }
83
84 /// Accesses the first item.
85 [[nodiscard]] constexpr auto front() noexcept -> reference
86 {
87 return *begin();
88 }
89
90 /// Accesses the first item.
91 [[nodiscard]] constexpr auto front() const noexcept -> const_reference
92 {
93 return *begin();
94 }
95
96 /// Accesses the last item.
97 [[nodiscard]] constexpr auto back() noexcept -> reference
98 {
99 return *etl::prev(end());
100 }
101
102 /// Accesses the last item.
103 [[nodiscard]] constexpr auto back() const noexcept -> const_reference
104 {
105 return *etl::prev(end());
106 }
107
108 /// Returns pointer to the underlying array serving as element
109 /// storage. The pointer is such that range [data(); data() + size()) is
110 /// always a valid range, even if the container is empty (data() is not
111 /// dereferenceable in that case).
112 [[nodiscard]] constexpr auto data() noexcept -> pointer
113 {
114 return begin();
115 }
116
117 /// Returns pointer to the underlying array serving as element
118 /// storage. The pointer is such that range [data(); data() + size()) is
119 /// always a valid range, even if the container is empty (data() is not
120 /// dereferenceable in that case).
121 [[nodiscard]] constexpr auto data() const noexcept -> const_pointer
122 {
123 return begin();
124 }
125
126 /// Returns an iterator to the beginning.
127 [[nodiscard]] constexpr auto begin() noexcept -> iterator
128 {
129 if constexpr (Size == 0) {
130 return nullptr;
131 } else {
132 return etl::begin(_internal_array_do_not_use_directly);
133 }
134 }
135
136 /// Returns an iterator to the beginning.
137 [[nodiscard]] constexpr auto begin() const noexcept -> const_iterator
138 {
139 if constexpr (Size == 0) {
140 return nullptr;
141 } else {
142 return etl::begin(_internal_array_do_not_use_directly);
143 }
144 }
145
146 /// Returns an const iterator to the beginning.
147 [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator
148 {
149 return begin();
150 }
151
152 /// Returns an iterator to the end.
153 [[nodiscard]] constexpr auto end() noexcept -> iterator
154 {
155 if constexpr (Size == 0) {
156 return nullptr;
157 } else {
158 return etl::end(_internal_array_do_not_use_directly);
159 }
160 }
161
162 /// Returns an iterator to the end.
163 [[nodiscard]] constexpr auto end() const noexcept -> const_iterator
164 {
165 if constexpr (Size == 0) {
166 return nullptr;
167 } else {
168 return etl::end(_internal_array_do_not_use_directly);
169 }
170 }
171
172 /// Returns an const iterator to the end.
173 [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator
174 {
175 return end();
176 }
177
178 /// Returns a reverse iterator to the first element of the reversed
179 /// array. It corresponds to the last element of the non-reversed array. If
180 /// the array is empty, the returned iterator is equal to rend().
181 [[nodiscard]] constexpr auto rbegin() noexcept -> reverse_iterator
182 {
183 return reverse_iterator(end());
184 }
185
186 /// Returns a reverse iterator to the first element of the reversed
187 /// array. It corresponds to the last element of the non-reversed array. If
188 /// the array is empty, the returned iterator is equal to rend().
189 [[nodiscard]] constexpr auto rbegin() const noexcept -> const_reverse_iterator
190 {
191 return const_reverse_iterator(end());
192 }
193
194 /// Returns a reverse iterator to the first element of the reversed
195 /// array. It corresponds to the last element of the non-reversed array. If
196 /// the array is empty, the returned iterator is equal to rend().
197 [[nodiscard]] constexpr auto crbegin() const noexcept -> const_reverse_iterator
198 {
199 return rbegin();
200 }
201
202 /// Returns a reverse iterator to the element following the last
203 /// element of the reversed array. It corresponds to the element preceding
204 /// the first element of the non-reversed array. This element acts as a
205 /// placeholder, attempting to access it results in undefined behavior.
206 [[nodiscard]] constexpr auto rend() noexcept -> reverse_iterator
207 {
208 return reverse_iterator(begin());
209 }
210
211 /// Returns a reverse iterator to the element following the last
212 /// element of the reversed array. It corresponds to the element preceding
213 /// the first element of the non-reversed array. This element acts as a
214 /// placeholder, attempting to access it results in undefined behavior.
215 [[nodiscard]] constexpr auto rend() const noexcept -> const_reverse_iterator
216 {
217 return const_reverse_iterator(begin());
218 }
219
220 /// Returns a reverse iterator to the element following the last
221 /// element of the reversed array. It corresponds to the element preceding
222 /// the first element of the non-reversed array. This element acts as a
223 /// placeholder, attempting to access it results in undefined behavior.
224 [[nodiscard]] constexpr auto crend() const noexcept -> const_reverse_iterator
225 {
226 return rend();
227 }
228
229 /// Checks if the container has no elements, i.e. whether begin() == end().
230 [[nodiscard]] constexpr auto empty() const noexcept -> bool
231 {
232 return begin() == end();
233 }
234
235 /// Returns the number of elements in the container, i.e. distance(begin(), end()).
236 [[nodiscard]] constexpr auto size() const noexcept -> size_type
237 {
238 return Size;
239 }
240
241 /// Returns the maximum number of elements the container is able to
242 /// hold due to system or library implementation limitations, i.e.
243 /// distance(begin(), end()) for the largest container.
244 ///
245 /// Because each array<T, N> is a fixed-size container, the value
246 /// returned by max_size equals N (which is also the value returned by size)
247 [[nodiscard]] constexpr auto max_size() const noexcept -> size_type
248 {
249 return Size;
250 }
251
252 /// Assigns the given value value to all elements in the container.
253 constexpr auto fill(const_reference value) -> void
254 {
255 etl::fill_n(begin(), Size, value);
256 }
257
258 /// Exchanges the contents of the container with those of other. Does
259 /// not cause iterators and references to associate with the other
260 /// container.
261 constexpr auto swap(array& other) noexcept(is_nothrow_swappable_v<Type>) -> void
262 {
263 etl::swap_ranges(begin(), end(), other.begin());
264 }
265
266 /// Specializes the swap algorithm for array. Swaps the contents of lhs and rhs.
267 friend constexpr auto swap(array& lhs, array& rhs) noexcept(noexcept(lhs.swap(rhs))) -> void
268 {
269 lhs.swap(rhs);
270 }
271
272 /// Checks if the contents of lhs and rhs are equal, that is, they have
273 /// the same number of elements and each element in lhs compares equal with the
274 /// element in rhs at the same position.
275 friend constexpr auto operator==(array const& lhs, array const& rhs) -> bool
276 {
277 return etl::equal(lhs.begin(), lhs.end(), rhs.begin());
278 }
279
280 /// Compares the contents of lhs and rhs lexicographically. The
281 /// comparison is performed by a function equivalent to lexicographical_compare.
282 friend constexpr auto operator<(array const& lhs, array const& rhs) -> bool
283 {
284 return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
285 }
286
287 friend constexpr auto operator<=(array const& lhs, array const& rhs) -> bool
288 {
289 return !(rhs < lhs);
290 }
291
292 friend constexpr auto operator>(array const& lhs, array const& rhs) -> bool
293 {
294 return rhs < lhs;
295 }
296
297 friend constexpr auto operator>=(array const& lhs, array const& rhs) -> bool
298 {
299 return !(lhs < rhs);
300 }
301
302 /// \internal
303 using array_t = conditional_t<Size == 0, empty_c_array, c_array<Type, Size + size_t{Size == 0}>>;
304
305 /// \internal
306 TETL_NO_UNIQUE_ADDRESS array_t _internal_array_do_not_use_directly; // NOLINT(readability-identifier-naming)
307};
308
309/// One deduction guide is provided for array to provide an equivalent of
310/// experimental::make_array for construction of array from a variadic parameter
311/// pack. The program is ill-formed if (is_same_v<T, U> and ...) is not true.
312/// Note that it is true when sizeof...(U) is zero.
313/// \relates array
314template <typename T, typename... U>
315array(T, U...) -> array<T, 1 + sizeof...(U)>;
316
317/// \brief Provides access to the number of elements in an array as a
318/// compile-time constant expression.
319/// \relates array
320template <typename T, size_t N>
321struct tuple_size<array<T, N>> : integral_constant<size_t, N> { };
322
323/// \relates array
324template <typename T, etl::size_t Size>
325inline constexpr auto is_tuple_like<etl::array<T, Size>> = true;
326
327/// \brief Provides compile-time indexed access to the type of the elements of
328/// the array using tuple-like interface.
329template <size_t I, typename T>
330struct tuple_element;
331
332template <size_t I, typename T, size_t N>
333struct tuple_element<I, array<T, N>> {
334 using type = T;
335};
336
337/// \brief Extracts the Ith element element from the array. I must be an integer
338/// value in range [0, N). This is enforced at compile time as opposed to at()
339/// or operator[].
340/// \relates array
341template <size_t Index, typename T, size_t Size>
342[[nodiscard]] constexpr auto get(array<T, Size>& array) noexcept -> T&
343{
344 static_assert(Index < Size, "array index out of range");
345 return array[Index];
346}
347
348/// \relates array
349template <size_t Index, typename T, size_t Size>
350[[nodiscard]] constexpr auto get(array<T, Size> const& array) noexcept -> T const&
351{
352 static_assert(Index < Size, "array index out of range");
353 return array[Index];
354}
355
356/// \relates array
357template <size_t Index, typename T, size_t Size>
358[[nodiscard]] constexpr auto get(array<T, Size>&& array) noexcept -> T&&
359{
360 static_assert(Index < Size, "array index out of range");
361 return etl::move(array[Index]);
362}
363
364/// \relates array
365template <size_t Index, typename T, size_t Size>
366[[nodiscard]] constexpr auto get(array<T, Size> const&& array) noexcept -> T const&&
367{
368 static_assert(Index < Size, "array index out of range");
369 return etl::move(array[Index]);
370}
371
372/// \brief Creates a array from the one dimensional built-in array a. The
373/// elements of the array are copy-initialized from the corresponding element of
374/// a. Copying or moving multidimensional built-in array is not supported.
375/// \relates array
376template <typename T, size_t N>
377[[nodiscard]] constexpr auto to_array(T (&a)[N]) -> array<remove_cv_t<T>, N>
378{
379 return [&]<etl::size_t... I>(etl::index_sequence<I...> /*i*/) {
380 return etl::array<etl::remove_cv_t<T>, N>{{a[I]...}};
381 }(etl::make_index_sequence<N>{});
382}
383
384/// \relates array
385template <typename T, size_t N>
386[[nodiscard]] constexpr auto to_array(T (&&a)[N])
387{
388 return [&]<etl::size_t... I>(etl::index_sequence<I...> /*i*/) {
389 return etl::array<etl::remove_cv_t<T>, N>{{etl::move(a[I])...}};
390 }(etl::make_index_sequence<N>{});
391}
392
393template <typename T>
394inline constexpr auto is_etl_array = false;
395
396template <typename T, size_t Size>
397inline constexpr auto is_etl_array<array<T, Size>> = true;
398
399} // namespace etl
400
401#endif // TETL_ARRAY_ARRAY_HPP
Definition adjacent_find.hpp:9
constexpr auto is_etl_array< array< T, Size > >
Definition array.hpp:397
constexpr auto is_etl_array
Definition array.hpp:394
auto unreachable() -> void
Definition unreachable.hpp:11
A container that encapsulates fixed size arrays.
Definition array.hpp:49
constexpr auto fill(const_reference value) -> void
Assigns the given value value to all elements in the container.
Definition array.hpp:253
constexpr auto to_array(T(&&a)[N])
Definition array.hpp:386
constexpr auto front() const noexcept -> const_reference
Accesses the first item.
Definition array.hpp:91
constexpr auto get(array< T, Size > &&array) noexcept -> T &&
Definition array.hpp:358
constexpr auto crbegin() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the first element of the reversed array. It corresponds to the last ele...
Definition array.hpp:197
array(T, U...) -> array< T, 1+sizeof...(U)>
One deduction guide is provided for array to provide an equivalent of experimental::make_array for co...
constexpr auto rbegin() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the first element of the reversed array. It corresponds to the last ele...
Definition array.hpp:189
constexpr auto get(array< T, Size > const &&array) noexcept -> T const &&
Definition array.hpp:366
constexpr auto is_tuple_like
Definition array.hpp:325
friend constexpr auto operator<(array const &lhs, array const &rhs) -> bool
Compares the contents of lhs and rhs lexicographically. The comparison is performed by a function equ...
Definition array.hpp:282
constexpr auto operator[](size_type const pos) noexcept -> reference
Accesses the specified item with range checking.
Definition array.hpp:63
constexpr auto operator[](size_type const pos) const noexcept -> const_reference
Accesses the specified item with range checking.
Definition array.hpp:74
constexpr auto back() noexcept -> reference
Accesses the last item.
Definition array.hpp:97
constexpr auto rend() noexcept -> reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed array....
Definition array.hpp:206
constexpr auto get(array< T, Size > &array) noexcept -> T &
Extracts the Ith element element from the array. I must be an integer value in range [0,...
Definition array.hpp:342
constexpr auto begin() noexcept -> iterator
Returns an iterator to the beginning.
Definition array.hpp:127
constexpr auto end() noexcept -> iterator
Returns an iterator to the end.
Definition array.hpp:153
constexpr auto begin() const noexcept -> const_iterator
Returns an iterator to the beginning.
Definition array.hpp:137
constexpr auto cbegin() const noexcept -> const_iterator
Returns an const iterator to the beginning.
Definition array.hpp:147
friend constexpr auto operator==(array const &lhs, array const &rhs) -> bool
Checks if the contents of lhs and rhs are equal, that is, they have the same number of elements and e...
Definition array.hpp:275
constexpr auto empty() const noexcept -> bool
Checks if the container has no elements, i.e. whether begin() == end().
Definition array.hpp:230
constexpr auto data() noexcept -> pointer
Returns pointer to the underlying array serving as element storage. The pointer is such that range [d...
Definition array.hpp:112
constexpr auto back() const noexcept -> const_reference
Accesses the last item.
Definition array.hpp:103
constexpr auto front() noexcept -> reference
Accesses the first item.
Definition array.hpp:85
friend constexpr auto operator>(array const &lhs, array const &rhs) -> bool
Definition array.hpp:292
friend constexpr auto swap(array &lhs, array &rhs) noexcept(noexcept(lhs.swap(rhs))) -> void
Specializes the swap algorithm for array. Swaps the contents of lhs and rhs.
Definition array.hpp:267
constexpr auto to_array(T(&a)[N]) -> array< remove_cv_t< T >, N >
Creates a array from the one dimensional built-in array a. The elements of the array are copy-initial...
Definition array.hpp:377
constexpr auto get(array< T, Size > const &array) noexcept -> T const &
Definition array.hpp:350
constexpr auto max_size() const noexcept -> size_type
Returns the maximum number of elements the container is able to hold due to system or library impleme...
Definition array.hpp:247
constexpr auto end() const noexcept -> const_iterator
Returns an iterator to the end.
Definition array.hpp:163
constexpr auto crend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed array....
Definition array.hpp:224
friend constexpr auto operator>=(array const &lhs, array const &rhs) -> bool
Definition array.hpp:297
friend constexpr auto operator<=(array const &lhs, array const &rhs) -> bool
Definition array.hpp:287
constexpr auto swap(array &other) noexcept(is_nothrow_swappable_v< Type >) -> void
Exchanges the contents of the container with those of other. Does not cause iterators and references ...
Definition array.hpp:261
constexpr auto data() const noexcept -> const_pointer
Returns pointer to the underlying array serving as element storage. The pointer is such that range [d...
Definition array.hpp:121
constexpr auto rend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed array....
Definition array.hpp:215
constexpr auto size() const noexcept -> size_type
Returns the number of elements in the container, i.e. distance(begin(), end()).
Definition array.hpp:236
constexpr auto cend() const noexcept -> const_iterator
Returns an const iterator to the end.
Definition array.hpp:173
constexpr auto rbegin() noexcept -> reverse_iterator
Returns a reverse iterator to the first element of the reversed array. It corresponds to the last ele...
Definition array.hpp:181
Definition c_array.hpp:16
Definition integral_constant.hpp:10