tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
tuple.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2
3#ifndef TETL_TUPLE_TUPLE_HPP
4#define TETL_TUPLE_TUPLE_HPP
5
6#include <etl/_config/all.hpp>
7
26#include <etl/_utility/move.hpp>
27#include <etl/_utility/swap.hpp>
28
29namespace etl {
30
31namespace detail {
32
33template <etl::size_t I, typename T>
34struct tuple_leaf {
35 auto get_type(index_constant<I> ic) -> T;
36
37 template <typename... Args>
38 constexpr tuple_leaf(Args&&... args)
39 : _value{etl::forward<Args>(args)...}
40 {
41 }
42
43 [[nodiscard]] constexpr auto get_impl(index_constant<I> /*ic*/) & noexcept -> T& { return _value; }
44
45 [[nodiscard]] constexpr auto get_impl(index_constant<I> /*ic*/) const& noexcept -> T const& { return _value; }
46
47 [[nodiscard]] constexpr auto get_impl(index_constant<I> /*ic*/) && noexcept -> T&& { return etl::move(_value); }
48
49 [[nodiscard]] constexpr auto get_impl(index_constant<I> /*ic*/) const&& noexcept -> T const&&
50 {
51 return etl::move(_value);
52 }
53
54 constexpr auto swap_impl(index_constant<I> /*ic*/, T& other) noexcept(is_nothrow_swappable_v<T>) -> void
55 {
56 using etl::swap;
57 swap(_value, other);
58 }
59
60private:
61 TETL_NO_UNIQUE_ADDRESS T _value; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members)
62};
63
64template <typename... Ts>
65struct tuple_impl;
66
67template <size_t... Idx, typename... Ts>
68struct tuple_impl<etl::index_sequence<Idx...>, Ts...> : tuple_leaf<Idx, Ts>... {
69private:
70public:
71 explicit(not(is_implicit_default_constructible_v<Ts> && ...)) constexpr tuple_impl()
72 requires((is_default_constructible_v<Ts> and ...))
73 : tuple_leaf<Idx, Ts>{}...
74 {
75 }
76
77 // No. 2
78 explicit(not(is_convertible_v<Ts const&, Ts> && ...)) constexpr tuple_impl(Ts const&... args)
79 requires((is_copy_constructible_v<Ts> && ...) && (sizeof...(Ts) > 0))
80 : tuple_leaf<Idx, Ts>(args)...
81 {
82 }
83
84 // No. 3
85 template <typename... Args>
86 requires((is_constructible_v<Ts, Args &&> && ...) && (sizeof...(Ts) > 0) && (sizeof...(Ts) == sizeof...(Args)))
87 explicit(!(is_convertible_v<Args&&, Ts> && ...)) constexpr tuple_impl(Args&&... args)
88 : tuple_leaf<Idx, Ts>{etl::forward<Args>(args)}...
89 {
90 }
91
92 constexpr tuple_impl(tuple_impl const&) = default;
93 constexpr tuple_impl(tuple_impl&&) noexcept = default;
94
95 using tuple_leaf<Idx, Ts>::get_type...;
96 using tuple_leaf<Idx, Ts>::get_impl...;
97
98 constexpr auto swap(tuple_impl& other) noexcept((is_nothrow_swappable_v<Ts> && ...)) -> void
99 {
100 (tuple_leaf<Idx, Ts>::swap_impl(etl::index_v<Idx>, other.get_impl(etl::index_v<Idx>)), ...);
101 }
102};
103
104} // namespace detail
105
106template <typename... Ts>
107struct tuple {
108private:
109 template <size_t I, typename T>
110 friend struct tuple_element;
111 template <size_t N, typename... Us>
112 friend constexpr auto get(tuple<Us...>& t) -> auto&; // NOLINT
113 template <size_t N, typename... Us>
114 friend constexpr auto get(tuple<Us...> const& t) -> auto const&; // NOLINT
115 template <size_t N, typename... Us>
116 friend constexpr auto get(tuple<Us...>&& t) -> auto&&; // NOLINT
117 template <size_t N, typename... Us>
118 friend constexpr auto get(tuple<Us...> const&& t) -> auto const&&; // NOLINT
119 template <typename T, typename... Us>
120 friend constexpr auto get(tuple<Us...>& t) -> auto&; // NOLINT
121 template <typename T, typename... Us>
122 friend constexpr auto get(tuple<Us...> const& t) -> auto const&; // NOLINT
123 template <typename T, typename... Us>
124 friend constexpr auto get(tuple<Us...>&& t) -> auto&&; // NOLINT
125 template <typename T, typename... Us>
126 friend constexpr auto get(tuple<Us...> const&& t) -> auto const&&; // NOLINT
127
128 using impl_t = detail::tuple_impl<etl::index_sequence_for<Ts...>, Ts...>;
129 TETL_NO_UNIQUE_ADDRESS impl_t _impl; // NOLINT(modernize-use-default-member-init)
130
131 template <etl::size_t I>
132 [[nodiscard]] constexpr auto get_impl(etl::index_constant<I> ic) & noexcept -> auto&
133 {
134 return _impl.get_impl(ic);
135 }
136
137 template <etl::size_t I>
138 [[nodiscard]] constexpr auto get_impl(etl::index_constant<I> ic) const& noexcept -> auto const&
139 {
140 return _impl.get_impl(ic);
141 }
142
143 template <etl::size_t I>
144 [[nodiscard]] constexpr auto get_impl(etl::index_constant<I> ic) && noexcept -> auto&&
145 {
146 return etl::move(_impl).get_impl(ic);
147 }
148
149 template <etl::size_t I>
150 [[nodiscard]] constexpr auto get_impl(etl::index_constant<I> ic) const&& noexcept -> auto const&&
151 {
152 return etl::move(_impl).get_impl(ic);
153 }
154
155 template <etl::size_t I>
156 auto get_type(etl::index_constant<I> ic) -> decltype(_impl.get_type(ic));
157
158public:
159 // No. 1
160 explicit(not(is_implicit_default_constructible_v<Ts> && ...)) constexpr tuple()
161 requires((is_default_constructible_v<Ts> and ...))
162 : _impl()
163 {
164 }
165
166 explicit(not(is_convertible_v<Ts const&, Ts> && ...)) constexpr tuple(Ts const&... args)
167 requires((is_copy_constructible_v<Ts> && ...) && (sizeof...(Ts) > 0))
168 : _impl(args...)
169 {
170 }
171
172 // No. 3
173 template <typename... Args>
174 requires((is_constructible_v<Ts, Args &&> && ...) && (sizeof...(Ts) > 0) && (sizeof...(Ts) == sizeof...(Args)))
175 explicit(!(is_convertible_v<Args&&, Ts> && ...)) constexpr tuple(Args&&... args)
176 : _impl{etl::forward<Args>(args)...}
177 {
178 }
179
180 constexpr tuple(tuple const&) = default;
181 constexpr tuple(tuple&&) noexcept = default;
182
183 constexpr auto swap(tuple& other) noexcept((is_nothrow_swappable_v<Ts> && ...)) -> void { _impl.swap(other._impl); }
184};
185
186template <etl::size_t I, typename... Ts>
187struct tuple_element<I, tuple<Ts...>> {
188 static_assert(I < sizeof...(Ts));
189 using type = decltype(declval<tuple<Ts...>>().get_type(etl::index_v<I>));
190};
191
192template <typename... Ts>
193struct tuple_size<tuple<Ts...>> : integral_constant<size_t, sizeof...(Ts)> { };
194
195template <typename... Ts>
196inline constexpr auto is_tuple_like<etl::tuple<Ts...>> = true;
197
198template <etl::size_t I, typename... Ts>
199[[nodiscard]] constexpr auto get(tuple<Ts...>& t) -> auto&
200{
201 static_assert(I < sizeof...(Ts));
202 return t.template get_impl<I>(etl::index_v<I>);
203}
204
205template <etl::size_t I, typename... Ts>
206[[nodiscard]] constexpr auto get(tuple<Ts...> const& t) -> auto const&
207{
208 static_assert(I < sizeof...(Ts));
209 return t.template get_impl<I>(etl::index_v<I>);
210}
211
212template <etl::size_t I, typename... Ts>
213[[nodiscard]] constexpr auto get(tuple<Ts...>&& t) -> auto&&
214{
215 static_assert(I < sizeof...(Ts));
216 return etl::move(t).template get_impl<I>(etl::index_v<I>);
217}
218
219template <etl::size_t I, typename... Ts>
220[[nodiscard]] constexpr auto get(tuple<Ts...> const&& t) -> auto const&&
221{
222 static_assert(I < sizeof...(Ts));
223 return etl::move(t).template get_impl<I>(etl::index_v<I>);
224}
225
226template <typename... Ts, typename... Us>
227 requires(sizeof...(Ts) == sizeof...(Us))
228[[nodiscard]] constexpr auto operator==(tuple<Ts...> const& lhs, tuple<Us...> const& rhs) -> bool
229{
230 if constexpr (sizeof...(Ts) == 0) {
231 return false;
232 } else {
233 return [&]<etl::size_t... Is>(etl::index_sequence<Is...> /*i*/) {
234 using etl::get;
235 return ((get<Is>(lhs) == get<Is>(rhs)) and ...);
236 }(etl::index_sequence_for<Ts...>{});
237 }
238}
239
240} // namespace etl
241
242#endif // TETL_TUPLE_TUPLE_HPP
#define TETL_NO_UNIQUE_ADDRESS
Definition attributes.hpp:41
constexpr auto move(InputIt first, InputIt last, OutputIt destination) -> OutputIt
Moves the elements in the range [first, last), to another range beginning at destination,...
Definition move.hpp:26
Definition adjacent_find.hpp:8
constexpr bool is_copy_constructible_v
Definition is_copy_constructible.hpp:30
integral_constant< size_t, I > index_constant
Definition index_constant.hpp:12
constexpr bool is_constructible_v
Definition is_constructible.hpp:24
constexpr auto is_tuple_like
Definition is_tuple_like.hpp:9
auto declval() noexcept -> add_rvalue_reference_t< T >
etl::make_index_sequence< sizeof...(T)> index_sequence_for
Definition index_sequence.hpp:18
constexpr auto index_v
Definition index_constant.hpp:15
constexpr auto get(complex< X > &z) noexcept -> X &
Definition complex.hpp:92
constexpr bool is_default_constructible_v
Definition is_default_constructible.hpp:26
etl::integer_sequence< etl::size_t, Ints... > index_sequence
Definition index_sequence.hpp:12
constexpr auto is_implicit_default_constructible_v
Definition is_implicit_default_constructible.hpp:26
auto swap(inplace_function< R(Args...), Capacity, Alignment > &lhs, inplace_function< R(Args...), Capacity, Alignment > &rhs) noexcept -> void
Overloads the etl::swap algorithm for etl::inplace_function. Exchanges the state of lhs with that of ...
Definition inplace_function.hpp:249
constexpr bool is_convertible_v
Definition is_convertible.hpp:46
constexpr auto forward(remove_reference_t< T > &param) noexcept -> T &&
Forwards lvalues as either lvalues or as rvalues, depending on T. When t is a forwarding reference (a...
Definition forward.hpp:18
TETL_BUILTIN_SIZET size_t
etl::size_t is the unsigned integer type of the result of the sizeof operator.
Definition size_t.hpp:14
constexpr bool is_nothrow_swappable_v
Definition is_nothrow_swappable.hpp:19
Definition integral_constant.hpp:9
decltype(declval< tuple< Ts... > >().get_type(etl::index_v< I >)) type
Definition tuple.hpp:189
Provides compile-time indexed access to the type of the elements of the array using tuple-like interf...
Definition array.hpp:267
Definition tuple_size.hpp:15
Definition tuple.hpp:107
constexpr tuple(tuple const &)=default
constexpr tuple(tuple &&) noexcept=default
friend constexpr auto get(tuple< Us... > &t) -> auto &
friend constexpr auto get(tuple< Us... > const &&t) -> auto const &&
friend struct tuple_element
Definition tuple.hpp:110
constexpr auto swap(tuple &other) noexcept((is_nothrow_swappable_v< Ts > &&...)) -> void
Definition tuple.hpp:183
friend constexpr auto get(tuple< Us... > const &t) -> auto const &
friend constexpr auto get(tuple< Us... > &&t) -> auto &&