· 5 years ago · Mar 04, 2021, 08:54 PM
1// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "../BasicTypes.h"
6#include "AreTypesEqual.h"
7#include "UnrealTemplate.h"
8#include "Decay.h"
9#include "../Delegates/IntegerSequence.h"
10
11// Static analysis causes internal compiler errors with auto-deduced return types,
12// but some older VC versions still have return type deduction failures inside the delegate code
13// when they are enabled. So we currently only enable them for static analysis builds.
14#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
15 #define USE_TUPLE_AUTO_RETURN_TYPES (PLATFORM_COMPILER_HAS_AUTO_RETURN_TYPES && USING_CODE_ANALYSIS)
16#else
17 #define USE_TUPLE_AUTO_RETURN_TYPES 1
18#endif
19
20#define TUPLES_USE_DEFAULTED_FUNCTIONS 1
21
22template <typename... Types>
23struct TTuple;
24
25namespace UE4Tuple_Private
26{
27 template <int32 N, typename... Types>
28 struct TNthTypeFromParameterPack;
29
30 template <int32 N, typename T, typename... OtherTypes>
31 struct TNthTypeFromParameterPack<N, T, OtherTypes...>
32 {
33 typedef typename TNthTypeFromParameterPack<N - 1, OtherTypes...>::Type Type;
34 };
35
36 template <typename T, typename... OtherTypes>
37 struct TNthTypeFromParameterPack<0, T, OtherTypes...>
38 {
39 typedef T Type;
40 };
41
42 template <typename T, typename... Types>
43 struct TDecayedFrontOfParameterPackIsSameType
44 {
45 enum { Value = TAreTypesEqual<T, typename TDecay<typename TNthTypeFromParameterPack<0, Types...>::Type>::Type>::Value };
46 };
47
48 template <typename T, uint32 Index>
49 struct TTupleElement
50 {
51 template <
52 typename... ArgTypes,
53 typename = typename TEnableIf<
54 TAndValue<
55 sizeof...(ArgTypes) != 0,
56 TOrValue<
57 sizeof...(ArgTypes) != 1,
58 TNot<UE4Tuple_Private::TDecayedFrontOfParameterPackIsSameType<TTupleElement, ArgTypes...>>
59 >
60 >::Value
61 >::Type
62 >
63 explicit TTupleElement(ArgTypes&&... Args)
64 : Value(Forward<ArgTypes>(Args)...)
65 {
66 }
67
68 TTupleElement()
69 : Value()
70 {
71 }
72
73 #if TUPLES_USE_DEFAULTED_FUNCTIONS
74
75 TTupleElement(TTupleElement&&) = default;
76 TTupleElement(const TTupleElement&) = default;
77 TTupleElement& operator=(TTupleElement&&) = default;
78 TTupleElement& operator=(const TTupleElement&) = default;
79
80 #else
81
82 TTupleElement(TTupleElement&& Other)
83 : Value(MoveTemp(Other.Value))
84 {
85 }
86
87 TTupleElement(const TTupleElement& Other)
88 : Value(Other.Value)
89 {
90 }
91
92 void operator=(TTupleElement&& Other)
93 {
94 Value = MoveTemp(Other.Value);
95 }
96
97 void operator=(const TTupleElement& Other)
98 {
99 Value = Other.Value;
100 }
101
102 #endif
103
104 T Value;
105 };
106
107 template <uint32 IterIndex, uint32 Index, typename... Types>
108 struct TTupleElementHelperImpl;
109
110 template <uint32 IterIndex, uint32 Index, typename ElementType, typename... Types>
111 struct TTupleElementHelperImpl<IterIndex, Index, ElementType, Types...> : TTupleElementHelperImpl<IterIndex + 1, Index, Types...>
112 {
113 };
114
115 template <uint32 Index, typename ElementType, typename... Types>
116 struct TTupleElementHelperImpl<Index, Index, ElementType, Types...>
117 {
118 typedef ElementType Type;
119
120 template <typename TupleType>
121 static FORCEINLINE ElementType& Get(TupleType& Tuple)
122 {
123 return static_cast<TTupleElement<ElementType, Index>&>(Tuple).Value;
124 }
125
126 template <typename TupleType>
127 static FORCEINLINE const ElementType& Get(const TupleType& Tuple)
128 {
129 return Get((TupleType&)Tuple);
130 }
131 };
132
133 template <uint32 WantedIndex, typename... Types>
134 struct TTupleElementHelper : TTupleElementHelperImpl<0, WantedIndex, Types...>
135 {
136 };
137
138 template <uint32 ArgCount, uint32 ArgToCompare>
139 struct FEqualityHelper
140 {
141 template <typename TupleType>
142 FORCEINLINE static bool Compare(const TupleType& Lhs, const TupleType& Rhs)
143 {
144 return Lhs.template Get<ArgToCompare>() == Rhs.template Get<ArgToCompare>() && FEqualityHelper<ArgCount, ArgToCompare + 1>::Compare(Lhs, Rhs);
145 }
146 };
147
148 template <uint32 ArgCount>
149 struct FEqualityHelper<ArgCount, ArgCount>
150 {
151 template <typename TupleType>
152 FORCEINLINE static bool Compare(const TupleType& Lhs, const TupleType& Rhs)
153 {
154 return true;
155 }
156 };
157
158 template <uint32 NumArgs, uint32 ArgToCompare = 0, bool Last = ArgToCompare + 1 == NumArgs>
159 struct TLessThanHelper
160 {
161 template <typename TupleType>
162 FORCEINLINE static bool Do(const TupleType& Lhs, const TupleType& Rhs)
163 {
164 return Lhs.template Get<ArgToCompare>() < Rhs.template Get<ArgToCompare>() || (!(Rhs.template Get<ArgToCompare>() < Lhs.template Get<ArgToCompare>()) && TLessThanHelper<NumArgs, ArgToCompare + 1>::Do(Lhs, Rhs));
165 }
166 };
167
168 template <uint32 NumArgs, uint32 ArgToCompare>
169 struct TLessThanHelper<NumArgs, ArgToCompare, true>
170 {
171 template <typename TupleType>
172 FORCEINLINE static bool Do(const TupleType& Lhs, const TupleType& Rhs)
173 {
174 return Lhs.template Get<ArgToCompare>() < Rhs.template Get<ArgToCompare>();
175 }
176 };
177
178 template <uint32 NumArgs>
179 struct TLessThanHelper<NumArgs, NumArgs, false>
180 {
181 template <typename TupleType>
182 FORCEINLINE static bool Do(const TupleType& Lhs, const TupleType& Rhs)
183 {
184 return false;
185 }
186 };
187
188 template <typename Indices, typename... Types>
189 struct TTupleStorage;
190
191 template <uint32... Indices, typename... Types>
192 struct TTupleStorage<TIntegerSequence<uint32, Indices...>, Types...> : TTupleElement<Types, Indices>...
193 {
194 template <
195 typename... ArgTypes,
196 typename = typename TEnableIf<
197 TAndValue<
198 sizeof...(ArgTypes) == sizeof...(Types) && sizeof...(ArgTypes) != 0,
199 TOrValue<
200 sizeof...(ArgTypes) != 1,
201 TNot<UE4Tuple_Private::TDecayedFrontOfParameterPackIsSameType<TTupleStorage, ArgTypes...>>
202 >
203 >::Value
204 >::Type
205 >
206 explicit TTupleStorage(ArgTypes&&... Args)
207 : TTupleElement<Types, Indices>(Forward<ArgTypes>(Args))...
208 {
209 }
210
211 #if TUPLES_USE_DEFAULTED_FUNCTIONS
212
213 TTupleStorage() = default;
214 TTupleStorage(TTupleStorage&&) = default;
215 TTupleStorage(const TTupleStorage&) = default;
216 TTupleStorage& operator=(TTupleStorage&&) = default;
217 TTupleStorage& operator=(const TTupleStorage&) = default;
218
219 #else
220
221 TTupleStorage()
222 : TTupleElement<Types, Indices>()...
223 {
224 }
225
226 TTupleStorage(TTupleStorage&& Other)
227 : TTupleElement<Types, Indices>(MoveTemp(*(TTupleElement<Types, Indices>*)&Other))...
228 {
229 }
230
231 TTupleStorage(const TTupleStorage& Other)
232 : TTupleElement<Types, Indices>(*(const TTupleElement<Types, Indices>*)&Other)...
233 {
234 }
235
236 void operator=(TTupleStorage&& Other)
237 {
238 int Temp[] = { 0, (*(TTupleElement<Types, Indices>*)this = MoveTemp(*(TTupleElement<Types, Indices>*)&Other), 0)... };
239 (void)Temp;
240 }
241
242 void operator=(const TTupleStorage& Other)
243 {
244 int Temp[] = { 0, (*(TTupleElement<Types, Indices>*)this = *(const TTupleElement<Types, Indices>*)&Other, 0)... };
245 (void)Temp;
246 }
247
248 #endif
249
250 template <uint32 Index> FORCEINLINE const typename TTupleElementHelper<Index, Types...>::Type& Get() const { return TTupleElementHelper<Index, Types...>::Get(*this); }
251 template <uint32 Index> FORCEINLINE typename TTupleElementHelper<Index, Types...>::Type& Get() { return TTupleElementHelper<Index, Types...>::Get(*this); }
252 };
253
254 // Specialization of 2-TTuple to give it the API of TPair.
255 template <typename InKeyType, typename InValueType>
256 struct TTupleStorage<TIntegerSequence<uint32, 0, 1>, InKeyType, InValueType>
257 {
258 private:
259 template <uint32 Index, typename Dummy> // Dummy needed for partial template specialization workaround
260 struct TGetHelper;
261
262 template <typename Dummy>
263 struct TGetHelper<0, Dummy>
264 {
265 typedef InKeyType ResultType;
266
267 static const InKeyType& Get(const TTupleStorage& Tuple) { return Tuple.Key; }
268 static InKeyType& Get( TTupleStorage& Tuple) { return Tuple.Key; }
269 };
270
271 template <typename Dummy>
272 struct TGetHelper<1, Dummy>
273 {
274 typedef InValueType ResultType;
275
276 static const InValueType& Get(const TTupleStorage& Tuple) { return Tuple.Value; }
277 static InValueType& Get( TTupleStorage& Tuple) { return Tuple.Value; }
278 };
279
280 public:
281 typedef InKeyType KeyType;
282 typedef InValueType ValueType;
283
284 template <typename KeyInitType, typename ValueInitType>
285 explicit TTupleStorage(KeyInitType&& KeyInit, ValueInitType&& ValueInit)
286 : Key (Forward<KeyInitType >(KeyInit ))
287 , Value(Forward<ValueInitType>(ValueInit))
288 {
289 }
290
291 TTupleStorage()
292 : Key()
293 , Value()
294 {
295 }
296
297 #if TUPLES_USE_DEFAULTED_FUNCTIONS
298
299 TTupleStorage(TTupleStorage&&) = default;
300 TTupleStorage(const TTupleStorage&) = default;
301 TTupleStorage& operator=(TTupleStorage&&) = default;
302 TTupleStorage& operator=(const TTupleStorage&) = default;
303
304 #else
305
306 TTupleStorage(TTupleStorage&& Other)
307 : Key (MoveTemp(Other.Key))
308 , Value(MoveTemp(Other.Value))
309 {
310 }
311
312 TTupleStorage(const TTupleStorage& Other)
313 : Key (Other.Key)
314 , Value(Other.Value)
315 {
316 }
317
318 void operator=(TTupleStorage&& Other)
319 {
320 Key = MoveTemp(Other.Key);
321 Value = MoveTemp(Other.Value);
322 }
323
324 void operator=(const TTupleStorage& Other)
325 {
326 Key = Other.Key;
327 Value = Other.Value;
328 }
329
330 #endif
331
332 template <uint32 Index> FORCEINLINE const typename TGetHelper<Index, void>::ResultType& Get() const { return TGetHelper<Index, void>::Get(*this); }
333 template <uint32 Index> FORCEINLINE typename TGetHelper<Index, void>::ResultType& Get() { return TGetHelper<Index, void>::Get(*this); }
334
335 InKeyType Key;
336 InValueType Value;
337 };
338
339 template <typename Indices, typename... Types>
340 struct TTupleImpl;
341
342 template <uint32... Indices, typename... Types>
343 struct TTupleImpl<TIntegerSequence<uint32, Indices...>, Types...> : TTupleStorage<TIntegerSequence<uint32, Indices...>, Types...>
344 {
345 private:
346 typedef TTupleStorage<TIntegerSequence<uint32, Indices...>, Types...> Super;
347
348 public:
349 using Super::Get;
350
351 template <
352 typename... ArgTypes,
353 typename = typename TEnableIf<
354 TAndValue<
355 sizeof...(ArgTypes) == sizeof...(Types) && sizeof...(ArgTypes) != 0,
356 TOrValue<
357 sizeof...(ArgTypes) != 1,
358 TNot<UE4Tuple_Private::TDecayedFrontOfParameterPackIsSameType<TTupleImpl, ArgTypes...>>
359 >
360 >::Value
361 >::Type
362 >
363 explicit TTupleImpl(ArgTypes&&... Args)
364 : Super(Forward<ArgTypes>(Args)...)
365 {
366 }
367
368 #if TUPLES_USE_DEFAULTED_FUNCTIONS
369
370 TTupleImpl() = default;
371 TTupleImpl(TTupleImpl&& Other) = default;
372 TTupleImpl(const TTupleImpl& Other) = default;
373 TTupleImpl& operator=(TTupleImpl&& Other) = default;
374 TTupleImpl& operator=(const TTupleImpl& Other) = default;
375
376 #else
377
378 TTupleImpl()
379 : Super()
380 {
381 }
382
383 TTupleImpl(TTupleImpl&& Other)
384 : Super(MoveTemp(*(Super*)&Other))
385 {
386 }
387
388 TTupleImpl(const TTupleImpl& Other)
389 : Super(*(const Super*)&Other)
390 {
391 }
392
393 void operator=(TTupleImpl&& Other)
394 {
395 *(Super*)this = MoveTemp(*(Super*)&Other);
396 }
397
398 void operator=(const TTupleImpl& Other)
399 {
400 *(Super*)this = *(const Super*)&Other;
401 }
402
403 #endif
404
405 template <typename FuncType, typename... ArgTypes>
406 #if USE_TUPLE_AUTO_RETURN_TYPES
407 decltype(auto) ApplyAfter(FuncType&& Func, ArgTypes&&... Args) const
408 #else
409 auto ApplyAfter(FuncType&& Func, ArgTypes&&... Args) const -> decltype(Func(Forward<ArgTypes>(Args)..., Get<Indices>()...))
410 #endif
411 {
412 return Func(Forward<ArgTypes>(Args)..., this->template Get<Indices>()...);
413 }
414
415 template <typename FuncType, typename... ArgTypes>
416 #if USE_TUPLE_AUTO_RETURN_TYPES
417 decltype(auto) ApplyBefore(FuncType&& Func, ArgTypes&&... Args) const
418 #else
419 auto ApplyBefore(FuncType&& Func, ArgTypes&&... Args) const -> decltype(Func(Get<Indices>()..., Forward<ArgTypes>(Args)...))
420 #endif
421 {
422 return Func(this->template Get<Indices>()..., Forward<ArgTypes>(Args)...);
423 }
424
425 FORCEINLINE friend bool operator==(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
426 {
427 // This could be implemented with a fold expression when our compilers support it
428 return FEqualityHelper<sizeof...(Types), 0>::Compare(Lhs, Rhs);
429 }
430
431 FORCEINLINE friend bool operator!=(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
432 {
433 return !(Lhs == Rhs);
434 }
435
436 FORCEINLINE friend bool operator<(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
437 {
438 return TLessThanHelper<sizeof...(Types)>::Do(Lhs, Rhs);
439 }
440
441 FORCEINLINE friend bool operator<=(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
442 {
443 return !(Rhs < Lhs);
444 }
445
446 FORCEINLINE friend bool operator>(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
447 {
448 return Rhs < Lhs;
449 }
450
451 FORCEINLINE friend bool operator>=(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
452 {
453 return !(Lhs < Rhs);
454 }
455 };
456
457 #ifdef _MSC_VER
458
459 // Not strictly necessary, but some VC versions give a 'syntax error: <fake-expression>' error
460 // for empty tuples.
461 template <>
462 struct TTupleImpl<TIntegerSequence<uint32>>
463 {
464 explicit TTupleImpl()
465 {
466 }
467
468 // Doesn't matter what these return, or even have a function body, but they need to be declared
469 template <uint32 Index> FORCEINLINE const int32& Get() const;
470 template <uint32 Index> FORCEINLINE int32& Get();
471
472 template <typename FuncType, typename... ArgTypes>
473 #if USE_TUPLE_AUTO_RETURN_TYPES
474 decltype(auto) ApplyAfter(FuncType&& Func, ArgTypes&&... Args) const
475 #else
476 auto ApplyAfter(FuncType&& Func, ArgTypes&&... Args) const -> decltype(Func(Forward<ArgTypes>(Args)...))
477 #endif
478 {
479 return Func(Forward<ArgTypes>(Args)...);
480 }
481
482 template <typename FuncType, typename... ArgTypes>
483 #if USE_TUPLE_AUTO_RETURN_TYPES
484 decltype(auto) ApplyBefore(FuncType&& Func, ArgTypes&&... Args) const
485 #else
486 auto ApplyBefore(FuncType&& Func, ArgTypes&&... Args) const -> decltype(Func(Forward<ArgTypes>(Args)...))
487 #endif
488 {
489 return Func(Forward<ArgTypes>(Args)...);
490 }
491
492 FORCEINLINE friend bool operator==(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
493 {
494 return true;
495 }
496
497 FORCEINLINE friend bool operator!=(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
498 {
499 return false;
500 }
501
502 FORCEINLINE friend bool operator<(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
503 {
504 return false;
505 }
506
507 FORCEINLINE friend bool operator<=(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
508 {
509 return true;
510 }
511
512 FORCEINLINE friend bool operator>(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
513 {
514 return false;
515 }
516
517 FORCEINLINE friend bool operator>=(const TTupleImpl& Lhs, const TTupleImpl& Rhs)
518 {
519 return true;
520 }
521 };
522
523 #endif
524
525 template <typename IntegerSequence>
526 struct TTransformTuple_Impl;
527
528 template <uint32... Indices>
529 struct TTransformTuple_Impl<TIntegerSequence<uint32, Indices...>>
530 {
531 template <typename TupleType, typename FuncType>
532 #if USE_TUPLE_AUTO_RETURN_TYPES
533 static decltype(auto) Do(TupleType&& Tuple, FuncType Func)
534 #else
535 static auto Do(TupleType&& Tuple, FuncType Func) -> decltype(MakeTuple(Func(Forward<TupleType>(Tuple).template Get<Indices>())...))
536 #endif
537 {
538 return MakeTuple(Func(Forward<TupleType>(Tuple).template Get<Indices>())...);
539 }
540 };
541
542 template <typename IntegerSequence>
543 struct TVisitTupleElements_Impl;
544
545 template <uint32... Indices>
546 struct TVisitTupleElements_Impl<TIntegerSequence<uint32, Indices...>>
547 {
548 template <typename TupleType, typename FuncType>
549 static void Do(TupleType&& Tuple, FuncType Func)
550 {
551 // This should be implemented with a fold expression when our compilers support it
552 int Temp[] = { 0, (Func(Tuple.template Get<Indices>()), 0)... };
553 (void)Temp;
554 }
555 };
556
557
558 template <typename TupleType>
559 struct TCVTupleArity;
560
561 template <typename... Types>
562 struct TCVTupleArity<const volatile TTuple<Types...>>
563 {
564 enum { Value = sizeof...(Types) };
565 };
566}
567
568template <typename... Types>
569struct TTuple : UE4Tuple_Private::TTupleImpl<TMakeIntegerSequence<uint32, sizeof...(Types)>, Types...>
570{
571private:
572 typedef UE4Tuple_Private::TTupleImpl<TMakeIntegerSequence<uint32, sizeof...(Types)>, Types...> Super;
573
574public:
575 template <
576 typename... ArgTypes,
577 typename = typename TEnableIf<
578 TAndValue<
579 sizeof...(ArgTypes) == sizeof...(Types) && sizeof...(ArgTypes) != 0,
580 TOrValue<
581 sizeof...(ArgTypes) != 1,
582 TNot<UE4Tuple_Private::TDecayedFrontOfParameterPackIsSameType<TTuple, ArgTypes...>>
583 >
584 >::Value
585 >::Type
586 >
587 explicit TTuple(ArgTypes&&... Args)
588 : Super(Forward<ArgTypes>(Args)...)
589 {
590 // This constructor is disabled for TTuple and zero parameters because VC is incorrectly instantiating it as a move/copy/default constructor.
591 }
592
593 #if TUPLES_USE_DEFAULTED_FUNCTIONS
594
595 TTuple() = default;
596 TTuple(TTuple&&) = default;
597 TTuple(const TTuple&) = default;
598 TTuple& operator=(TTuple&&) = default;
599 TTuple& operator=(const TTuple&) = default;
600
601 #else
602
603 TTuple()
604 {
605 }
606
607 TTuple(TTuple&& Other)
608 : Super(MoveTemp(*(Super*)&Other))
609 {
610 }
611
612 TTuple(const TTuple& Other)
613 : Super(*(const Super*)&Other)
614 {
615 }
616
617 TTuple& operator=(TTuple&& Other)
618 {
619 *(Super*)this = MoveTemp(*(Super*)&Other);
620 return *this;
621 }
622
623 TTuple& operator=(const TTuple& Other)
624 {
625 *(Super*)this = *(const Super*)&Other;
626 return *this;
627 }
628
629 #endif
630};
631
632
633/**
634 * Traits class which calculates the number of elements in a tuple.
635 */
636template <typename TupleType>
637struct TTupleArity : UE4Tuple_Private::TCVTupleArity<const volatile TupleType>
638{
639};
640
641
642/**
643 * Makes a TTuple from some arguments. The type of the TTuple elements are the decayed versions of the arguments.
644 *
645 * @param Args The arguments used to construct the tuple.
646 * @return A tuple containing a copy of the arguments.
647 *
648 * Example:
649 *
650 * void Func(const int32 A, FString&& B)
651 * {
652 * // Equivalent to:
653 * // TTuple<int32, const TCHAR*, FString> MyTuple(A, TEXT("Hello"), MoveTemp(B));
654 * auto MyTuple = MakeTuple(A, TEXT("Hello"), MoveTemp(B));
655 * }
656 */
657template <typename... Types>
658TTuple<typename TDecay<Types>::Type...> MakeTuple(Types&&... Args)
659{
660 return TTuple<typename TDecay<Types>::Type...>(Forward<Types>(Args)...);
661}
662
663
664/**
665 * Creates a new TTuple by applying a functor to each of the elements.
666 *
667 * @param Tuple The tuple to apply the functor to.
668 * @param Func The functor to apply.
669 *
670 * @return A new tuple of the transformed elements.
671 *
672 * Example:
673 *
674 * float Overloaded(int32 Arg);
675 * char Overloaded(const TCHAR* Arg);
676 * const TCHAR* Overloaded(const FString& Arg);
677 *
678 * void Func(const TTuple<int32, const TCHAR*, FString>& MyTuple)
679 * {
680 * // Equivalent to:
681 * // TTuple<float, char, const TCHAR*> TransformedTuple(Overloaded(MyTuple.Get<0>()), Overloaded(MyTuple.Get<1>()), Overloaded(MyTuple.Get<2>())));
682 * auto TransformedTuple = TransformTuple(MyTuple, [](const auto& Arg) { return Overloaded(Arg); });
683 * }
684 */
685template <typename FuncType, typename... Types>
686#if USE_TUPLE_AUTO_RETURN_TYPES
687 FORCEINLINE decltype(auto) TransformTuple(TTuple<Types...>&& Tuple, FuncType Func)
688#else
689 FORCEINLINE auto TransformTuple(TTuple<Types...>&& Tuple, FuncType Func) -> decltype(UE4Tuple_Private::TTransformTuple_Impl<TMakeIntegerSequence<uint32, sizeof...(Types)>>::Do(MoveTemp(Tuple), MoveTemp(Func)))
690#endif
691{
692 return UE4Tuple_Private::TTransformTuple_Impl<TMakeIntegerSequence<uint32, sizeof...(Types)>>::Do(MoveTemp(Tuple), MoveTemp(Func));
693}
694
695template <typename FuncType, typename... Types>
696#if USE_TUPLE_AUTO_RETURN_TYPES
697 FORCEINLINE decltype(auto) TransformTuple(const TTuple<Types...>& Tuple, FuncType Func)
698#else
699 FORCEINLINE auto TransformTuple(const TTuple<Types...>& Tuple, FuncType Func) -> decltype(UE4Tuple_Private::TTransformTuple_Impl<TMakeIntegerSequence<uint32, sizeof...(Types)>>::Do(Tuple, MoveTemp(Func)))
700#endif
701{
702 return UE4Tuple_Private::TTransformTuple_Impl<TMakeIntegerSequence<uint32, sizeof...(Types)>>::Do(Tuple, MoveTemp(Func));
703}
704
705
706/**
707 * Visits each element in the tuple in turn and applies the supplied functor to it.
708 *
709 * @param Tuple The tuple to apply the functor to.
710 * @param Func The functor to apply.
711 */
712template <typename TupleType, typename FuncType>
713FORCEINLINE void VisitTupleElements(TupleType& Tuple, FuncType Func)
714{
715 UE4Tuple_Private::TVisitTupleElements_Impl<TMakeIntegerSequence<uint32, TTupleArity<TupleType>::Value>>::Do(Tuple, MoveTemp(Func));
716}
717