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

View File

@ -43,39 +43,28 @@ struct TVariantAlternativeImpl<I, TVariant<Ts...>>
using Type = Meta::TType<I, TTypeSequence<Ts...>>;
};
template <typename T, typename... Ts>
struct TVariantSelectedType;
template <typename T, typename U, typename... Ts>
struct TVariantSelectedType<T, U, Ts...>
template <typename T, typename TSequence>
struct TVariantOverloadType
{
using TypeAlternativeA = TConditional<CConstructibleFrom<U, T&&>, U, void>;
using TypeAlternativeB = typename TVariantSelectedType<T, Ts...>::Type;
using FrontType = Meta::TFront<TSequence>;
using NextSequence = Meta::TPop<TSequence>;
using NextUniqueSequence = typename TVariantOverloadType<T, NextSequence>::Type;
using Type = TConditional<CSameAs<TRemoveCVRef<TypeAlternativeA>, void>, TypeAlternativeB,
TConditional<CSameAs<TRemoveCVRef<TypeAlternativeB>, void>, TypeAlternativeA,
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;
// T_i x[] = { Forward<T>(t) };
static constexpr bool bConditional = requires { DeclVal<void(FrontType(&&)[1])>()({ DeclVal<T>() }); };
using Type = TConditional<bConditional, Meta::TPush<FrontType, NextUniqueSequence>, NextUniqueSequence>;
};
template <typename T>
struct TVariantSelectedType<T>
struct TVariantOverloadType<T, TTypeSequence<>>
{
static constexpr uint8 Flag = 0;
using Type = void;
using Type = TTypeSequence<>;
};
template <typename T, typename... Ts>
using TVariantSelectedType = Meta::TOverloadResolution<T, typename NAMESPACE_PRIVATE::TVariantOverloadType<T, TTypeSequence<Ts...>>::Type>;
NAMESPACE_PRIVATE_END
template <typename T>
@ -129,10 +118,10 @@ public:
: 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>>
&& !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;
@ -190,10 +179,10 @@ public:
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)
{
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);
else