MCRO
C++23 utilities for Unreal Engine.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
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
18#include "range/v3/all.hpp"
20
21/** @brief Templating utilities for manipulating `TTuple`s */
22namespace Mcro::Tuples
23{
24 using namespace Mcro::Concepts;
25
26 template <typename>
27 constexpr bool TIsStdArray = false;
28
29 template <typename T, size_t S>
30 constexpr bool TIsStdArray<std::array<T, S>> = true;
31
32 template <typename>
33 constexpr bool TIsStdSubRange = false;
34
35 template <class I, class S, std::ranges::subrange_kind K>
37
38 template <typename>
39 constexpr bool TIsRangeV3SubRange = false;
40
41 template <class I, class S, ranges::subrange_kind K>
43
44 template <typename>
45 constexpr bool TIsStdTuple = false;
46
47 template <typename... Args>
48 constexpr bool TIsStdTuple<std::tuple<Args...>> = true;
49
50 template <typename>
51 constexpr bool TIsStdPair = false;
52
53 template <typename... Args>
54 constexpr bool TIsStdPair<std::pair<Args...>> = true;
55
56 template <typename>
57 constexpr bool TIsRangeV3Tuple = false;
58
59 template <typename... Args>
60 constexpr bool TIsRangeV3Tuple<ranges::common_tuple<Args...>> = true;
61
62 template <typename>
63 constexpr bool TIsRangeV3Pair = false;
64
65 template <typename... Args>
66 constexpr bool TIsRangeV3Pair<ranges::common_pair<Args...>> = true;
67
68 template <typename T>
69 concept CStdTupleLike =
74
75 template <typename T>
80
81 template <typename T>
82 concept CStdPairLike = CStdTupleLike<T> && std::tuple_size_v<std::remove_cvref_t<T>> == 2;
83
84 template <typename T>
85 concept CRangeV3PairLike = CRangeV3TupleLike<T> && std::tuple_size_v<std::remove_cvref_t<T>> == 2;
86
87 template <typename T, typename... Args>
89 CConvertibleToDecayed<T, TTuple<Args...>>
90 || CConvertibleToDecayed<T, std::tuple<Args...>>
91 || CConvertibleToDecayed<T, ranges::common_tuple<Args...>>
92 ;
93
94 template <typename T>
95 concept CUnrealTuple = TIsTuple_V<std::decay_t<T>>;
96
97 template <typename T>
99
100 template <typename T>
102
103 template <size_t I, CStdTupleLike T>
104 decltype(auto) GetItem(T&& tuple)
105 {
106 return std::get<I>(Forward<T>(tuple));
107 }
108
109 template <size_t I, CRangeV3TupleLike T>
110 decltype(auto) GetItem(T&& tuple)
111 {
112 return ranges::get<I>(Forward<T>(tuple));
113 }
114
115 template <size_t I, CUnrealTuple T>
116 decltype(auto) GetItem(T&& tuple)
117 {
118 return tuple.template Get<I>();
119 }
120
121 template <CStdOrRangeV3Tuple T>
122 consteval size_t GetSize()
123 {
124 return std::tuple_size_v<std::decay_t<T>>;
125 }
126
127 template <CUnrealTuple T>
128 consteval size_t GetSize()
129 {
130 return TTupleArity<std::decay_t<T>>::Value;
131 }
132
133 template <CTuple T>
134 using TIndexSequenceForTuple = std::make_index_sequence<GetSize<T>()>;
135
136 template <size_t, typename>
137 struct TTypeAt_Struct {};
138
139 template <size_t I, CStdOrRangeV3Tuple T>
140 struct TTypeAt_Struct<I, T>
141 {
142 using Type = std::tuple_element_t<I, T>;
143 };
144
145 template <size_t I, CUnrealTuple T>
146 struct TTypeAt_Struct<I, T>
147 {
148 using Type = typename TTupleElement<I, T>::Type;
149 };
150
151 template <size_t I, CTuple T>
153
154 template <size_t I, CTuple T>
155 using TTypeAtDecayed = std::decay_t<typename TTypeAt_Struct<I, T>::Type>;
156
157 // TODO: Make these templates compatible with STL and Range-V3 tuples as well
158
159 /** @brief Compose one tuple out of the elements of another tuple based on the input index parameter pack */
160 template <typename Tuple, size_t... Indices>
161 using TComposeFrom = TTuple<typename TTupleElement<Indices, Tuple>::Type...>;
162
163 template <size_t Count, typename Tuple>
164 requires (TTupleArity<Tuple>::Value >= Count)
166 {
167 template <size_t... Indices>
168 static consteval TComposeFrom<Tuple, (Indices + Count)...> Compose(std::index_sequence<Indices...>&&);
169
170 using Type = decltype(
171 Compose(std::make_index_sequence<TTupleArity<Tuple>::Value - Count>{})
172 );
173 };
174
175 /** @brief Skip the first `Count` elements of the input tuple */
176 template <size_t Count, typename Tuple>
178
179 template <size_t Count, typename Tuple>
180 requires (TTupleArity<Tuple>::Value >= Count)
182 {
183 template <size_t... Indices>
184 static consteval TComposeFrom<Tuple, Indices...> Compose(std::index_sequence<Indices...>&&);
185
186 using Type = decltype(
187 Compose(std::make_index_sequence<TTupleArity<Tuple>::Value - Count>{})
188 );
189 };
190
191 /** @brief Disregard the last `Count` elements of the input tuple */
192 template <size_t Count, typename Tuple>
194
195 template <size_t Count, typename Tuple>
196 requires (TTupleArity<Tuple>::Value >= Count)
198 {
199 template <size_t... Indices>
200 static consteval TComposeFrom<Tuple, Indices...> Compose(std::index_sequence<Indices...>&&);
201
202 using Type = decltype(
203 Compose(std::make_index_sequence<Count>{})
204 );
205 };
206
207 /** @brief Take only the first `Count` elements of the input tuple */
208 template <size_t Count, typename Tuple>
210
211 namespace Detail
212 {
213 template <typename T, typename RestTuple, size_t... Indices>
214 auto Prepend_Impl(T&& left, RestTuple const& right, std::index_sequence<Indices...>&&)
215 {
216 return TTuple<T, typename TTupleElement<Indices, RestTuple>::Type...>(
217 Forward<T>(left), right.template Get<Indices>()...
218 );
219 }
220
221 template <typename T, typename RestTuple, size_t... Indices>
222 auto Append_Impl(T&& right, RestTuple const& left, std::index_sequence<Indices...>&&)
223 {
224 return TTuple<typename TTupleElement<Indices, RestTuple>::Type..., T>(
225 left.template Get<Indices>()..., Forward<T>(right)
226 );
227 }
228 }
229
230 /** @brief Prepend a value to a tuple */
231 template <typename T, typename... Rest>
232 TTuple<T, Rest...> operator >> (T&& left, TTuple<Rest...> const& right)
233 {
234 return Detail::Prepend_Impl(left, right, std::make_index_sequence<sizeof...(Rest)>{});
235 }
236
237 /** @brief Append a value to a tuple */
238 template <typename T, typename... Rest>
239 TTuple<Rest..., T> operator << (TTuple<Rest...> const& left, T&& right)
240 {
241 return Detail::Append_Impl(right, left, std::make_index_sequence<sizeof...(Rest)>{});
242 }
243}
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...
Use this header and End.h in tandem to include third-party library headers which may not tolerate Unr...
auto Append_Impl(T &&right, RestTuple const &left, std::index_sequence< Indices... > &&)
Definition Tuples.h:222
auto Prepend_Impl(T &&left, RestTuple const &right, std::index_sequence< Indices... > &&)
Definition Tuples.h:214
Templating utilities for manipulating TTuples.
Definition Tuples.h:23
constexpr bool TIsStdArray
Definition Tuples.h:27
typename TTake_Struct< Count, Tuple >::Type TTake
Take only the first Count elements of the input tuple.
Definition Tuples.h:209
typename TSkip_Struct< Count, Tuple >::Type TSkip
Skip the first Count elements of the input tuple.
Definition Tuples.h:177
TTuple< Rest..., T > operator<<(TTuple< Rest... > const &left, T &&right)
Append a value to a tuple.
Definition Tuples.h:239
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:161
decltype(auto) GetItem(T &&tuple)
Definition Tuples.h:104
std::decay_t< typename TTypeAt_Struct< I, T >::Type > TTypeAtDecayed
Definition Tuples.h:155
constexpr bool TIsRangeV3Pair
Definition Tuples.h:63
typename TTrimEnd_Struct< Count, Tuple >::Type TTrimEnd
Disregard the last Count elements of the input tuple.
Definition Tuples.h:193
constexpr bool TIsStdSubRange
Definition Tuples.h:33
constexpr bool TIsRangeV3SubRange
Definition Tuples.h:39
constexpr bool TIsStdPair
Definition Tuples.h:51
consteval size_t GetSize()
Definition Tuples.h:122
typename TTypeAt_Struct< I, T >::Type TTypeAt
Definition Tuples.h:152
constexpr bool TIsRangeV3Tuple
Definition Tuples.h:57
constexpr bool TIsStdTuple
Definition Tuples.h:45
TTuple< T, Rest... > operator>>(T &&left, TTuple< Rest... > const &right)
Prepend a value to a tuple.
Definition Tuples.h:232
std::make_index_sequence< GetSize< T >()> TIndexSequenceForTuple
Definition Tuples.h:134
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:170
static consteval TComposeFrom< Tuple, Indices... > Compose(std::index_sequence< Indices... > &&)
decltype( Compose(std::make_index_sequence< Count >{})) Type
Definition Tuples.h:202
static consteval TComposeFrom< Tuple, Indices... > Compose(std::index_sequence< Indices... > &&)
decltype( Compose(std::make_index_sequence< TTupleArity< Tuple >::Value - Count >{})) Type
Definition Tuples.h:186
std::tuple_element_t< I, T > Type
Definition Tuples.h:142