fix(templates): fix the type selection of TVariant's converting constructor

This commit is contained in:
_Redstone_c_ 2022-12-03 23:12:29 +08:00
parent 01eec5d4c0
commit 797386f3d6
2 changed files with 26 additions and 31 deletions

View File

@ -180,8 +180,8 @@ void TestVariant()
TVariant<int32> TempB(Invalid); TVariant<int32> TempB(Invalid);
TVariant<int32> TempC(InPlaceType<int32>, 0); TVariant<int32> TempC(InPlaceType<int32>, 0);
TVariant<int32> TempD(0); TVariant<int32> TempD(0);
TVariant<int32> TempE(0l); // TVariant<int32> TempE(0ll);
TVariant<int32> TempF(0.0); // TVariant<int32> TempF(0.0);
TVariant<int32> TempG(TempA); TVariant<int32> TempG(TempA);
TVariant<int32> TempH(TempD); TVariant<int32> TempH(TempD);
TVariant<int32> TempI(TVariant<int32>(0)); TVariant<int32> TempI(TVariant<int32>(0));
@ -241,6 +241,12 @@ void TestVariant()
Swap(TempW, TempX); Swap(TempW, TempX);
} }
{
// TVariant<bool> TempA = false;
// TempA.Visit([](auto& A) { A = true; });
// always_check(TempA.GetValue<bool>());
}
{ {
struct FTracker struct FTracker
{ {

View File

@ -43,39 +43,28 @@ struct TVariantAlternativeImpl<I, TVariant<Ts...>>
using Type = Meta::TType<I, TTypeSequence<Ts...>>; using Type = Meta::TType<I, TTypeSequence<Ts...>>;
}; };
template <typename T, typename... Ts> template <typename T, typename TSequence>
struct TVariantSelectedType; struct TVariantOverloadType
template <typename T, typename U, typename... Ts>
struct TVariantSelectedType<T, U, Ts...>
{ {
using TypeAlternativeA = TConditional<CConstructibleFrom<U, T&&>, U, void>; using FrontType = Meta::TFront<TSequence>;
using TypeAlternativeB = typename TVariantSelectedType<T, Ts...>::Type; using NextSequence = Meta::TPop<TSequence>;
using NextUniqueSequence = typename TVariantOverloadType<T, NextSequence>::Type;
using Type = TConditional<CSameAs<TRemoveCVRef<TypeAlternativeA>, void>, TypeAlternativeB, // T_i x[] = { Forward<T>(t) };
TConditional<CSameAs<TRemoveCVRef<TypeAlternativeB>, void>, TypeAlternativeA, static constexpr bool bConditional = requires { DeclVal<void(FrontType(&&)[1])>()({ DeclVal<T>() }); };
TConditional<CSameAs<TRemoveCVRef<TypeAlternativeB>, TRemoveCVRef<T>>, TypeAlternativeB, TypeAlternativeA>>>;
// 0 - Type not found
// 1 - Same type found
// 2 - Multiple types found
// 3 - The type found
static constexpr uint8 Flag = CSameAs<TRemoveCVRef<Type>, void> ? 0 :
CSameAs<TRemoveCVRef<TypeAlternativeA>, TRemoveCVRef<TypeAlternativeB>> ? 2 :
CSameAs<TRemoveCVRef< Type>, TRemoveCVRef< T>> ? 1 :
!CSameAs<TRemoveCVRef<TypeAlternativeA>, void> && !CSameAs<TypeAlternativeB, void> ? 2 : 3;
static constexpr bool Value = Flag & 1;
using Type = TConditional<bConditional, Meta::TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
}; };
template <typename T> template <typename T>
struct TVariantSelectedType<T> struct TVariantOverloadType<T, TTypeSequence<>>
{ {
static constexpr uint8 Flag = 0; using Type = TTypeSequence<>;
using Type = void;
}; };
template <typename T, typename... Ts>
using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::Type>;
NAMESPACE_PRIVATE_END NAMESPACE_PRIVATE_END
template <typename T> template <typename T>
@ -129,10 +118,10 @@ public:
: TVariant(InPlaceIndex<TVariantIndex<T, TVariant<Ts...>>>, Forward<ArgTypes>(Args)...) : TVariant(InPlaceIndex<TVariantIndex<T, TVariant<Ts...>>>, Forward<ArgTypes>(Args)...)
{ } { }
template <typename T> requires (NAMESPACE_PRIVATE::TVariantSelectedType<TRemoveReference<T>, Ts...>::Value template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; }
&& !CTInPlaceType<TRemoveCVRef<T>> && !CTInPlaceIndex<TRemoveCVRef<T>> && !CTInPlaceType<TRemoveCVRef<T>> && !CTInPlaceIndex<TRemoveCVRef<T>>
&& !CBaseOf<TVariant, TRemoveCVRef<T>>) && !CBaseOf<TVariant, TRemoveCVRef<T>>)
constexpr TVariant(T&& InValue) : TVariant(InPlaceType<typename NAMESPACE_PRIVATE::TVariantSelectedType<TRemoveReference<T>, Ts...>::Type>, Forward<T>(InValue)) constexpr TVariant(T&& InValue) : TVariant(InPlaceType<NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>>, Forward<T>(InValue))
{ } { }
constexpr ~TVariant() requires (true && ... && CTriviallyDestructible<Ts>) = default; constexpr ~TVariant() requires (true && ... && CTriviallyDestructible<Ts>) = default;
@ -190,10 +179,10 @@ public:
return *this; return *this;
} }
template <typename T> requires (NAMESPACE_PRIVATE::TVariantSelectedType<TRemoveReference<T>, Ts...>::Value) template <typename T> requires (requires { typename NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>; })
constexpr TVariant& operator=(T&& InValue) constexpr TVariant& operator=(T&& InValue)
{ {
using SelectedType = typename NAMESPACE_PRIVATE::TVariantSelectedType<TRemoveReference<T>, Ts...>::Type; using SelectedType = NAMESPACE_PRIVATE::TVariantSelectedType<T, Ts...>;
if (GetIndex() == TVariantIndex<SelectedType, TVariant<Ts...>>) GetValue<SelectedType>() = Forward<T>(InValue); if (GetIndex() == TVariantIndex<SelectedType, TVariant<Ts...>>) GetValue<SelectedType>() = Forward<T>(InValue);
else else