MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
Tuples.h
Go to the documentation of this file.
1/** @noop License Comment
2 * @file
3 * @copyright
4 * This Source Code is subject to the terms of the Mozilla Public License, v2.0.
5 * If a copy of the MPL was not distributed with this file You can obtain one at
6 * https://mozilla.org/MPL/2.0/
7 *
8 * @author David Mórász
9 * @date 2025
10 */
11
12#pragma once
13
14#include "CoreMinimal.h"
15#include "Mcro/Concepts.h"
16#include "Mcro/Templates.h"
17
19#include "range/v3/all.hpp"
21
22/** @brief Templating utilities for manipulating `TTuple`s */
23namespace Mcro::Tuples
24{
25 using namespace Mcro::Concepts;
26 using namespace Mcro::Templates;
27
28 template <typename>
29 constexpr bool TIsStdArray = false;
30
31 template <typename T, size_t S>
32 constexpr bool TIsStdArray<std::array<T, S>> = true;
33
34 template <typename>
35 constexpr bool TIsStdSubRange = false;
36
37 template <class I, class S, std::ranges::subrange_kind K>
39
40 template <typename>
41 constexpr bool TIsRangeV3SubRange = false;
42
43 template <class I, class S, ranges::subrange_kind K>
45
46 template <typename>
47 constexpr bool TIsStdTuple = false;
48
49 template <typename... Args>
50 constexpr bool TIsStdTuple<std::tuple<Args...>> = true;
51
52 template <typename>
53 constexpr bool TIsStdPair = false;
54
55 template <typename... Args>
56 constexpr bool TIsStdPair<std::pair<Args...>> = true;
57
58 template <typename>
59 constexpr bool TIsRangeV3Tuple = false;
60
61 template <typename... Args>
62 constexpr bool TIsRangeV3Tuple<ranges::common_tuple<Args...>> = true;
63
64 template <typename>
65 constexpr bool TIsRangeV3Pair = false;
66
67 template <typename... Args>
68 constexpr bool TIsRangeV3Pair<ranges::common_pair<Args...>> = true;
69
70 template <typename T>
71 concept CStdTupleLike =
76
77 template <typename T>
82
83 template <typename T>
84 concept CStdPairLike = CStdTupleLike<T> && std::tuple_size_v<std::remove_cvref_t<T>> == 2;
85
86 template <typename T>
87 concept CRangeV3PairLike = CRangeV3TupleLike<T> && std::tuple_size_v<std::remove_cvref_t<T>> == 2;
88
89 template <typename T, typename... Args>
91 CConvertibleToDecayed<T, TTuple<Args...>>
92 || CConvertibleToDecayed<T, std::tuple<Args...>>
93 || CConvertibleToDecayed<T, ranges::common_tuple<Args...>>
94 ;
95
96 template <typename T>
97 concept CUnrealTuple = TIsTuple_V<std::decay_t<T>>;
98
99 template <typename T>
101
102 template <typename T>
104
105 template <size_t I, CStdTupleLike T>
106 decltype(auto) GetItem(T&& tuple)
107 {
108 return std::get<I>(FWD(tuple));
109 }
110
111 template <size_t I, CRangeV3TupleLike T>
112 decltype(auto) GetItem(T&& tuple)
113 {
114 return ranges::get<I>(FWD(tuple));
115 }
116
117 template <size_t I, CUnrealTuple T>
118 decltype(auto) GetItem(T&& tuple)
119 {
120 return FWD(tuple).template Get<I>();
121 }
122
123 template <CStdOrRangeV3Tuple T>
124 consteval size_t GetSize()
125 {
126 return std::tuple_size_v<std::decay_t<T>>;
127 }
128
129 template <CUnrealTuple T>
130 consteval size_t GetSize()
131 {
132 return TTupleArity<std::decay_t<T>>::Value;
133 }
134
135 template <CTuple T>
136 using TIndexSequenceForTuple = std::make_index_sequence<GetSize<T>()>;
137
138 template <size_t, typename>
139 struct TTypeAt_Struct {};
140
141 template <size_t I, CStdOrRangeV3Tuple T>
142 struct TTypeAt_Struct<I, T>
143 {
144 using Type = std::tuple_element_t<I, T>;
145 };
146
147 template <size_t I, CUnrealTuple T>
148 struct TTypeAt_Struct<I, T>
149 {
151 };
152
153 template <size_t I, CTuple T>
155
156 template <size_t I, CTuple T>
157 using TTypeAtDecayed = std::decay_t<typename TTypeAt_Struct<I, T>::Type>;
158
159 // TODO: Make these templates compatible with STL and Range-V3 tuples as well
160
161 /** @brief Compose one tuple out of the elements of another tuple based on the input index parameter pack */
162 template <typename Tuple, size_t... Indices>
163 using TComposeFrom = TTuple<typename TTupleElement<Indices, Tuple>::Type...>;
164
165 template <size_t Count, typename Tuple>
166 requires (TTupleArity<Tuple>::Value >= Count)
168 {
169 template <size_t... Indices>
170 static consteval TComposeFrom<Tuple, (Indices + Count)...> Compose(std::index_sequence<Indices...>&&);
171
172 using Type = decltype(
173 Compose(std::make_index_sequence<TTupleArity<Tuple>::Value - Count>{})
174 );
175 };
176
177 /** @brief Skip the first `Count` elements of the input tuple */
178 template <size_t Count, typename Tuple>
180
181 template <size_t Count, typename Tuple>
182 requires (TTupleArity<Tuple>::Value >= Count)
184 {
185 template <size_t... Indices>
186 static consteval TComposeFrom<Tuple, Indices...> Compose(std::index_sequence<Indices...>&&);
187
188 using Type = decltype(
189 Compose(std::make_index_sequence<TTupleArity<Tuple>::Value - Count>{})
190 );
191 };
192
193 /** @brief Disregard the last `Count` elements of the input tuple */
194 template <size_t Count, typename Tuple>
196
197 template <size_t Count, typename Tuple>
198 requires (TTupleArity<Tuple>::Value >= Count)
200 {
201 template <size_t... Indices>
202 static consteval TComposeFrom<Tuple, Indices...> Compose(std::index_sequence<Indices...>&&);
203
204 using Type = decltype(
205 Compose(std::make_index_sequence<Count>{})
206 );
207 };
208
209 /** @brief Take only the first `Count` elements of the input tuple */
210 template <size_t Count, typename Tuple>
212
213 namespace Detail
214 {
215 template <typename T, typename RestTuple, size_t... Indices>
216 auto Prepend_Impl(T&& left, RestTuple const& right, std::index_sequence<Indices...>&&)
217 {
218 return TTuple<T, typename TTupleElement<Indices, RestTuple>::Type...>(
219 FWD(left), right.template Get<Indices>()...
220 );
221 }
222
223 template <typename T, typename RestTuple, size_t... Indices>
224 auto Append_Impl(T&& right, RestTuple const& left, std::index_sequence<Indices...>&&)
225 {
226 return TTuple<typename TTupleElement<Indices, RestTuple>::Type..., T>(
227 left.template Get<Indices>()..., FWD(right)
228 );
229 }
230 }
231
232 /** @brief Prepend a value to a tuple */
233 template <typename T, typename... Rest>
234 TTuple<T, Rest...> operator >> (T&& left, TTuple<Rest...> const& right)
235 {
236 return Detail::Prepend_Impl(left, right, std::make_index_sequence<sizeof...(Rest)>{});
237 }
238
239 /** @brief Append a value to a tuple */
240 template <typename T, typename... Rest>
241 TTuple<Rest..., T> operator << (TTuple<Rest...> const& left, T&& right)
242 {
243 return Detail::Append_Impl(right, left, std::make_index_sequence<sizeof...(Rest)>{});
244 }
245}
This header exists because STL headers in Android doesn't define STL concepts (other than same_as whi...
Use this header and Start.h in tandem to include third-party library headers which may not tolerate U...
#define FWD(...)
Shorten forwarding expression with this macro so one may not need to specify explicit type.
Definition Macros.h:100
Use this header and End.h in tandem to include third-party library headers which may not tolerate Unr...
This namespace provides templating utilities and introspection into template instantiations.
Definition Templates.h:21
auto Append_Impl(T &&right, RestTuple const &left, std::index_sequence< Indices... > &&)
Definition Tuples.h:224
auto Prepend_Impl(T &&left, RestTuple const &right, std::index_sequence< Indices... > &&)
Definition Tuples.h:216
Templating utilities for manipulating TTuples.
Definition Tuples.h:24
constexpr bool TIsStdArray
Definition Tuples.h:29
typename TTake_Struct< Count, Tuple >::Type TTake
Take only the first Count elements of the input tuple.
Definition Tuples.h:211
typename TSkip_Struct< Count, Tuple >::Type TSkip
Skip the first Count elements of the input tuple.
Definition Tuples.h:179
TTuple< Rest..., T > operator<<(TTuple< Rest... > const &left, T &&right)
Append a value to a tuple.
Definition Tuples.h:241
TTuple< typename TTupleElement< Indices, Tuple >::Type... > TComposeFrom
Compose one tuple out of the elements of another tuple based on the input index parameter pack.
Definition Tuples.h:163
decltype(auto) GetItem(T &&tuple)
Definition Tuples.h:106
std::decay_t< typename TTypeAt_Struct< I, T >::Type > TTypeAtDecayed
Definition Tuples.h:157
constexpr bool TIsRangeV3Pair
Definition Tuples.h:65
typename TTrimEnd_Struct< Count, Tuple >::Type TTrimEnd
Disregard the last Count elements of the input tuple.
Definition Tuples.h:195
constexpr bool TIsStdSubRange
Definition Tuples.h:35
constexpr bool TIsRangeV3SubRange
Definition Tuples.h:41
constexpr bool TIsStdPair
Definition Tuples.h:53
consteval size_t GetSize()
Definition Tuples.h:124
typename TTypeAt_Struct< I, T >::Type TTypeAt
Definition Tuples.h:154
constexpr bool TIsRangeV3Tuple
Definition Tuples.h:59
constexpr bool TIsStdTuple
Definition Tuples.h:47
TTuple< T, Rest... > operator>>(T &&left, TTuple< Rest... > const &right)
Prepend a value to a tuple.
Definition Tuples.h:234
std::make_index_sequence< GetSize< T >()> TIndexSequenceForTuple
Definition Tuples.h:136
static consteval TComposeFrom< Tuple,(Indices+Count)... > Compose(std::index_sequence< Indices... > &&)
decltype( Compose(std::make_index_sequence< TTupleArity< Tuple >::Value - Count >{})) Type
Definition Tuples.h:172
static consteval TComposeFrom< Tuple, Indices... > Compose(std::index_sequence< Indices... > &&)
decltype( Compose(std::make_index_sequence< Count >{})) Type
Definition Tuples.h:204
static consteval TComposeFrom< Tuple, Indices... > Compose(std::index_sequence< Indices... > &&)
decltype( Compose(std::make_index_sequence< TTupleArity< Tuple >::Value - Count >{})) Type
Definition Tuples.h:188
std::tuple_element_t< I, T > Type
Definition Tuples.h:144