feat(templates): add TTuple and the corresponding testing
This commit is contained in:
parent
fd0bebd7be
commit
d8a4908a88
@ -21,6 +21,7 @@ void TestTemplates()
|
||||
TestOptional();
|
||||
TestVariant();
|
||||
TestAny();
|
||||
TestTuple();
|
||||
TestMiscTemplates();
|
||||
}
|
||||
|
||||
@ -524,6 +525,381 @@ void TestAny()
|
||||
}
|
||||
}
|
||||
|
||||
void TestTuple()
|
||||
{
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< int, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const int, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< volatile int, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const volatile int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< int, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const int, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< volatile int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const volatile int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< int, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< volatile int, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const volatile int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< volatile int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const volatile int, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< int, char>&&>().GetValue<0>()), int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const int, char>&&>().GetValue<0>()), const int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< volatile int, char>&&>().GetValue<0>()), volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const volatile int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< int, char>&&>().GetValue<0>()), const int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const int, char>&&>().GetValue<0>()), const int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< volatile int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const volatile int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< int, char>&&>().GetValue<0>()), volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< volatile int, char>&&>().GetValue<0>()), volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const volatile int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< volatile int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const volatile int, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< int&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const int&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< volatile int&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const volatile int&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< int&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const int&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< volatile int&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const volatile int&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< int&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const int&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< volatile int&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const volatile int&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< int&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const int&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< volatile int&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const volatile int&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< int&, char>&&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const int&, char>&&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< volatile int&, char>&&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const volatile int&, char>&&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< int&, char>&&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const int&, char>&&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< volatile int&, char>&&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const volatile int&, char>&&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< int&, char>&&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const int&, char>&&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< volatile int&, char>&&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const volatile int&, char>&&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< int&, char>&&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const int&, char>&&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< volatile int&, char>&&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const volatile int&, char>&&>().GetValue<0>()), const volatile int&>::Value));
|
||||
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< int&&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const int&&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< volatile int&&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const volatile int&&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< int&&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const int&&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< volatile int&&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const volatile int&&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< int&&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const int&&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< volatile int&&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const volatile int&&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< int&&, char>&>().GetValue<0>()), int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const int&&, char>&>().GetValue<0>()), const int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< volatile int&&, char>&>().GetValue<0>()), volatile int&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const volatile int&&, char>&>().GetValue<0>()), const volatile int&>::Value));
|
||||
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< int&&, char>&&>().GetValue<0>()), int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const int&&, char>&&>().GetValue<0>()), const int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple< volatile int&&, char>&&>().GetValue<0>()), volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< TTuple<const volatile int&&, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< int&&, char>&&>().GetValue<0>()), int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const int&&, char>&&>().GetValue<0>()), const int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple< volatile int&&, char>&&>().GetValue<0>()), volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const TTuple<const volatile int&&, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< int&&, char>&&>().GetValue<0>()), int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const int&&, char>&&>().GetValue<0>()), const int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple< volatile int&&, char>&&>().GetValue<0>()), volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal< volatile TTuple<const volatile int&&, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< int&&, char>&&>().GetValue<0>()), int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const int&&, char>&&>().GetValue<0>()), const int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple< volatile int&&, char>&&>().GetValue<0>()), volatile int&&>::Value));
|
||||
always_check((TIsSame<decltype(DeclVal<const volatile TTuple<const volatile int&&, char>&&>().GetValue<0>()), const volatile int&&>::Value));
|
||||
|
||||
always_check((TIsSame<TTupleElementType<0, TTuple<double, float&, char&&>>::Type, double>::Value));
|
||||
always_check((TIsSame<TTupleElementType<1, TTuple<double, float&, char&&>>::Type, float&>::Value));
|
||||
always_check((TIsSame<TTupleElementType<2, TTuple<double, float&, char&&>>::Type, char&&>::Value));
|
||||
always_check((TIsSame<TTupleElementType<0, const TTuple<double, float&, char&&>>::Type, const double>::Value));
|
||||
always_check((TIsSame<TTupleElementType<1, const TTuple<double, float&, char&&>>::Type, const float&>::Value));
|
||||
always_check((TIsSame<TTupleElementType<2, const TTuple<double, float&, char&&>>::Type, const char&&>::Value));
|
||||
always_check((TIsSame<TTupleElementType<0, volatile TTuple<double, float&, char&&>>::Type, volatile double>::Value));
|
||||
always_check((TIsSame<TTupleElementType<1, volatile TTuple<double, float&, char&&>>::Type, volatile float&>::Value));
|
||||
always_check((TIsSame<TTupleElementType<2, volatile TTuple<double, float&, char&&>>::Type, volatile char&&>::Value));
|
||||
always_check((TIsSame<TTupleElementType<0, const volatile TTuple<double, float&, char&&>>::Type, const volatile double>::Value));
|
||||
always_check((TIsSame<TTupleElementType<1, const volatile TTuple<double, float&, char&&>>::Type, const volatile float&>::Value));
|
||||
always_check((TIsSame<TTupleElementType<2, const volatile TTuple<double, float&, char&&>>::Type, const volatile char&&>::Value));
|
||||
|
||||
always_check((TTupleElementIndex<double, TTuple<double, float&, char&&>>::Value == 0));
|
||||
always_check((TTupleElementIndex<float&, TTuple<double, float&, char&&>>::Value == 1));
|
||||
always_check((TTupleElementIndex<char&&, TTuple<double, float&, char&&>>::Value == 2));
|
||||
always_check((TTupleElementIndex<double, const TTuple<double, float&, char&&>>::Value == 0));
|
||||
always_check((TTupleElementIndex<float&, const TTuple<double, float&, char&&>>::Value == 1));
|
||||
always_check((TTupleElementIndex<char&&, const TTuple<double, float&, char&&>>::Value == 2));
|
||||
always_check((TTupleElementIndex<double, volatile TTuple<double, float&, char&&>>::Value == 0));
|
||||
always_check((TTupleElementIndex<float&, volatile TTuple<double, float&, char&&>>::Value == 1));
|
||||
always_check((TTupleElementIndex<char&&, volatile TTuple<double, float&, char&&>>::Value == 2));
|
||||
always_check((TTupleElementIndex<double, const volatile TTuple<double, float&, char&&>>::Value == 0));
|
||||
always_check((TTupleElementIndex<float&, const volatile TTuple<double, float&, char&&>>::Value == 1));
|
||||
always_check((TTupleElementIndex<char&&, const volatile TTuple<double, float&, char&&>>::Value == 2));
|
||||
|
||||
always_check((TTupleElementIndex<int, TTuple<double, float&, char&&>>::Value == INDEX_NONE));
|
||||
|
||||
// always_check((TIsSame<TTupleElementType<0, int>::Type, double>::Value));
|
||||
|
||||
// always_check((TTupleElementIndex<int, int>::Value == 0));
|
||||
|
||||
// always_check((TIsSame<TTupleElementType<4, TTuple<double, float&, char&&>>::Type, double>::Value));
|
||||
|
||||
{
|
||||
using Type = TTuple<int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
|
||||
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64,
|
||||
int8, uint8, int16, uint16, int32, uint32, int64, uint64, int8, uint8, int16, uint16, int32, uint32, int64, uint64>;
|
||||
|
||||
Type Temp;
|
||||
|
||||
Temp.First = 0;
|
||||
Temp.Second = 0;
|
||||
Temp.Third = 0;
|
||||
Temp.Fourth = 0;
|
||||
Temp.Fifth = 0;
|
||||
Temp.Sixth = 0;
|
||||
Temp.Seventh = 0;
|
||||
Temp.Eighth = 0;
|
||||
Temp.Ninth = 0;
|
||||
Temp.Tenth = 0;
|
||||
Temp.Eleventh = 0;
|
||||
Temp.Twelfth = 0;
|
||||
Temp.Thirteenth = 0;
|
||||
Temp.Fourteenth = 0;
|
||||
Temp.Fifteenth = 0;
|
||||
Temp.Sixteenth = 0;
|
||||
|
||||
always_check(TIsDefaultConstructible<Type>::Value);
|
||||
always_check(TIsTriviallyDefaultConstructible<Type>::Value);
|
||||
always_check(TIsConstructible<Type>::Value);
|
||||
always_check(TIsTriviallyConstructible<Type>::Value);
|
||||
always_check(TIsCopyConstructible<Type>::Value);
|
||||
always_check(TIsTriviallyCopyConstructible<Type>::Value);
|
||||
always_check(TIsMoveConstructible<Type>::Value);
|
||||
always_check(TIsTriviallyMoveConstructible<Type>::Value);
|
||||
always_check(TIsCopyAssignable<Type>::Value);
|
||||
always_check(TIsTriviallyCopyAssignable<Type>::Value);
|
||||
always_check(TIsMoveAssignable<Type>::Value);
|
||||
always_check(TIsTriviallyMoveAssignable<Type>::Value);
|
||||
always_check(TIsDestructible<Type>::Value);
|
||||
always_check(TIsTriviallyDestructible<Type>::Value);
|
||||
}
|
||||
|
||||
{
|
||||
TTuple<int32, int32> TempA(0, 1);
|
||||
TTuple<int32, int32> TempB = { 0, 1 };
|
||||
TTuple<int64, double> TempC = TempB;
|
||||
TTuple<int64, double> TempD = MoveTemp(TempB);
|
||||
TTuple<double, int64> TempE, TempF;
|
||||
TempE = TempC;
|
||||
TempF = MoveTemp(TempD);
|
||||
always_check(TempC.GetValue<0>() == 0);
|
||||
always_check(TempC.GetValue<int64>() == 0);
|
||||
}
|
||||
|
||||
{
|
||||
TTuple TempA = MakeTuple(1, 2, 3);
|
||||
int32 TempB;
|
||||
Tie(Ignore, TempB, Ignore) = TempA;
|
||||
always_check(TempB == 2);
|
||||
TTuple TempC = ForwardAsTuple(TempB);
|
||||
TempC.GetValue<0>() = 4;
|
||||
always_check(TempB == 4);
|
||||
}
|
||||
|
||||
struct FTracker
|
||||
{
|
||||
int8 Flag;
|
||||
FTracker(int8 InFlag) : Flag(InFlag) { }
|
||||
FTracker(const FTracker& InValue) { Flag = InValue.Flag - 1; always_check(!Flag); }
|
||||
FTracker(FTracker&& InValue) { Flag = InValue.Flag + 1; always_check(!Flag); }
|
||||
FTracker& operator=(const FTracker& InValue) { Flag = InValue.Flag - 1; always_check(!Flag); return *this; }
|
||||
FTracker& operator=(FTracker&& InValue) { Flag = InValue.Flag + 1; always_check(!Flag); return *this; }
|
||||
};
|
||||
|
||||
{
|
||||
TTuple<int32, FTracker> TempA(404, -1);
|
||||
TTuple<double, FTracker> TempB(3.14, 1);
|
||||
TTuple<float, FTracker> TempC(1.42f, -1);
|
||||
TTuple<> TempD = { };
|
||||
auto TempE = TupleCat(MoveTemp(TempA), TempB, MoveTemp(TempC), MoveTemp(TempD));
|
||||
always_check(TempE.GetValue<int32>() == 404);
|
||||
always_check(TempE.GetValue<double>() == 3.14);
|
||||
always_check(TempE.GetValue<float>() == 1.42f);
|
||||
always_check((TIsSame<decltype(TempE), TTuple<int32, FTracker, double, FTracker, float, FTracker>>::Value));
|
||||
always_check((TIsSame<decltype(TempE), typename TTupleCatResult<TTuple<int32, FTracker>, TTuple<double, FTracker>, TTuple<float, FTracker>>::Type>::Value));
|
||||
}
|
||||
|
||||
{
|
||||
always_check(MakeTuple(10, 0.0) == MakeTuple(10.0, 0));
|
||||
always_check(MakeTuple(10, 0.0) != MakeTuple(10.1, 0));
|
||||
|
||||
always_check((MakeTuple(10, 0.0) <=> MakeTuple(10.0, 0)) == 0);
|
||||
always_check((MakeTuple(10, 1.0) <=> MakeTuple(10.0, 0)) > 0);
|
||||
always_check((MakeTuple(10, 0.0) <=> MakeTuple(10.1, 0)) < 0);
|
||||
always_check((MakeTuple(10, 0.0) <=> MakeTuple(10.1, 0)) != 0);
|
||||
}
|
||||
|
||||
{
|
||||
double TempB = 0.0;
|
||||
TTuple<int32, double&> TempC(10, TempB);
|
||||
int16 TempD = 10;
|
||||
FTracker TempE(0);
|
||||
TTuple<int16&, FTracker&&> TempF(TempD, MoveTemp(TempE));
|
||||
auto TempG = TupleCat(TempC, TempF);
|
||||
TempG.GetValue<1>() = 3.14;
|
||||
always_check(TempB == 3.14);
|
||||
always_check(TempG.GetValue<0>() == 10);
|
||||
always_check(TempG.GetValue<2>() == 10);
|
||||
always_check((TIsSame<decltype(TempG), TTuple<int32, double&, int16&, FTracker&&>>::Value));
|
||||
always_check((TIsSame<decltype(TempG), typename TTupleCatResult<TTuple<int32, double&>, TTuple<int16&, FTracker&&>>::Type>::Value));
|
||||
}
|
||||
|
||||
{
|
||||
int32 TempO = 15;
|
||||
TTuple<int32&&, const int64> TempA = { MoveTemp(TempO), 514 };
|
||||
|
||||
TempA.Apply(
|
||||
[]<typename T, typename U> (T&& A, U&& B)
|
||||
{
|
||||
always_check(A == 15);
|
||||
always_check(B == 514);
|
||||
always_check((TIsSame<T&&, int32&>::Value));
|
||||
always_check((TIsSame<U&&, const int64&>::Value));
|
||||
}
|
||||
);
|
||||
|
||||
MoveTemp(TempA).Apply(
|
||||
[]<typename T, typename U> (T&& A, U&& B)
|
||||
{
|
||||
always_check(A == 15);
|
||||
always_check(B == 514);
|
||||
always_check((TIsSame<T&&, int32&&>::Value));
|
||||
always_check((TIsSame<U&&, const int64&&>::Value));
|
||||
}
|
||||
);
|
||||
|
||||
TempA.ApplyAfter(
|
||||
[]<typename T, typename U, typename V> (T&& A, U&& B, V&&C)
|
||||
{
|
||||
always_check(A == '-');
|
||||
always_check(B == 15);
|
||||
always_check(C == 514);
|
||||
always_check((TIsSame<T&&, char&&>::Value));
|
||||
always_check((TIsSame<U&&, int32&>::Value));
|
||||
always_check((TIsSame<V&&, const int64&>::Value));
|
||||
},
|
||||
'-'
|
||||
);
|
||||
|
||||
MoveTemp(TempA).ApplyAfter(
|
||||
[]<typename T, typename U, typename V> (T&& A, U&& B, V&&C)
|
||||
{
|
||||
always_check(A == '-');
|
||||
always_check(B == 15);
|
||||
always_check(C == 514);
|
||||
always_check((TIsSame<T&&, char&&>::Value));
|
||||
always_check((TIsSame<U&&, int32&&>::Value));
|
||||
always_check((TIsSame<V&&, const int64&&>::Value));
|
||||
},
|
||||
'-'
|
||||
);
|
||||
|
||||
TempA.ApplyBefore(
|
||||
[]<typename T, typename U, typename V> (T&& A, U&& B, V&&C)
|
||||
{
|
||||
always_check(A == 15);
|
||||
always_check(B == 514);
|
||||
always_check(C == '-');
|
||||
always_check((TIsSame<T&&, int32&>::Value));
|
||||
always_check((TIsSame<U&&, const int64&>::Value));
|
||||
always_check((TIsSame<V&&, char&&>::Value));
|
||||
},
|
||||
'-'
|
||||
);
|
||||
|
||||
MoveTemp(TempA).ApplyBefore(
|
||||
[]<typename T, typename U, typename V> (T&& A, U&& B, V&&C)
|
||||
{
|
||||
always_check(A == 15);
|
||||
always_check(B == 514);
|
||||
always_check(C == '-');
|
||||
always_check((TIsSame<T&&, int32&&>::Value));
|
||||
always_check((TIsSame<U&&, const int64&&>::Value));
|
||||
always_check((TIsSame<V&&, char&&>::Value));
|
||||
},
|
||||
'-'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
TTuple<int32, char> TempA = { 1, 'A' };
|
||||
TTuple<int32, char> TempB = TempA.Transform([](auto&& InValue) { return InValue + 1; });
|
||||
|
||||
VisitTuple(
|
||||
[]<typename T> (T&& A)
|
||||
{
|
||||
if constexpr (TIsSame<T&&, int32&>::Value) always_check(A == 2);
|
||||
else if constexpr (TIsSame<T&&, char&>::Value) always_check(A == 'B');
|
||||
else always_check_no_entry();
|
||||
},
|
||||
TempB
|
||||
);
|
||||
|
||||
VisitTuple([](auto&& A) { A++; }, TempB);
|
||||
|
||||
VisitTuple(
|
||||
[]<typename T> (T&& A)
|
||||
{
|
||||
if constexpr (TIsSame<T&&, int32&>::Value) always_check(A == 3);
|
||||
else if constexpr (TIsSame<T&&, char&>::Value) always_check(A == 'C');
|
||||
else always_check_no_entry();
|
||||
},
|
||||
TempB
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
struct FTest
|
||||
{
|
||||
FTest(int32 A, float B, char C)
|
||||
{
|
||||
always_check(A == 1);
|
||||
always_check(B == 1.2f);
|
||||
always_check(C == 'A');
|
||||
}
|
||||
};
|
||||
MakeTuple(1, 1.2f, 'A').Construct<FTest>();
|
||||
}
|
||||
|
||||
{
|
||||
auto Func = [] { return MakeTuple(1, 2.3, 'A'); };
|
||||
auto [A, B, C] = Func();
|
||||
always_check(A == 1);
|
||||
always_check(B == 2.3);
|
||||
always_check(C == 'A');
|
||||
always_check((TIsSame<decltype(C), char>::Value));
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_UNNAMED_BEGIN
|
||||
|
||||
template <typename T>
|
||||
|
@ -10,3 +10,4 @@
|
||||
#include "Templates/Variant.h"
|
||||
#include "Templates/Any.h"
|
||||
#include "Templates/IntegerSequence.h"
|
||||
#include "Templates/Tuple.h"
|
||||
|
621
Redcraft.Utility/Source/Public/Templates/Tuple.h
Normal file
621
Redcraft.Utility/Source/Public/Templates/Tuple.h
Normal file
@ -0,0 +1,621 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Templates/Utility.h"
|
||||
#include "TypeTraits/TypeTraits.h"
|
||||
#include "Templates/IntegerSequence.h"
|
||||
#include "Templates/ReferenceWrapper.h"
|
||||
#include "Templates/Invoke.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
#define RS_TUPLE_ELEMENT_STATIC_ALIAS 1
|
||||
|
||||
template <typename... Types>
|
||||
struct TTuple;
|
||||
|
||||
NAMESPACE_PRIVATE_BEGIN
|
||||
|
||||
struct FForwardingConstructor { explicit FForwardingConstructor() = default; };
|
||||
struct FOtherTupleConstructor { explicit FOtherTupleConstructor() = default; };
|
||||
|
||||
inline constexpr FForwardingConstructor ForwardingConstructor{ };
|
||||
inline constexpr FOtherTupleConstructor OtherTupleConstructor{ };
|
||||
|
||||
template <typename T, typename... Types>
|
||||
struct TTupleElementIndex;
|
||||
|
||||
template <typename T, typename U, typename... Types>
|
||||
struct TTupleElementIndex<T, U, Types...>
|
||||
: TConstant<size_t, TIsSame<T, U>::Value ? 0 : (TTupleElementIndex<T, Types...>::Value == INDEX_NONE
|
||||
? INDEX_NONE : TTupleElementIndex<T, Types...>::Value + 1)>
|
||||
{ };
|
||||
|
||||
template <typename T>
|
||||
struct TTupleElementIndex<T> : TConstant<size_t, INDEX_NONE> { };
|
||||
|
||||
template <size_t I, typename... Types>
|
||||
struct TTupleElementType;
|
||||
|
||||
template <size_t I, typename T, typename... Types>
|
||||
struct TTupleElementType<I, T, Types...>
|
||||
{
|
||||
static_assert(I < sizeof...(Types) + 1, "Tuple type index is invalid");
|
||||
using Type = TTupleElementType<I - 1, Types...>::Type;
|
||||
};
|
||||
|
||||
template <typename T, typename... Types>
|
||||
struct TTupleElementType<0, T, Types...> { using Type = T; };
|
||||
|
||||
template <>
|
||||
struct TTupleElementType<0> { };
|
||||
|
||||
template <typename T, size_t Index>
|
||||
struct TTupleElement
|
||||
{
|
||||
using ValueType = T;
|
||||
ValueType Value;
|
||||
|
||||
template <typename Type>
|
||||
constexpr TTupleElement(Type&& Arg)
|
||||
: Value(Forward<Type>(Arg))
|
||||
{ }
|
||||
|
||||
TTupleElement() = default;
|
||||
TTupleElement(TTupleElement&&) = default;
|
||||
TTupleElement(const TTupleElement&) = default;
|
||||
TTupleElement& operator=(TTupleElement&&) = default;
|
||||
TTupleElement& operator=(const TTupleElement&) = default;
|
||||
|
||||
constexpr T& GetValue() & { return static_cast< T& >(Value); }
|
||||
constexpr const T& GetValue() const & { return static_cast<const T& >(Value); }
|
||||
constexpr volatile T& GetValue() volatile& { return static_cast< volatile T& >(Value); }
|
||||
constexpr const volatile T& GetValue() const volatile& { return static_cast<const volatile T& >(Value); }
|
||||
constexpr T&& GetValue() && { return static_cast< T&&>(Value); }
|
||||
constexpr const T&& GetValue() const && { return static_cast<const T&&>(Value); }
|
||||
constexpr volatile T&& GetValue() volatile&& { return static_cast< volatile T&&>(Value); }
|
||||
constexpr const volatile T&& GetValue() const volatile&& { return static_cast<const volatile T&&>(Value); }
|
||||
};
|
||||
|
||||
#if RS_TUPLE_ELEMENT_STATIC_ALIAS
|
||||
|
||||
#define DEFINE_TTupleElement(Index, Name) \
|
||||
template <typename T> \
|
||||
struct TTupleElement<T, Index> \
|
||||
{ \
|
||||
using Name##Type = T; \
|
||||
Name##Type Name; \
|
||||
\
|
||||
template <typename Type> \
|
||||
constexpr TTupleElement(Type&& Arg) \
|
||||
: Name(Forward<Type>(Arg)) \
|
||||
{ } \
|
||||
\
|
||||
TTupleElement() = default; \
|
||||
TTupleElement(TTupleElement&&) = default; \
|
||||
TTupleElement(const TTupleElement&) = default; \
|
||||
TTupleElement& operator=(TTupleElement&&) = default; \
|
||||
TTupleElement& operator=(const TTupleElement&) = default; \
|
||||
\
|
||||
constexpr T& GetValue() & { return static_cast< T& >(Name); } \
|
||||
constexpr const T& GetValue() const & { return static_cast<const T& >(Name); } \
|
||||
constexpr volatile T& GetValue() volatile& { return static_cast< volatile T& >(Name); } \
|
||||
constexpr const volatile T& GetValue() const volatile& { return static_cast<const volatile T& >(Name); } \
|
||||
constexpr T&& GetValue() && { return static_cast< T&&>(Name); } \
|
||||
constexpr const T&& GetValue() const && { return static_cast<const T&&>(Name); } \
|
||||
constexpr volatile T&& GetValue() volatile&& { return static_cast< volatile T&&>(Name); } \
|
||||
constexpr const volatile T&& GetValue() const volatile&& { return static_cast<const volatile T&&>(Name); } \
|
||||
}
|
||||
|
||||
DEFINE_TTupleElement(0x0, First);
|
||||
DEFINE_TTupleElement(0x1, Second);
|
||||
DEFINE_TTupleElement(0x2, Third);
|
||||
DEFINE_TTupleElement(0x3, Fourth);
|
||||
DEFINE_TTupleElement(0x4, Fifth);
|
||||
DEFINE_TTupleElement(0x5, Sixth);
|
||||
DEFINE_TTupleElement(0x6, Seventh);
|
||||
DEFINE_TTupleElement(0x7, Eighth);
|
||||
DEFINE_TTupleElement(0x8, Ninth);
|
||||
DEFINE_TTupleElement(0x9, Tenth);
|
||||
DEFINE_TTupleElement(0xA, Eleventh);
|
||||
DEFINE_TTupleElement(0xB, Twelfth);
|
||||
DEFINE_TTupleElement(0xC, Thirteenth);
|
||||
DEFINE_TTupleElement(0xD, Fourteenth);
|
||||
DEFINE_TTupleElement(0xE, Fifteenth);
|
||||
DEFINE_TTupleElement(0xF, Sixteenth);
|
||||
|
||||
#undef DEFINE_TTupleElement
|
||||
|
||||
#endif
|
||||
|
||||
template <typename... Types>
|
||||
constexpr TTuple<typename TUnwrapRefDecay<Types>::Type...> MakeTupleImpl(Types&&... Args)
|
||||
{
|
||||
return TTuple<typename TUnwrapRefDecay<Types>::Type...>(Forward<Types>(Args)...);
|
||||
}
|
||||
|
||||
template <typename Indices, typename... Types>
|
||||
struct TTupleImpl;
|
||||
|
||||
template <size_t... Indices, typename... Types>
|
||||
struct TTupleImpl<TIndexSequence<Indices...>, Types...> : TTupleElement<Types, Indices>...
|
||||
{
|
||||
protected:
|
||||
|
||||
static constexpr size_t ElementSize = sizeof...(Types);
|
||||
|
||||
template <size_t I> struct TElementType : NAMESPACE_PRIVATE::TTupleElementType<I, Types...> { };
|
||||
template <typename T> struct TElementIndex : NAMESPACE_PRIVATE::TTupleElementIndex<T, Types...> { };
|
||||
|
||||
TTupleImpl() = default;
|
||||
|
||||
template <typename... ArgTypes>
|
||||
explicit TTupleImpl(FForwardingConstructor, ArgTypes&&... Args)
|
||||
: TTupleElement<Types, Indices>(Forward<ArgTypes>(Args))...
|
||||
{ }
|
||||
|
||||
template <typename TupleType>
|
||||
explicit TTupleImpl(FOtherTupleConstructor, TupleType&& InValue)
|
||||
: TTupleElement<Types, Indices>(Forward<TupleType>(InValue).template GetValue<Indices>())...
|
||||
{ }
|
||||
|
||||
TTupleImpl(const TTupleImpl&) = default;
|
||||
TTupleImpl(TTupleImpl&&) = default;
|
||||
|
||||
template <typename LHSTupleType, typename RHSTupleType>
|
||||
static constexpr void Assign(LHSTupleType& LHS, RHSTupleType&& RHS)
|
||||
{
|
||||
static_assert(ElementSize == LHS.ElementSize && LHS.ElementSize == RHS.ElementSize, "Cannot assign tuple from different size");
|
||||
((LHS.template GetValue<Indices>() = Forward<RHSTupleType>(RHS).template GetValue<Indices>()), ...);
|
||||
}
|
||||
|
||||
TTupleImpl& operator=(const TTupleImpl&) = default;
|
||||
TTupleImpl& operator=(TTupleImpl&&) = default;
|
||||
|
||||
template <typename F, typename TTupleType>
|
||||
static constexpr auto Apply(F&& Func, TTupleType&& Arg)
|
||||
{
|
||||
return Invoke(Forward<F>(Func), Forward<TTupleType>(Arg).template GetValue<Indices>()...);
|
||||
}
|
||||
|
||||
template <typename F, typename TTupleType, typename... ArgTypes>
|
||||
static constexpr auto ApplyAfter(F&& Func, TTupleType&& Arg, ArgTypes&&... OtherArgs)
|
||||
{
|
||||
return Invoke(Forward<F>(Func), Forward<ArgTypes>(OtherArgs)..., Forward<TTupleType>(Arg).template GetValue<Indices>()...);
|
||||
}
|
||||
|
||||
template <typename F, typename TTupleType, typename... ArgTypes>
|
||||
static constexpr auto ApplyBefore(F&& Func, TTupleType&& Arg, ArgTypes&&... OtherArgs)
|
||||
{
|
||||
return Invoke(Forward<F>(Func), Forward<TTupleType>(Arg).template GetValue<Indices>()..., Forward<ArgTypes>(OtherArgs)...);
|
||||
}
|
||||
|
||||
template <typename F, typename TTupleType>
|
||||
static constexpr auto Transform(F&& Func, TTupleType&& Arg)
|
||||
{
|
||||
return MakeTupleImpl(Invoke(Forward<F>(Func), Forward<TTupleType>(Arg).template GetValue<Indices>())...);
|
||||
}
|
||||
|
||||
template <typename T, typename TTupleType>
|
||||
static constexpr T Construct(TTupleType&& Arg)
|
||||
{
|
||||
return T(Forward<TTupleType>(Arg).template GetValue<Indices>()...);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
NAMESPACE_PRIVATE_END
|
||||
|
||||
template <typename... Types>
|
||||
struct TTuple : NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Types...>, Types...>
|
||||
{
|
||||
private:
|
||||
|
||||
using Super = NAMESPACE_PRIVATE::TTupleImpl<TIndexSequenceFor<Types...>, Types...>;
|
||||
|
||||
public:
|
||||
|
||||
static constexpr size_t ElementSize = Super::ElementSize;
|
||||
|
||||
template <size_t I> struct TElementType : Super::template TElementType<I> { };
|
||||
template <typename T> struct TElementIndex : Super::template TElementIndex<T> { };
|
||||
|
||||
TTuple() = default;
|
||||
|
||||
template <typename... ArgTypes> requires (ElementSize > 0) && (sizeof...(ArgTypes) == ElementSize)
|
||||
&& (true && ... && TIsConstructible<Types, ArgTypes&&>::Value)
|
||||
&& (true && ... && TIsConvertible<ArgTypes&&, Types>::Value)
|
||||
constexpr TTuple(ArgTypes&&... Args)
|
||||
: Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<ArgTypes>(Args)...)
|
||||
{ }
|
||||
|
||||
template <typename... ArgTypes> requires (ElementSize > 0) && (sizeof...(ArgTypes) == ElementSize)
|
||||
&& (true && ... && TIsConstructible<Types, ArgTypes&&>::Value)
|
||||
&& (!(true && ... && TIsConvertible<ArgTypes&&, Types>::Value))
|
||||
constexpr explicit TTuple(ArgTypes&&... Args)
|
||||
: Super(NAMESPACE_PRIVATE::ForwardingConstructor, Forward<ArgTypes>(Args)...)
|
||||
{ }
|
||||
|
||||
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == ElementSize)
|
||||
&& (true && ... && TIsConstructible<Types, const OtherTypes&>::Value)
|
||||
&& ((ElementSize != 1) || !(TIsConvertible<const TTuple<OtherTypes...>&, typename TElementType<0>::Type>::Value
|
||||
|| TIsConstructible<typename TElementType<0>::Type, const TTuple<OtherTypes...>&>::Value
|
||||
|| TIsSame<typename TElementType<0>::Type, typename TTuple<OtherTypes...>::template TElementType<0>::Type>::Value))
|
||||
&& (true && ... && TIsConvertible<OtherTypes&&, Types>::Value)
|
||||
constexpr TTuple(const TTuple<OtherTypes...>& InValue)
|
||||
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue)
|
||||
{ }
|
||||
|
||||
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == ElementSize)
|
||||
&& (true && ... && TIsConstructible<Types, const OtherTypes&>::Value)
|
||||
&& ((ElementSize != 1) || !(TIsConvertible<const TTuple<OtherTypes...>&, typename TElementType<0>::Type>::Value
|
||||
|| TIsConstructible<typename TElementType<0>::Type, const TTuple<OtherTypes...>&>::Value
|
||||
|| TIsSame<typename TElementType<0>::Type, typename TTuple<OtherTypes...>::template TElementType<0>::Type>::Value))
|
||||
&& (!(true && ... && TIsConvertible<OtherTypes&&, Types>::Value))
|
||||
constexpr explicit TTuple(const TTuple<OtherTypes...>& InValue)
|
||||
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, InValue)
|
||||
{ }
|
||||
|
||||
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == ElementSize)
|
||||
&& (true && ... && TIsConstructible<Types, OtherTypes&&>::Value)
|
||||
&& ((ElementSize != 1) || !(TIsConvertible<TTuple<OtherTypes...>&&, typename TElementType<0>::Type>::Value
|
||||
|| TIsConstructible<typename TElementType<0>::Type, TTuple<OtherTypes...>&&>::Value
|
||||
|| TIsSame<typename TElementType<0>::Type, typename TTuple<OtherTypes...>::template TElementType<0>::Type>::Value))
|
||||
&& (true && ... && TIsConvertible<OtherTypes&&, Types>::Value)
|
||||
constexpr TTuple(TTuple<OtherTypes...>&& InValue)
|
||||
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue))
|
||||
{ }
|
||||
|
||||
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == ElementSize)
|
||||
&& (true && ... && TIsConstructible<Types, OtherTypes&&>::Value)
|
||||
&& ((ElementSize != 1) || !(TIsConvertible<TTuple<OtherTypes...>&&, typename TElementType<0>::Type>::Value
|
||||
|| TIsConstructible<typename TElementType<0>::Type, TTuple<OtherTypes...>&&>::Value
|
||||
|| TIsSame<typename TElementType<0>::Type, typename TTuple<OtherTypes...>::template TElementType<0>::Type>::Value))
|
||||
&& (!(true && ... && TIsConvertible<OtherTypes&&, Types>::Value))
|
||||
constexpr explicit TTuple(TTuple<OtherTypes...>&& InValue)
|
||||
: Super(NAMESPACE_PRIVATE::OtherTupleConstructor, MoveTemp(InValue))
|
||||
{ }
|
||||
|
||||
TTuple(const TTuple&) = default;
|
||||
TTuple(TTuple&&) = default;
|
||||
|
||||
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == ElementSize)
|
||||
&& (true && ... && TIsAssignable<Types&, const OtherTypes&>::Value)
|
||||
constexpr TTuple& operator=(const TTuple<OtherTypes...>& InValue)
|
||||
{
|
||||
Super::Assign(*this, InValue);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... OtherTypes> requires (sizeof...(OtherTypes) == ElementSize)
|
||||
&& (true && ... && TIsAssignable<Types&, OtherTypes&&>::Value)
|
||||
constexpr TTuple& operator=(TTuple<OtherTypes...>&& InValue)
|
||||
{
|
||||
Super::Assign(*this, MoveTemp(InValue));
|
||||
return *this;
|
||||
}
|
||||
|
||||
TTuple& operator=(const TTuple&) = default;
|
||||
TTuple& operator=(TTuple&&) = default;
|
||||
|
||||
constexpr void* GetData() { return this; }
|
||||
constexpr const void* GetData() const { return this; }
|
||||
|
||||
template <size_t I> requires (I < ElementSize) constexpr TElementType<I>::Type& GetValue() & { return static_cast< NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>& >(*this).GetValue(); }
|
||||
template <size_t I> requires (I < ElementSize) constexpr const TElementType<I>::Type& GetValue() const & { return static_cast<const NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>& >(*this).GetValue(); }
|
||||
template <size_t I> requires (I < ElementSize) constexpr volatile TElementType<I>::Type& GetValue() volatile& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>& >(*this).GetValue(); }
|
||||
template <size_t I> requires (I < ElementSize) constexpr const volatile TElementType<I>::Type& GetValue() const volatile& { return static_cast<const volatile NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>& >(*this).GetValue(); }
|
||||
template <size_t I> requires (I < ElementSize) constexpr TElementType<I>::Type&& GetValue() && { return static_cast< NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>&&>(*this).GetValue(); }
|
||||
template <size_t I> requires (I < ElementSize) constexpr const TElementType<I>::Type&& GetValue() const && { return static_cast<const NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>&&>(*this).GetValue(); }
|
||||
template <size_t I> requires (I < ElementSize) constexpr volatile TElementType<I>::Type&& GetValue() volatile&& { return static_cast< volatile NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>&&>(*this).GetValue(); }
|
||||
template <size_t I> requires (I < ElementSize) constexpr const volatile TElementType<I>::Type&& GetValue() const volatile&& { return static_cast<const volatile NAMESPACE_PRIVATE::TTupleElement<typename TElementType<I>::Type, I>&&>(*this).GetValue(); }
|
||||
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr T& GetValue() & { return static_cast< TTuple& >(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr const T& GetValue() const & { return static_cast<const TTuple& >(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr volatile T& GetValue() volatile& { return static_cast< volatile TTuple& >(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr const volatile T& GetValue() const volatile& { return static_cast<const volatile TTuple& >(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr T&& GetValue() && { return static_cast< TTuple&&>(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr const T&& GetValue() const && { return static_cast<const TTuple&&>(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr volatile T&& GetValue() volatile&& { return static_cast< volatile TTuple&&>(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
template <typename T> requires (TElementIndex<T>::Value != INDEX_NONE) constexpr const volatile T&& GetValue() const volatile&& { return static_cast<const volatile TTuple&&>(*this).GetValue<TElementIndex<T>::Value>(); }
|
||||
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) & { return Super::Apply(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) const & { return Super::Apply(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) volatile& { return Super::Apply(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) const volatile& { return Super::Apply(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) && { return Super::Apply(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) const && { return Super::Apply(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) volatile&& { return Super::Apply(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
|
||||
template <typename F> requires TIsInvocable<F, Types...>::Value constexpr auto Apply(F&& Func) const volatile&& { return Super::Apply(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
|
||||
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) & { return Super::ApplyAfter(Forward<F>(Func), static_cast< TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const & { return Super::ApplyAfter(Forward<F>(Func), static_cast<const TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile& { return Super::ApplyAfter(Forward<F>(Func), static_cast< volatile TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile& { return Super::ApplyAfter(Forward<F>(Func), static_cast<const volatile TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) && { return Super::ApplyAfter(Forward<F>(Func), static_cast< TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const && { return Super::ApplyAfter(Forward<F>(Func), static_cast<const TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) volatile&& { return Super::ApplyAfter(Forward<F>(Func), static_cast< volatile TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, ArgTypes..., Types...>::Value constexpr auto ApplyAfter(F&& Func, ArgTypes&&... Args) const volatile&& { return Super::ApplyAfter(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) & { return Super::ApplyBefore(Forward<F>(Func), static_cast< TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const & { return Super::ApplyBefore(Forward<F>(Func), static_cast<const TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile& { return Super::ApplyBefore(Forward<F>(Func), static_cast< volatile TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile& { return Super::ApplyBefore(Forward<F>(Func), static_cast<const volatile TTuple& >(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) && { return Super::ApplyBefore(Forward<F>(Func), static_cast< TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const && { return Super::ApplyBefore(Forward<F>(Func), static_cast<const TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) volatile&& { return Super::ApplyBefore(Forward<F>(Func), static_cast< volatile TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
template <typename F, typename... ArgTypes> requires TIsInvocable<F, Types..., ArgTypes...>::Value constexpr auto ApplyBefore(F&& Func, ArgTypes&&... Args) const volatile&& { return Super::ApplyBefore(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this), Forward<ArgTypes>(Args)...); }
|
||||
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) & { return Super::Transform(Forward<F>(Func), static_cast< TTuple& >(*this)); }
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) const & { return Super::Transform(Forward<F>(Func), static_cast<const TTuple& >(*this)); }
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) volatile& { return Super::Transform(Forward<F>(Func), static_cast< volatile TTuple& >(*this)); }
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) const volatile& { return Super::Transform(Forward<F>(Func), static_cast<const volatile TTuple& >(*this)); }
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) && { return Super::Transform(Forward<F>(Func), static_cast< TTuple&&>(*this)); }
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) const && { return Super::Transform(Forward<F>(Func), static_cast<const TTuple&&>(*this)); }
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) volatile&& { return Super::Transform(Forward<F>(Func), static_cast< volatile TTuple&&>(*this)); }
|
||||
template <typename F> requires (true && ... && (TIsInvocable<F, Types>::Value && !TIsSame<void, typename TInvokeResult<F, Types>::Type>::Value)) constexpr auto Transform(F&& Func) const volatile&& { return Super::Transform(Forward<F>(Func), static_cast<const volatile TTuple&&>(*this)); }
|
||||
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() & { return Super::template Construct<T>(static_cast< TTuple& >(*this)); }
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() const & { return Super::template Construct<T>(static_cast<const TTuple& >(*this)); }
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() volatile& { return Super::template Construct<T>(static_cast< volatile TTuple& >(*this)); }
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() const volatile& { return Super::template Construct<T>(static_cast<const volatile TTuple& >(*this)); }
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() && { return Super::template Construct<T>(static_cast< TTuple&&>(*this)); }
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() const && { return Super::template Construct<T>(static_cast<const TTuple&&>(*this)); }
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() volatile&& { return Super::template Construct<T>(static_cast< volatile TTuple&&>(*this)); }
|
||||
template <typename T> requires TIsConstructible<T, Types...>::Value constexpr T Construct() const volatile&& { return Super::template Construct<T>(static_cast<const volatile TTuple&&>(*this)); }
|
||||
|
||||
};
|
||||
|
||||
template <typename... Types>
|
||||
TTuple(Types...) -> TTuple<Types...>;
|
||||
|
||||
template <typename T, typename U>
|
||||
using TPair = TTuple<T, U>;
|
||||
|
||||
template <typename T > struct TIsTupleSpecialization : FFalse { };
|
||||
template <typename... Types> struct TIsTupleSpecialization<TTuple<Types...>> : FTrue { };
|
||||
|
||||
template <typename TupleType> requires TIsTupleSpecialization<typename TRemoveCVRef<TupleType>::Type>::Value
|
||||
struct TTupleElementSize : TConstant<size_t, TRemoveCVRef<TupleType>::Type::ElementSize> { };
|
||||
|
||||
template <size_t I, typename TupleType> requires TIsTupleSpecialization<typename TRemoveCVRef<TupleType>::Type>::Value
|
||||
struct TTupleElementType { using Type = typename TCopyCVRef<typename TRemoveReference<TupleType>::Type, typename TRemoveCVRef<TupleType>::Type::template TElementType<I>::Type>::Type; };
|
||||
|
||||
template <typename T, typename TupleType> requires TIsTupleSpecialization<typename TRemoveCVRef<TupleType>::Type>::Value
|
||||
struct TTupleElementIndex : TupleType::template TElementIndex<T> { };
|
||||
|
||||
template <typename... Types>
|
||||
constexpr TTuple<typename TUnwrapRefDecay<Types>::Type...> MakeTuple(Types&&... Args)
|
||||
{
|
||||
return TTuple<typename TUnwrapRefDecay<Types>::Type...>(Forward<Types>(Args)...);
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
constexpr TTuple<Types&...> Tie(Types&... Args)
|
||||
{
|
||||
return TTuple<Types&...>(Args...);
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
constexpr TTuple<Types&&...> ForwardAsTuple(Types&&... Args)
|
||||
{
|
||||
return TTuple<Types&&...>(Forward<Types>(Args)...);
|
||||
}
|
||||
|
||||
NAMESPACE_PRIVATE_BEGIN
|
||||
|
||||
struct FTupleEndFlag { };
|
||||
|
||||
template <typename... TTupleTypes>
|
||||
struct TTupleCatResultImpl;
|
||||
|
||||
template <typename... Types, typename... TTupleTypes>
|
||||
struct TTupleCatResultImpl<TTuple<Types...>, TTupleTypes...>
|
||||
{
|
||||
using Type = typename TTupleCatResultImpl<TTupleTypes..., Types...>::Type;
|
||||
};
|
||||
|
||||
template <typename... Types>
|
||||
struct TTupleCatResultImpl<FTupleEndFlag, Types...>
|
||||
{
|
||||
using Type = TTuple<Types...>;
|
||||
};
|
||||
|
||||
template <typename R, typename Indices>
|
||||
struct TTupleCatMake;
|
||||
|
||||
template <typename... RTypes, size_t... Indices>
|
||||
struct TTupleCatMake<TTuple<RTypes...>, TIndexSequence<Indices...>>
|
||||
{
|
||||
template <typename T, typename U>
|
||||
struct TForward { using Type = typename TConditional<TIsRValueReference<T>::Value, typename TRemoveReference<U>::Type&&, U>::Type; };
|
||||
|
||||
template <typename TTupleType>
|
||||
static constexpr TTuple<RTypes...> F(TTupleType&& InValue)
|
||||
{
|
||||
return TTuple<RTypes...>
|
||||
(
|
||||
static_cast<typename TForward<RTypes, decltype(Forward<TTupleType>(InValue).template GetValue<Indices>())>::Type>
|
||||
(
|
||||
Forward<TTupleType>(InValue).template GetValue<Indices>()
|
||||
)...
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ForwardIndices, typename TTupleIndices>
|
||||
struct TTupleCatForward;
|
||||
|
||||
template <size_t... ForwardIndices, size_t... TTupleIndices>
|
||||
struct TTupleCatForward<TIndexSequence<ForwardIndices...>, TIndexSequence<TTupleIndices...>>
|
||||
{
|
||||
template <typename ForwardType, typename TTupleType>
|
||||
static constexpr auto F(ForwardType&& ForwardTuple, TTupleType&& InValue)
|
||||
{
|
||||
return ForwardAsTuple(Forward<ForwardType>(ForwardTuple).template GetValue<ForwardIndices>()..., Forward<TTupleType>(InValue).template GetValue<TTupleIndices>()...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct TTupleCatImpl
|
||||
{
|
||||
template <typename ForwardType, typename TTupleType, typename... OtherTTupleTypes>
|
||||
static constexpr auto F(ForwardType&& ForwardTuple, TTupleType&& InValue, OtherTTupleTypes&&... OtherValue)
|
||||
{
|
||||
return F(TTupleCatForward<TMakeIndexSequence<TTupleElementSize<ForwardType>::Value>, TMakeIndexSequence<TTupleElementSize<TTupleType>::Value>>::F(Forward<ForwardType>(ForwardTuple), Forward<TTupleType>(InValue)), Forward<OtherTTupleTypes>(OtherValue)...);
|
||||
}
|
||||
|
||||
template <typename ForwardType>
|
||||
static constexpr auto F(ForwardType&& ForwardTuple)
|
||||
{
|
||||
return TTupleCatMake<R, TMakeIndexSequence<TTupleElementSize<ForwardType>::Value>>::F(Forward<ForwardType>(ForwardTuple));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indices>
|
||||
struct TTupleEqual;
|
||||
|
||||
template <size_t... Indices>
|
||||
struct TTupleEqual<TIndexSequence<Indices...>>
|
||||
{
|
||||
template <typename LHSTupleType, typename RHSTupleType>
|
||||
static constexpr bool F(const LHSTupleType& LHS, const RHSTupleType& RHS)
|
||||
{
|
||||
return (true && ... && (LHS.template GetValue<Indices>() == RHS.template GetValue<Indices>()));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R, typename Indices>
|
||||
struct TTupleThreeWay;
|
||||
|
||||
template <typename R, size_t I, size_t... Indices>
|
||||
struct TTupleThreeWay<R, TIndexSequence<I, Indices...>>
|
||||
{
|
||||
template <typename LHSTupleType, typename RHSTupleType>
|
||||
static constexpr R F(const LHSTupleType& LHS, const RHSTupleType& RHS)
|
||||
{
|
||||
auto Result = TSynthThreeWay{}(LHS.template GetValue<I>(), RHS.template GetValue<I>());
|
||||
if (Result != 0) return Result;
|
||||
return TTupleThreeWay<R, TIndexSequence<Indices...>>::F(LHS, RHS);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
struct TTupleThreeWay<R, TIndexSequence<>>
|
||||
{
|
||||
template <typename LHSTupleType, typename RHSTupleType>
|
||||
static constexpr R F(const LHSTupleType& LHS, const RHSTupleType& RHS)
|
||||
{
|
||||
return R::equivalent;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indices>
|
||||
struct TTupleSwapImpl;
|
||||
|
||||
template <size_t... Indices>
|
||||
struct TTupleSwapImpl<TIndexSequence<Indices...>>
|
||||
{
|
||||
template <typename TTupleType>
|
||||
static constexpr void F(TTupleType& A, TTupleType& B)
|
||||
{
|
||||
((Swap(A.template GetValue<Indices>(), B.template GetValue<Indices>())), ...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Indices>
|
||||
struct TTupleVisitImpl;
|
||||
|
||||
template <size_t I, size_t... Indices>
|
||||
struct TTupleVisitImpl<TIndexSequence<I, Indices...>>
|
||||
{
|
||||
template <typename G, typename... TupleTypes>
|
||||
static constexpr void F(G&& Func, TupleTypes&&... Tuples)
|
||||
{
|
||||
Invoke(Forward<G>(Func), Forward<TupleTypes>(Tuples).template GetValue<I>()...);
|
||||
TTupleVisitImpl<TIndexSequence<Indices...>>::F(Forward<G>(Func), Forward<TupleTypes>(Tuples)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TTupleVisitImpl<TIndexSequence<>>
|
||||
{
|
||||
template <typename... TupleTypes>
|
||||
static constexpr void F(TupleTypes&&... Tuples) { }
|
||||
};
|
||||
|
||||
NAMESPACE_PRIVATE_END
|
||||
|
||||
template <typename... TTupleTypes> requires (true && ... && (TIsTupleSpecialization<typename TRemoveCVRef<TTupleTypes>::Type>::Value))
|
||||
struct TTupleCatResult { using Type = typename NAMESPACE_PRIVATE::TTupleCatResultImpl<typename TRemoveReference<TTupleTypes>::Type..., NAMESPACE_PRIVATE::FTupleEndFlag>::Type; };
|
||||
|
||||
template <typename... TTupleTypes> requires (true && ... && (TIsTupleSpecialization<typename TRemoveCVRef<TTupleTypes>::Type>::Value))
|
||||
constexpr auto TupleCat(TTupleTypes&&... Args)
|
||||
{
|
||||
using R = typename TTupleCatResult<TTupleTypes...>::Type;
|
||||
if constexpr (sizeof...(Args) == 0) return R();
|
||||
else return NAMESPACE_PRIVATE::TTupleCatImpl<R>::F(Forward<TTupleTypes>(Args)...);
|
||||
}
|
||||
|
||||
template <typename... LHSTypes, typename... RHSTypes> requires ((sizeof...(LHSTypes) != sizeof...(RHSTypes)) || (true && ... && CWeaklyEqualityComparableWith<LHSTypes, RHSTypes>))
|
||||
constexpr bool operator==(const TTuple<LHSTypes...>& LHS, const TTuple<RHSTypes...>& RHS)
|
||||
{
|
||||
if constexpr (sizeof...(LHSTypes) != sizeof...(RHSTypes)) return false;
|
||||
return NAMESPACE_PRIVATE::TTupleEqual<TMakeIndexSequence<sizeof...(LHSTypes)>>::F(LHS, RHS);
|
||||
}
|
||||
|
||||
template <typename... LHSTypes, typename... RHSTypes> requires ((sizeof...(LHSTypes) == sizeof...(RHSTypes)) && (true && ... && (CSynthThreeWayComparableWith<LHSTypes, RHSTypes>)))
|
||||
constexpr typename TCommonComparisonCategory<typename TSynthThreeWayResult<LHSTypes, RHSTypes>::Type...>::Type operator<=>(const TTuple<LHSTypes...>& LHS, const TTuple<RHSTypes...>& RHS)
|
||||
{
|
||||
using R = typename TCommonComparisonCategory<typename TSynthThreeWayResult<LHSTypes, RHSTypes>::Type...>::Type;
|
||||
return NAMESPACE_PRIVATE::TTupleThreeWay<R, TMakeIndexSequence<sizeof...(LHSTypes)>>::F(LHS, RHS);
|
||||
}
|
||||
|
||||
template <typename... Types> requires (true && ... && (TIsMoveConstructible<Types>::Value && TIsSwappable<Types>::Value))
|
||||
constexpr void Swap(TTuple<Types...>& A, TTuple<Types...>& B)
|
||||
{
|
||||
NAMESPACE_PRIVATE::TTupleSwapImpl<TIndexSequenceFor<Types...>>::F(A, B);
|
||||
}
|
||||
|
||||
template <typename F> requires TIsInvocable<F>::Value
|
||||
constexpr void VisitTuple(F&& Func) { }
|
||||
|
||||
template <typename F, typename FirstTupleType, typename... TupleTypes>
|
||||
constexpr void VisitTuple(F&& Func, FirstTupleType&& FirstTuple, TupleTypes&&... Tuples)
|
||||
{
|
||||
NAMESPACE_PRIVATE::TTupleVisitImpl<TMakeIndexSequence<TTupleElementSize<FirstTupleType>::Value>>::F(Forward<F>(Func), Forward<FirstTupleType>(FirstTuple), Forward<TupleTypes>(Tuples)...);
|
||||
}
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
||||
|
||||
NAMESPACE_STD_BEGIN
|
||||
|
||||
// Support structure binding, should not be directly used
|
||||
template <typename... Types> struct tuple_size<NAMESPACE_REDCRAFT::TTuple<Types...>> : integral_constant<size_t, NAMESPACE_REDCRAFT::TTupleElementSize<NAMESPACE_REDCRAFT::TTuple<Types...>>::Value> { };
|
||||
template <size_t I, typename... Types> struct tuple_element<I, NAMESPACE_REDCRAFT::TTuple<Types...>> { using type = typename NAMESPACE_REDCRAFT::TTupleElementType<I, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type; };
|
||||
|
||||
NAMESPACE_STD_END
|
||||
|
||||
NAMESPACE_REDCRAFT_BEGIN
|
||||
NAMESPACE_MODULE_BEGIN(Redcraft)
|
||||
NAMESPACE_MODULE_BEGIN(Utility)
|
||||
|
||||
// Support structure binding, should not be directly used
|
||||
template <size_t Index, typename ...Types> constexpr typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& get( NAMESPACE_REDCRAFT::TTuple<Types...>& InValue) { return static_cast< typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& >(InValue.template GetValue<Index>()); }
|
||||
template <size_t Index, typename ...Types> constexpr const typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& get(const NAMESPACE_REDCRAFT::TTuple<Types...>& InValue) { return static_cast<const typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& >(InValue.template GetValue<Index>()); }
|
||||
template <size_t Index, typename ...Types> constexpr volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& get( volatile NAMESPACE_REDCRAFT::TTuple<Types...>& InValue) { return static_cast< volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& >(InValue.template GetValue<Index>()); }
|
||||
template <size_t Index, typename ...Types> constexpr const volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& get(const volatile NAMESPACE_REDCRAFT::TTuple<Types...>& InValue) { return static_cast<const volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type& >(InValue.template GetValue<Index>()); }
|
||||
template <size_t Index, typename ...Types> constexpr typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&& get( NAMESPACE_REDCRAFT::TTuple<Types...>&& InValue) { return static_cast< typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&&>(InValue.template GetValue<Index>()); }
|
||||
template <size_t Index, typename ...Types> constexpr const typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&& get(const NAMESPACE_REDCRAFT::TTuple<Types...>&& InValue) { return static_cast<const typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&&>(InValue.template GetValue<Index>()); }
|
||||
template <size_t Index, typename ...Types> constexpr volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&& get( volatile NAMESPACE_REDCRAFT::TTuple<Types...>&& InValue) { return static_cast< volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&&>(InValue.template GetValue<Index>()); }
|
||||
template <size_t Index, typename ...Types> constexpr const volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&& get(const volatile NAMESPACE_REDCRAFT::TTuple<Types...>&& InValue) { return static_cast<const volatile typename TTupleElementType<Index, NAMESPACE_REDCRAFT::TTuple<Types...>>::Type&&>(InValue.template GetValue<Index>()); }
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
@ -92,6 +92,14 @@ constexpr T* AddressOf(T& Object)
|
||||
return &Object;
|
||||
}
|
||||
|
||||
struct FIgnore
|
||||
{
|
||||
template <typename T>
|
||||
constexpr void operator=(T&&) const { }
|
||||
};
|
||||
|
||||
inline constexpr FIgnore Ignore;
|
||||
|
||||
NAMESPACE_MODULE_END(Utility)
|
||||
NAMESPACE_MODULE_END(Redcraft)
|
||||
NAMESPACE_REDCRAFT_END
|
||||
|
@ -14,6 +14,7 @@ REDCRAFTUTILITY_API void TestReferenceWrapper();
|
||||
REDCRAFTUTILITY_API void TestOptional();
|
||||
REDCRAFTUTILITY_API void TestVariant();
|
||||
REDCRAFTUTILITY_API void TestAny();
|
||||
REDCRAFTUTILITY_API void TestTuple();
|
||||
REDCRAFTUTILITY_API void TestMiscTemplates();
|
||||
|
||||
NAMESPACE_END(Testing)
|
||||
|
Loading…
Reference in New Issue
Block a user