refactor(templates): optimize the implementation of TOptional and TVariant

This commit is contained in:
2022-05-03 18:22:41 +08:00
parent a737eea487
commit 522c71f2b6
3 changed files with 296 additions and 312 deletions

View File

@ -85,247 +85,277 @@ void TestReferenceWrapper()
void TestOptional()
{
TOptional<int32> TempA;
TOptional<int32> TempB(Invalid);
TOptional<int32> TempC(InPlace, 0);
TOptional<int32> TempD(0);
TOptional<int32> TempE(0l);
TOptional<int32> TempF(0.0);
TOptional<int32> TempG(TempA);
TOptional<int32> TempH(TempD);
TOptional<int32> TempI(MakeOptional<int32>(0));
TOptional<int32> TempJ(MakeOptional<int32>(Invalid));
TOptional<int32> TempK, TempL, TempM, TempN;
TempK = TempA;
TempL = TempD;
TempM = MakeOptional<int32>(0);
TempN = MakeOptional<int32>(Invalid);
*TempL = 303;
*TempM = 404;
TOptional<int32> TempO;
TempO.Emplace(404);
always_check(TempO);
always_check(TempO.IsValid());
always_check(*TempO == 404);
always_check(TempO.GetValue() == 404);
always_check(TempO.Get(500) == 404);
TempO.Reset();
always_check(TempO == TempO);
always_check(!(TempO != TempO));
always_check(TempO.Get(500) == 500);
int32 TempP = 200;
TempO = TempP;
TempO = 300;
always_check(TempO != TempA);
always_check(TempO != TempD);
always_check(TempO == TempO);
always_check(TempO == 300);
always_check(300 == TempO);
int16 TempQ = 1024;
TOptional<int16> TempR = TempQ;
TOptional<int32> TempS(InPlace, TempQ);
TOptional<int32> TempT(TempQ);
TOptional<int32> TempU(TempR);
TOptional<int32> TempV(MakeOptional<int16>(2048));
TOptional<int32> TempW, TempX, TempY;
TempW = TempQ;
TempX = TempR;
TempY = MakeOptional<int16>(2048);
struct FTracker
{
FTracker() { }
FTracker(const FTracker& InValue) { always_check_no_entry(); }
FTracker(FTracker&& InValue) { }
FTracker& operator=(const FTracker& InValue) { always_check_no_entry(); return *this; }
FTracker& operator=(FTracker&& InValue) { return *this; }
};
TOptional<int32> TempA;
TOptional<int32> TempB(Invalid);
TOptional<int32> TempC(InPlace, 0);
TOptional<int32> TempD(0);
TOptional<int32> TempE(0l);
TOptional<int32> TempF(0.0);
TOptional<int32> TempG(TempA);
TOptional<int32> TempH(TempD);
TOptional<int32> TempI(MakeOptional<int32>(0));
TOptional<int32> TempJ(MakeOptional<int32>(Invalid));
TOptional<FTracker> TempZ(MakeOptional<FTracker>());
TempZ = MakeOptional<FTracker>();
TempZ = FTracker();
TOptional<int32> TempK, TempL, TempM, TempN;
TempK = TempA;
TempL = TempD;
TempM = MakeOptional<int32>(0);
TempN = MakeOptional<int32>(Invalid);
always_check(GetTypeHash(MakeOptional<int32>(114)) == GetTypeHash(MakeOptional<int32>(114)));
always_check(GetTypeHash(MakeOptional<int32>(114)) != GetTypeHash(MakeOptional<int32>(514)));
*TempL = 303;
*TempM = 404;
TOptional<int32> TempO;
TempO.Emplace(404);
always_check(TempO);
always_check(TempO.IsValid());
always_check(*TempO == 404);
always_check(TempO.GetValue() == 404);
always_check(TempO.Get(500) == 404);
TempO.Reset();
always_check(TempO == TempO);
always_check(!(TempO != TempO));
always_check(TempO.Get(500) == 500);
int32 TempP = 200;
TempO = TempP;
TempO = 300;
always_check(TempO != TempA);
always_check(TempO != TempD);
always_check(TempO == TempO);
always_check(TempO == 300);
always_check(300 == TempO);
int16 TempQ = 1024;
TOptional<int16> TempR = TempQ;
TOptional<int32> TempS(InPlace, TempQ);
TOptional<int32> TempT(TempQ);
TOptional<int32> TempU(TempR);
TOptional<int32> TempV(MakeOptional<int16>(2048));
TOptional<int32> TempW, TempX, TempY;
TempW = TempQ;
TempX = TempR;
TempY = MakeOptional<int16>(2048);
struct FTracker
{
FTracker() { }
FTracker(const FTracker& InValue) { always_check_no_entry(); }
FTracker(FTracker&& InValue) { }
FTracker& operator=(const FTracker& InValue) { always_check_no_entry(); return *this; }
FTracker& operator=(FTracker&& InValue) { return *this; }
};
TOptional<FTracker> TempZ(MakeOptional<FTracker>());
TempZ = MakeOptional<FTracker>();
TempZ = FTracker();
always_check(GetTypeHash(MakeOptional<int32>(114)) == GetTypeHash(MakeOptional<int32>(114)));
always_check(GetTypeHash(MakeOptional<int32>(114)) != GetTypeHash(MakeOptional<int32>(514)));
}
{
TOptional<uint8> TempA = Invalid;
TOptional<int16> TempB = 16;
TOptional<int64> TempC = 32;
always_check(TempA != TempB);
always_check(TempB != TempC);
always_check(TempB <= TempC);
always_check(TempA <=> TempB == partial_ordering::unordered);
}
}
void TestVariant()
{
TVariant<int32> TempA;
TVariant<int32> TempB(Invalid);
TVariant<int32> TempC(InPlaceType<int32>, 0);
TVariant<int32> TempD(0);
TVariant<int32> TempE(0l);
TVariant<int32> TempF(0.0);
TVariant<int32> TempG(TempA);
TVariant<int32> TempH(TempD);
TVariant<int32> TempI(TVariant<int32>(0));
TVariant<int32> TempJ(TVariant<int32>(Invalid));
TVariant<int32> TempK, TempL, TempM, TempN;
TempK = TempA;
TempL = TempD;
TempM = TVariant<int32>(0);
TempN = TVariant<int32>(Invalid);
TempL = 303;
TempM = 404;
TVariant<int32> TempO;
TempO.Emplace<int32>(202);
TempO.Emplace<0>(404);
always_check(TempO);
always_check(TempO.IsValid());
always_check(TempO == 404);
always_check(TempO.GetValue<int32>() == 404);
always_check(TempO.Get<0>(500) == 404);
TempO.Reset();
always_check(TempO == TempO);
always_check(!(TempO != TempO));
always_check(TempO.Get<int32>(500) == 500);
int32 TempP = 200;
TempO = TempP;
TempO = 300;
always_check(TempO != TempA);
always_check(TempO != TempD);
always_check(TempO == TempO);
always_check(TempO == 300);
always_check(300 == TempO);
Swap(TempD, TempA);
int16 TempQ = 1024;
TVariant<int16, int32> TempR = TempQ;
TVariant<int16, int32> TempS(InPlaceType<int32>, TempQ);
TVariant<int16, int32> TempT(TempQ);
TVariant<int16, int32> TempU(TempR);
TVariant<int16, int32> TempV(TVariant<int16, int32>(2048));
TVariant<int16, int32> TempW, TempX, TempY;
TempW = TempQ;
TempX = TempR;
TempY = TVariant<int16, int32>(2048);
Swap(TempW, TempX);
Swap(TempW, TempX);
struct FTracker
{
FTracker() { }
FTracker(const FTracker& InValue) { always_check_no_entry(); }
FTracker(FTracker&& InValue) { }
FTracker& operator=(const FTracker& InValue) { always_check_no_entry(); return *this; }
FTracker& operator=(FTracker&& InValue) { return *this; }
};
TVariant<int32> TempA;
TVariant<int32> TempB(Invalid);
TVariant<int32> TempC(InPlaceType<int32>, 0);
TVariant<int32> TempD(0);
TVariant<int32> TempE(0l);
TVariant<int32> TempF(0.0);
TVariant<int32> TempG(TempA);
TVariant<int32> TempH(TempD);
TVariant<int32> TempI(TVariant<int32>(0));
TVariant<int32> TempJ(TVariant<int32>(Invalid));
TVariant<FTracker> TempZ(Invalid);
TempZ = TVariant<FTracker>();
TempZ = FTracker();
TVariant<int32> TempK, TempL, TempM, TempN;
TempK = TempA;
TempL = TempD;
TempM = TVariant<int32>(0);
TempN = TVariant<int32>(Invalid);
always_check((TIsSame<int32, TVariantAlternativeType<0, TVariant<int32, float>>::Type>::Value));
always_check((TIsSame<float, TVariantAlternativeType<1, TVariant<int32, float>>::Type>::Value));
always_check((TIsSame<const int32, TVariantAlternativeType<0, const TVariant<int32, float>>::Type>::Value));
TempL = 303;
TempM = 404;
always_check((TVariantAlternativeIndex<int32, TVariant<int32, float>>::Value == 0));
always_check((TVariantAlternativeIndex<float, TVariant<int32, float>>::Value == 1));
TVariant<int32> TempO;
TempO.Emplace<int32>(202);
TempO.Emplace<0>(404);
bool bIsConst;
bool bIsLValue;
bool bIsRValue;
always_check(TempO);
always_check(TempO.IsValid());
auto TestQualifiers = [&bIsConst, &bIsLValue, &bIsRValue](auto&& Arg) -> int32
always_check(TempO == 404);
always_check(TempO.GetValue<int32>() == 404);
always_check(TempO.Get<0>(500) == 404);
TempO.Reset();
always_check(TempO == TempO);
always_check(!(TempO != TempO));
always_check(TempO.Get<int32>(500) == 500);
int32 TempP = 200;
TempO = TempP;
TempO = 300;
always_check(TempO != TempA);
always_check(TempO != TempD);
always_check(TempO == TempO);
always_check(TempO == 300);
always_check(300 == TempO);
Swap(TempD, TempA);
int16 TempQ = 1024;
TVariant<int16, int32> TempR = TempQ;
TVariant<int16, int32> TempS(InPlaceType<int32>, TempQ);
TVariant<int16, int32> TempT(TempQ);
TVariant<int16, int32> TempU(TempR);
TVariant<int16, int32> TempV(TVariant<int16, int32>(2048));
TVariant<int16, int32> TempW, TempX, TempY;
TempW = TempQ;
TempX = TempR;
TempY = TVariant<int16, int32>(2048);
Swap(TempW, TempX);
Swap(TempW, TempX);
}
{
using T = decltype(Arg);
always_check(Arg == 10);
always_check(TIsConst<typename TRemoveReference<T>::Type>::Value == bIsConst);
always_check(TIsLValueReference<T>::Value == bIsLValue);
always_check(TIsRValueReference<T>::Value == bIsRValue);
return 0;
};
struct FTracker
{
FTracker() { }
FTracker(const FTracker& InValue) { always_check_no_entry(); }
FTracker(FTracker&& InValue) { }
FTracker& operator=(const FTracker& InValue) { always_check_no_entry(); return *this; }
FTracker& operator=(FTracker&& InValue) { return *this; }
};
bIsConst = false;
bIsLValue = true;
bIsRValue = false;
TVariant<FTracker> TempZ(Invalid);
TempZ = TVariant<FTracker>();
TempZ = FTracker();
TVariant<int32> TempLA = 10;
auto ReturnLA = TempLA.Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLA)>::Value));
always_check((TIsSame<int32, TVariantAlternativeType<0, TVariant<int32, float>>::Type>::Value));
always_check((TIsSame<float, TVariantAlternativeType<1, TVariant<int32, float>>::Type>::Value));
always_check((TIsSame<const int32, TVariantAlternativeType<0, const TVariant<int32, float>>::Type>::Value));
bIsConst = true;
bIsLValue = true;
bIsRValue = false;
always_check((TVariantAlternativeIndex<int32, TVariant<int32, float>>::Value == 0));
always_check((TVariantAlternativeIndex<float, TVariant<int32, float>>::Value == 1));
const TVariant<int32> TempLB = TempLA;
auto ReturnLB = TempLB.Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLB)>::Value));
bool bIsConst;
bool bIsLValue;
bool bIsRValue;
auto TestQualifiers = [&bIsConst, &bIsLValue, &bIsRValue](auto&& Arg) -> int32
{
using T = decltype(Arg);
always_check(Arg == 10);
always_check(TIsConst<typename TRemoveReference<T>::Type>::Value == bIsConst);
always_check(TIsLValueReference<T>::Value == bIsLValue);
always_check(TIsRValueReference<T>::Value == bIsRValue);
return 0;
};
bIsConst = false;
bIsLValue = true;
bIsRValue = false;
TVariant<int32> TempLA = 10;
auto ReturnLA = TempLA.Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLA)>::Value));
bIsConst = true;
bIsLValue = true;
bIsRValue = false;
const TVariant<int32> TempLB = TempLA;
auto ReturnLB = TempLB.Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLB)>::Value));
bIsConst = false;
bIsLValue = false;
bIsRValue = true;
TVariant<int32> TempRA = 10;
auto ReturnRA = MoveTemp(TempRA).Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRA)>::Value));
bIsConst = true;
bIsLValue = false;
bIsRValue = true;
const TVariant<int32> TempRB = TempLA;
auto ReturnRB = MoveTemp(TempRB).Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRB)>::Value));
bIsConst = false;
bIsLValue = true;
bIsRValue = false;
TVariant<int32> TempLC = 10;
auto ReturnLC = TempLC.Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLC)>::Value));
bIsConst = true;
bIsLValue = true;
bIsRValue = false;
const TVariant<int32> TempLD = TempLC;
auto ReturnLD = TempLD.Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLD)>::Value));
bIsConst = false;
bIsLValue = false;
bIsRValue = true;
TVariant<int32> TempRC = 10;
auto ReturnRC = MoveTemp(TempRC).Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRC)>::Value));
bIsConst = true;
bIsLValue = false;
bIsRValue = true;
const TVariant<int32> TempRD = TempLC;
auto ReturnRD = MoveTemp(TempRD).Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRD)>::Value));
always_check(GetTypeHash(TVariant<int32, float>(114)) == GetTypeHash(TVariant<int32, float>(114)));
always_check(GetTypeHash(TVariant<int32, float>(114)) != GetTypeHash(TVariant<int32, float>(514)));
}
bIsConst = false;
bIsLValue = false;
bIsRValue = true;
{
TVariant<uint8, int16, int32> TempA = Invalid;
TVariant<uint8, int16, int32> TempB = static_cast<int16>(16);
TVariant<uint8, int16, int32> TempC = static_cast<int32>(16);
TVariant<uint8, int16, int32> TempD = static_cast<int32>(32);
TVariant<int32> TempRA = 10;
auto ReturnRA = MoveTemp(TempRA).Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRA)>::Value));
bIsConst = true;
bIsLValue = false;
bIsRValue = true;
const TVariant<int32> TempRB = TempLA;
auto ReturnRB = MoveTemp(TempRB).Visit(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRB)>::Value));
bIsConst = false;
bIsLValue = true;
bIsRValue = false;
TVariant<int32> TempLC = 10;
auto ReturnLC = TempLC.Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLC)>::Value));
bIsConst = true;
bIsLValue = true;
bIsRValue = false;
const TVariant<int32> TempLD = TempLC;
auto ReturnLD = TempLD.Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnLD)>::Value));
bIsConst = false;
bIsLValue = false;
bIsRValue = true;
TVariant<int32> TempRC = 10;
auto ReturnRC = MoveTemp(TempRC).Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRC)>::Value));
bIsConst = true;
bIsLValue = false;
bIsRValue = true;
const TVariant<int32> TempRD = TempLC;
auto ReturnRD = MoveTemp(TempRD).Visit<int32>(TestQualifiers);
always_check((TIsSame<int32, decltype(ReturnRD)>::Value));
always_check(GetTypeHash(TVariant<int32, float>(114)) == GetTypeHash(TVariant<int32, float>(114)));
always_check(GetTypeHash(TVariant<int32, float>(114)) != GetTypeHash(TVariant<int32, float>(514)));
always_check(TempA != TempB);
always_check(TempB != TempC);
always_check(TempB != TempC);
always_check(TempD >= TempC);
always_check(TempA <=> TempB == partial_ordering::unordered);
}
}
void TestAny()
@ -530,6 +560,19 @@ void TestAny()
TempZ = FAny();
TempZ = FTracker();
}
{
FAny TempA = Invalid;
FAny TempB = static_cast<int16>(16);
FAny TempC = static_cast<int32>(16);
FAny TempD = static_cast<int32>(32);
always_check(TempA != TempB);
always_check(TempB != TempC);
always_check(TempB != TempC);
always_check(TempD >= TempC);
always_check(TempA <=> TempB == partial_ordering::unordered);
}
}
void TestTuple()