2022-03-15 11:26:31 +00:00
# pragma once
# include "CoreTypes.h"
# include "Templates/Invoke.h"
# include "Templates/Utility.h"
2022-04-22 14:28:44 +00:00
# include "Templates/TypeHash.h"
2022-03-15 11:26:31 +00:00
# include "TypeTraits/TypeTraits.h"
2022-05-03 10:22:41 +00:00
# include "Miscellaneous/Compare.h"
# include "Miscellaneous/TypeInfo.h"
2022-03-22 03:12:05 +00:00
# include "Miscellaneous/AssertionMacros.h"
2022-03-15 11:26:31 +00:00
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN ( Redcraft )
NAMESPACE_MODULE_BEGIN ( Utility )
NAMESPACE_PRIVATE_BEGIN
template < typename T , typename . . . Types >
struct TVariantAlternativeIndex ;
template < typename T , typename U , typename . . . Types >
struct TVariantAlternativeIndex < T , U , Types . . . >
2022-03-17 01:22:48 +00:00
: TConstant < size_t , TIsSame < T , U > : : Value ? 0 : ( TVariantAlternativeIndex < T , Types . . . > : : Value = = INDEX_NONE
? INDEX_NONE : TVariantAlternativeIndex < T , Types . . . > : : Value + 1 ) >
2022-03-15 11:26:31 +00:00
{ } ;
template < typename T >
2022-03-17 01:22:48 +00:00
struct TVariantAlternativeIndex < T > : TConstant < size_t , INDEX_NONE > { } ;
2022-03-15 11:26:31 +00:00
template < size_t I , typename . . . Types >
struct TVariantAlternativeType ;
template < size_t I , typename T , typename . . . Types >
struct TVariantAlternativeType < I , T , Types . . . >
{
static_assert ( I < sizeof . . . ( Types ) + 1 , " Variant type index is invalid " ) ;
using Type = TVariantAlternativeType < I - 1 , Types . . . > : : Type ;
} ;
template < typename T , typename . . . Types >
struct TVariantAlternativeType < 0 , T , Types . . . > { using Type = T ; } ;
2022-03-30 04:06:05 +00:00
template < >
struct TVariantAlternativeType < 0 > { } ;
2022-03-15 11:26:31 +00:00
template < typename T , typename . . . Types >
struct TVariantSelectedType ;
template < typename T , typename U , typename . . . Types >
struct TVariantSelectedType < T , U , Types . . . >
{
using TypeAlternativeA = typename TConditional < TIsConstructible < U , T & & > : : Value , U , void > : : Type ;
using TypeAlternativeB = typename TVariantSelectedType < T , Types . . . > : : Type ;
2022-03-30 04:06:05 +00:00
using Type = typename TConditional < TIsSame < typename TRemoveCVRef < TypeAlternativeA > : : Type , void > : : Value , TypeAlternativeB ,
typename TConditional < TIsSame < typename TRemoveCVRef < TypeAlternativeB > : : Type , void > : : Value , TypeAlternativeA ,
typename TConditional < TIsSame < typename TRemoveCVRef < TypeAlternativeB > : : Type , typename TRemoveCVRef < T > : : Type > : : Value , TypeAlternativeB , TypeAlternativeA > : : Type > : : Type > : : Type ;
2022-03-15 11:26:31 +00:00
// 0 - Type not found
// 1 - Same type found
// 2 - Multiple types found
// 3 - The type found
2022-03-30 04:06:05 +00:00
static constexpr uint8 Flag = TIsSame < typename TRemoveCVRef < Type > : : Type , void > : : Value ? 0 :
TIsSame < typename TRemoveCVRef < TypeAlternativeA > : : Type , typename TRemoveCVRef < TypeAlternativeB > : : Type > : : Value ? 2 :
TIsSame < typename TRemoveCVRef < Type > : : Type , typename TRemoveCVRef < T > : : Type > : : Value ? 1 :
! TIsSame < typename TRemoveCVRef < TypeAlternativeA > : : Type , void > : : Value & & ! TIsSame < TypeAlternativeB , void > : : Value ? 2 : 3 ;
2022-03-15 11:26:31 +00:00
static constexpr bool Value = Flag & 1 ;
} ;
template < typename T >
struct TVariantSelectedType < T >
{
static constexpr uint8 Flag = 0 ;
using Type = void ;
} ;
template < typename R , typename F , typename T >
constexpr R VariantVisitLValue ( F & & Func , void * Arg )
{
2022-03-23 09:49:30 +00:00
if constexpr ( TIsVoid < R > : : Value ) Invoke ( Forward < F > ( Func ) , * reinterpret_cast < T * > ( Arg ) ) ;
2022-03-15 11:26:31 +00:00
else return InvokeResult < R > ( Forward < F > ( Func ) , * reinterpret_cast < T * > ( Arg ) ) ;
}
template < typename R , typename F >
using FVariantVisitLValueFunc = R ( * ) ( F & & , void * ) ;
template < typename R , typename F , typename T >
constexpr R VariantVisitRValue ( F & & Func , void * Arg )
{
2022-03-23 09:49:30 +00:00
if constexpr ( TIsVoid < R > : : Value ) Invoke ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < T * > ( Arg ) ) ) ;
2022-03-15 11:26:31 +00:00
else return InvokeResult < R > ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < T * > ( Arg ) ) ) ;
}
template < typename R , typename F >
using FVariantVisitRValueFunc = R ( * ) ( F & & , void * ) ;
template < typename R , typename F , typename T >
constexpr R VariantVisitConstLValue ( F & & Func , const void * Arg )
{
2022-03-23 09:49:30 +00:00
if constexpr ( TIsVoid < R > : : Value ) Invoke ( Forward < F > ( Func ) , * reinterpret_cast < const T * > ( Arg ) ) ;
2022-03-15 11:26:31 +00:00
else return InvokeResult < R > ( Forward < F > ( Func ) , * reinterpret_cast < const T * > ( Arg ) ) ;
}
template < typename R , typename F >
using FVariantVisitConstLValueFunc = R ( * ) ( F & & , const void * ) ;
template < typename R , typename F , typename T >
constexpr R VariantVisitConstRValue ( F & & Func , const void * Arg )
{
2022-03-23 09:49:30 +00:00
if constexpr ( TIsVoid < R > : : Value ) Invoke ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < const T * > ( Arg ) ) ) ;
2022-03-15 11:26:31 +00:00
else return InvokeResult < R > ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < const T * > ( Arg ) ) ) ;
}
template < typename R , typename F >
using FVariantVisitConstRValueFunc = R ( * ) ( F & & , const void * ) ;
template < typename R , typename F , typename . . . Types >
struct TVariantVisitHelper
{
static constexpr FVariantVisitLValueFunc < R , F > VisitLValueFuncs [ ] = { VariantVisitLValue < R , F , Types > . . . } ;
static constexpr FVariantVisitRValueFunc < R , F > VisitRValueFuncs [ ] = { VariantVisitRValue < R , F , Types > . . . } ;
static constexpr FVariantVisitConstLValueFunc < R , F > VisitConstLValueFuncs [ ] = { VariantVisitConstLValue < R , F , Types > . . . } ;
static constexpr FVariantVisitConstRValueFunc < R , F > VisitConstRValueFuncs [ ] = { VariantVisitConstRValue < R , F , Types > . . . } ;
} ;
NAMESPACE_PRIVATE_END
2022-04-22 14:28:44 +00:00
template < typename . . . Types > requires ( true & & . . . & & ( TIsObject < Types > : : Value & & ! TIsArray < Types > : : Value & & TIsDestructible < Types > : : Value ) ) & & ( sizeof . . . ( Types ) < 0xFF )
2022-03-15 11:26:31 +00:00
struct TVariant
{
2022-03-23 09:49:30 +00:00
static constexpr size_t AlternativeSize = sizeof . . . ( Types ) ;
2022-03-15 11:26:31 +00:00
template < size_t I > struct TAlternativeType : NAMESPACE_PRIVATE : : TVariantAlternativeType < I , Types . . . > { } ;
template < typename T > struct TAlternativeIndex : NAMESPACE_PRIVATE : : TVariantAlternativeIndex < T , Types . . . > { } ;
2022-04-22 14:28:44 +00:00
constexpr TVariant ( ) : TypeIndex ( 0xFF ) { } ;
2022-03-15 11:26:31 +00:00
constexpr TVariant ( FInvalid ) : TVariant ( ) { } ;
2022-03-31 04:07:15 +00:00
constexpr TVariant ( const TVariant & InValue ) requires ( true & & . . . & & TIsCopyConstructible < Types > : : Value )
2022-04-22 14:28:44 +00:00
: TypeIndex ( static_cast < uint8 > ( InValue . GetIndex ( ) ) )
2022-03-15 11:26:31 +00:00
{
2022-05-03 10:22:41 +00:00
if ( IsValid ( ) ) TypeInfos [ InValue . GetIndex ( ) ] - > CopyConstruct ( & Value , & InValue . Value ) ;
2022-03-15 11:26:31 +00:00
}
2022-03-31 04:07:15 +00:00
constexpr TVariant ( TVariant & & InValue ) requires ( true & & . . . & & TIsMoveConstructible < Types > : : Value )
2022-04-22 14:28:44 +00:00
: TypeIndex ( static_cast < uint8 > ( InValue . GetIndex ( ) ) )
2022-03-15 11:26:31 +00:00
{
2022-05-03 10:22:41 +00:00
if ( IsValid ( ) ) TypeInfos [ InValue . GetIndex ( ) ] - > MoveConstruct ( & Value , & InValue . Value ) ;
2022-03-15 11:26:31 +00:00
}
2022-03-23 09:49:30 +00:00
template < size_t I , typename . . . ArgTypes > requires ( I < AlternativeSize )
2022-03-15 11:26:31 +00:00
& & TIsConstructible < typename TAlternativeType < I > : : Type , ArgTypes . . . > : : Value
constexpr explicit TVariant ( TInPlaceIndex < I > , ArgTypes & & . . . Args )
: TypeIndex ( I )
{
using SelectedType = typename TAlternativeType < I > : : Type ;
new ( & Value ) SelectedType ( Forward < ArgTypes > ( Args ) . . . ) ;
}
2022-03-21 10:40:30 +00:00
template < typename T , typename . . . ArgTypes > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE )
2022-03-15 11:26:31 +00:00
& & TIsConstructible < typename TAlternativeType < TAlternativeIndex < T > : : Value > : : Type , ArgTypes . . . > : : Value
constexpr explicit TVariant ( TInPlaceType < T > , ArgTypes & & . . . Args )
: TVariant ( InPlaceIndex < TAlternativeIndex < T > : : Value > , Forward < ArgTypes > ( Args ) . . . )
{ }
template < typename T > requires NAMESPACE_PRIVATE : : TVariantSelectedType < typename TRemoveReference < T > : : Type , Types . . . > : : Value
2022-03-31 09:36:48 +00:00
& & ( ! TIsTInPlaceType < typename TRemoveCVRef < T > : : Type > : : Value ) & & ( ! TIsTInPlaceIndex < typename TRemoveCVRef < T > : : Type > : : Value )
2022-03-15 11:26:31 +00:00
& & ( ! TIsSame < typename TRemoveCVRef < T > : : Type , TVariant > : : Value )
constexpr TVariant ( T & & InValue ) : TVariant ( InPlaceType < typename NAMESPACE_PRIVATE : : TVariantSelectedType < typename TRemoveReference < T > : : Type , Types . . . > : : Type > , Forward < T > ( InValue ) )
{ }
constexpr ~ TVariant ( )
{
2022-03-23 09:49:30 +00:00
if constexpr ( ! ( true & & . . . & & TIsTriviallyDestructible < Types > : : Value ) ) Reset ( ) ;
2022-03-15 11:26:31 +00:00
}
2022-03-31 04:07:15 +00:00
constexpr TVariant & operator = ( const TVariant & InValue ) requires ( true & & . . . & & ( TIsCopyConstructible < Types > : : Value & & TIsCopyAssignable < Types > : : Value ) )
2022-03-15 11:26:31 +00:00
{
if ( & InValue = = this ) return * this ;
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
return * this ;
}
2022-05-03 10:22:41 +00:00
if ( GetIndex ( ) = = InValue . GetIndex ( ) ) TypeInfos [ InValue . GetIndex ( ) ] - > CopyAssign ( & Value , & InValue . Value ) ;
2022-03-15 11:26:31 +00:00
else
{
Reset ( ) ;
2022-05-03 10:22:41 +00:00
TypeInfos [ InValue . GetIndex ( ) ] - > CopyConstruct ( & Value , & InValue . Value ) ;
2022-04-22 14:28:44 +00:00
TypeIndex = static_cast < uint8 > ( InValue . GetIndex ( ) ) ;
2022-03-15 11:26:31 +00:00
}
return * this ;
}
2022-03-31 04:07:15 +00:00
constexpr TVariant & operator = ( TVariant & & InValue ) requires ( true & & . . . & & ( TIsMoveConstructible < Types > : : Value & & TIsMoveAssignable < Types > : : Value ) )
2022-03-15 11:26:31 +00:00
{
if ( & InValue = = this ) return * this ;
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
return * this ;
}
2022-05-03 10:22:41 +00:00
if ( GetIndex ( ) = = InValue . GetIndex ( ) ) TypeInfos [ InValue . GetIndex ( ) ] - > MoveAssign ( & Value , & InValue . Value ) ;
2022-03-15 11:26:31 +00:00
else
{
Reset ( ) ;
2022-05-03 10:22:41 +00:00
TypeInfos [ InValue . GetIndex ( ) ] - > MoveConstruct ( & Value , & InValue . Value ) ;
2022-04-22 14:28:44 +00:00
TypeIndex = static_cast < uint8 > ( InValue . GetIndex ( ) ) ;
2022-03-15 11:26:31 +00:00
}
return * this ;
}
template < typename T > requires NAMESPACE_PRIVATE : : TVariantSelectedType < typename TRemoveReference < T > : : Type , Types . . . > : : Value
constexpr TVariant & operator = ( T & & InValue )
{
using SelectedType = typename NAMESPACE_PRIVATE : : TVariantSelectedType < typename TRemoveReference < T > : : Type , Types . . . > : : Type ;
if ( GetIndex ( ) = = TAlternativeIndex < SelectedType > : : Value ) GetValue < SelectedType > ( ) = Forward < T > ( InValue ) ;
else
{
Reset ( ) ;
new ( & Value ) SelectedType ( Forward < T > ( InValue ) ) ;
TypeIndex = TAlternativeIndex < SelectedType > : : Value ;
}
return * this ;
}
2022-03-23 09:49:30 +00:00
template < size_t I , typename . . . ArgTypes > requires ( I < AlternativeSize )
2022-03-15 11:26:31 +00:00
& & TIsConstructible < typename TAlternativeType < I > : : Type , ArgTypes . . . > : : Value
constexpr typename TAlternativeType < I > : : Type & Emplace ( ArgTypes & & . . . Args )
{
Reset ( ) ;
using SelectedType = typename TAlternativeType < I > : : Type ;
SelectedType * Result = new ( & Value ) SelectedType ( Forward < ArgTypes > ( Args ) . . . ) ;
TypeIndex = I ;
return * Result ;
}
2022-03-17 01:22:48 +00:00
template < typename T , typename . . . ArgTypes > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE )
2022-03-15 11:26:31 +00:00
& & TIsConstructible < typename TAlternativeType < TAlternativeIndex < T > : : Value > : : Type , ArgTypes . . . > : : Value
constexpr T & Emplace ( ArgTypes & & . . . Args )
{
return Emplace < TAlternativeIndex < T > : : Value > ( Forward < ArgTypes > ( Args ) . . . ) ;
}
2022-05-03 10:22:41 +00:00
constexpr const FTypeInfo & GetTypeInfo ( ) const { return IsValid ( ) ? * TypeInfos [ GetIndex ( ) ] : Typeid ( void ) ; }
2022-04-22 14:28:44 +00:00
constexpr size_t GetIndex ( ) const { return TypeIndex ! = 0xFF ? TypeIndex : INDEX_NONE ; }
constexpr bool IsValid ( ) const { return TypeIndex ! = 0xFF ; }
constexpr explicit operator bool ( ) const { return TypeIndex ! = 0xFF ; }
2022-03-15 11:26:31 +00:00
template < size_t I > constexpr bool HoldsAlternative ( ) const { return IsValid ( ) ? GetIndex ( ) = = I : false ; }
template < typename T > constexpr bool HoldsAlternative ( ) const { return IsValid ( ) ? GetIndex ( ) = = TAlternativeIndex < T > : : Value : false ; }
2022-03-23 09:49:30 +00:00
template < size_t I > requires ( I < AlternativeSize ) constexpr typename TAlternativeType < I > : : Type & GetValue ( ) & { checkf ( HoldsAlternative < I > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return * reinterpret_cast < TAlternativeType < I > : : Type * > ( & Value ) ; }
template < size_t I > requires ( I < AlternativeSize ) constexpr typename TAlternativeType < I > : : Type & & GetValue ( ) & & { checkf ( HoldsAlternative < I > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return MoveTemp ( * reinterpret_cast < TAlternativeType < I > : : Type * > ( & Value ) ) ; }
template < size_t I > requires ( I < AlternativeSize ) constexpr const typename TAlternativeType < I > : : Type & GetValue ( ) const & { checkf ( HoldsAlternative < I > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return * reinterpret_cast < const TAlternativeType < I > : : Type * > ( & Value ) ; }
template < size_t I > requires ( I < AlternativeSize ) constexpr const typename TAlternativeType < I > : : Type & & GetValue ( ) const & & { checkf ( HoldsAlternative < I > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return MoveTemp ( * reinterpret_cast < const TAlternativeType < I > : : Type * > ( & Value ) ) ; }
2022-03-15 11:26:31 +00:00
2022-03-23 09:49:30 +00:00
template < typename T > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE ) constexpr T & GetValue ( ) & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return * reinterpret_cast < T * > ( & Value ) ; }
template < typename T > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE ) constexpr T & & GetValue ( ) & & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return MoveTemp ( * reinterpret_cast < T * > ( & Value ) ) ; }
template < typename T > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE ) constexpr const T & GetValue ( ) const & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return * reinterpret_cast < const T * > ( & Value ) ; }
template < typename T > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE ) constexpr const T & & GetValue ( ) const & & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return MoveTemp ( * reinterpret_cast < const T * > ( & Value ) ) ; }
2022-03-15 11:26:31 +00:00
2022-03-30 04:06:05 +00:00
template < size_t I > requires ( I < AlternativeSize ) constexpr typename TAlternativeType < I > : : Type & Get ( typename TAlternativeType < I > : : Type & DefaultValue ) & { return HoldsAlternative < I > ( ) ? GetValue < I > ( ) : DefaultValue ; }
2022-03-23 09:49:30 +00:00
template < size_t I > requires ( I < AlternativeSize ) constexpr const typename TAlternativeType < I > : : Type & Get ( const typename TAlternativeType < I > : : Type & DefaultValue ) const & { return HoldsAlternative < I > ( ) ? GetValue < I > ( ) : DefaultValue ; }
2022-03-15 11:26:31 +00:00
2022-03-30 04:06:05 +00:00
template < typename T > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE ) constexpr T & Get ( T & DefaultValue ) & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
2022-03-23 09:49:30 +00:00
template < typename T > requires ( TAlternativeIndex < T > : : Value ! = INDEX_NONE ) constexpr const T & Get ( const T & DefaultValue ) const & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
2022-03-15 11:26:31 +00:00
2022-03-23 09:49:30 +00:00
template < typename F > requires ( true & & . . . & & TIsInvocable < F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr auto Visit ( F & & Func ) &
{
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return ReturnType ( NAMESPACE_PRIVATE : : TVariantVisitHelper < ReturnType , F , Types . . . > : : VisitLValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-23 09:49:30 +00:00
template < typename F > requires ( true & & . . . & & TIsInvocable < F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr auto Visit ( F & & Func ) & &
{
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return ReturnType ( NAMESPACE_PRIVATE : : TVariantVisitHelper < ReturnType , F , Types . . . > : : VisitRValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-23 09:49:30 +00:00
template < typename F > requires ( true & & . . . & & TIsInvocable < F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr auto Visit ( F & & Func ) const &
{
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return ReturnType ( NAMESPACE_PRIVATE : : TVariantVisitHelper < ReturnType , F , Types . . . > : : VisitConstLValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-23 09:49:30 +00:00
template < typename F > requires ( true & & . . . & & TIsInvocable < F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr auto Visit ( F & & Func ) const & &
{
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return ReturnType ( NAMESPACE_PRIVATE : : TVariantVisitHelper < ReturnType , F , Types . . . > : : VisitConstRValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr R Visit ( F & & Func ) &
{
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return R ( NAMESPACE_PRIVATE : : TVariantVisitHelper < R , F , Types . . . > : : VisitLValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr R Visit ( F & & Func ) & &
{
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return R ( NAMESPACE_PRIVATE : : TVariantVisitHelper < R , F , Types . . . > : : VisitRValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr R Visit ( F & & Func ) const &
{
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return R ( NAMESPACE_PRIVATE : : TVariantVisitHelper < R , F , Types . . . > : : VisitConstLValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-03-15 11:26:31 +00:00
constexpr R Visit ( F & & Func ) const & &
{
2022-04-26 15:04:50 +00:00
checkf ( IsValid ( ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
2022-03-15 11:26:31 +00:00
return R ( NAMESPACE_PRIVATE : : TVariantVisitHelper < R , F , Types . . . > : : VisitConstRValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
constexpr void Reset ( )
{
2022-03-17 01:22:48 +00:00
if ( GetIndex ( ) = = INDEX_NONE ) return ;
2022-03-15 11:26:31 +00:00
2022-03-23 09:49:30 +00:00
if constexpr ( ! ( true & & . . . & & TIsTriviallyDestructible < Types > : : Value ) )
{
2022-05-03 10:22:41 +00:00
TypeInfos [ GetIndex ( ) ] - > Destroy ( & Value ) ;
2022-03-23 09:49:30 +00:00
}
2022-03-15 11:26:31 +00:00
2022-04-22 14:28:44 +00:00
TypeIndex = static_cast < uint8 > ( INDEX_NONE ) ;
2022-03-15 11:26:31 +00:00
}
2022-04-22 14:28:44 +00:00
constexpr size_t GetTypeHash ( ) const requires ( true & & . . . & & CHashable < Types > )
{
if ( ! IsValid ( ) ) return 114514 ;
2022-05-03 10:22:41 +00:00
return HashCombine ( NAMESPACE_REDCRAFT : : GetTypeHash ( GetIndex ( ) ) , TypeInfos [ GetIndex ( ) ] - > HashItem ( & Value ) ) ;
2022-04-22 14:28:44 +00:00
}
2022-04-14 14:41:22 +00:00
constexpr void Swap ( TVariant & InValue ) requires ( true & & . . . & & ( TIsMoveConstructible < Types > : : Value & & TIsSwappable < Types > : : Value ) )
{
if ( ! IsValid ( ) & & ! InValue . IsValid ( ) ) return ;
if ( IsValid ( ) & & ! InValue . IsValid ( ) )
{
InValue = MoveTemp ( * this ) ;
Reset ( ) ;
return ;
}
if ( InValue . IsValid ( ) & & ! IsValid ( ) )
{
* this = MoveTemp ( InValue ) ;
InValue . Reset ( ) ;
return ;
}
if ( GetIndex ( ) = = InValue . GetIndex ( ) )
{
2022-05-03 10:22:41 +00:00
TypeInfos [ GetIndex ( ) ] - > SwapItem ( & Value , & InValue . Value ) ;
2022-04-14 14:41:22 +00:00
return ;
}
TVariant Temp = MoveTemp ( * this ) ;
* this = MoveTemp ( InValue ) ;
InValue = MoveTemp ( Temp ) ;
}
2022-03-15 11:26:31 +00:00
private :
2022-05-03 10:22:41 +00:00
static constexpr const FTypeInfo * TypeInfos [ ] = { & Typeid ( Types ) . . . } ;
2022-03-15 11:26:31 +00:00
TAlignedUnion < 1 , Types . . . > : : Type Value ;
2022-04-22 14:28:44 +00:00
uint8 TypeIndex ;
2022-03-15 11:26:31 +00:00
2022-03-31 04:07:15 +00:00
friend constexpr bool operator = = ( const TVariant & LHS , const TVariant & RHS ) requires ( true & & . . . & & CEqualityComparable < Types > )
2022-03-15 11:26:31 +00:00
{
if ( LHS . GetIndex ( ) ! = RHS . GetIndex ( ) ) return false ;
if ( LHS . IsValid ( ) = = false ) return true ;
2022-05-03 10:22:41 +00:00
return TypeInfos [ LHS . GetIndex ( ) ] - > EqualityCompare ( & LHS . Value , & RHS . Value ) ;
}
friend constexpr partial_ordering operator < = > ( const TVariant & LHS , const TVariant & RHS ) requires ( true & & . . . & & CSynthThreeWayComparable < Types > )
{
if ( LHS . GetIndex ( ) ! = RHS . GetIndex ( ) ) return partial_ordering : : unordered ;
if ( LHS . IsValid ( ) = = false ) return partial_ordering : : equivalent ;
return TypeInfos [ LHS . GetIndex ( ) ] - > SynthThreeWayCompare ( & LHS . Value , & RHS . Value ) ;
2022-03-15 11:26:31 +00:00
}
} ;
2022-03-31 04:07:15 +00:00
template < typename T , typename . . . Types > requires ( ! TIsSame < T , TVariant < Types . . . > > : : Value ) & & CEqualityComparable < T >
2022-03-15 11:26:31 +00:00
constexpr bool operator = = ( const TVariant < Types . . . > & LHS , const T & RHS )
{
return LHS . template HoldsAlternative < T > ( ) ? LHS . template GetValue < T > ( ) = = RHS : false ;
}
2022-03-22 03:12:05 +00:00
template < typename . . . Types >
constexpr bool operator = = ( const TVariant < Types . . . > & LHS , FInvalid )
{
return ! LHS . IsValid ( ) ;
}
2022-03-31 09:36:48 +00:00
template < typename T > struct TIsTVariant : FFalse { } ;
template < typename . . . Types > struct TIsTVariant < TVariant < Types . . . > > : FTrue { } ;
2022-03-15 11:26:31 +00:00
2022-03-31 09:36:48 +00:00
template < typename VariantType > requires TIsTVariant < typename TRemoveCVRef < VariantType > : : Type > : : Value
2022-03-30 04:06:05 +00:00
struct TVariantAlternativeSize : TConstant < size_t , VariantType : : AlternativeSize > { } ;
2022-03-31 09:36:48 +00:00
template < size_t I , typename VariantType > requires TIsTVariant < typename TRemoveCVRef < VariantType > : : Type > : : Value
2022-03-15 11:26:31 +00:00
struct TVariantAlternativeType { using Type = typename TCopyCV < typename TRemoveReference < VariantType > : : Type , typename TRemoveCVRef < VariantType > : : Type : : template TAlternativeType < I > : : Type > : : Type ; } ;
2022-03-31 09:36:48 +00:00
template < typename T , typename VariantType > requires TIsTVariant < typename TRemoveCVRef < VariantType > : : Type > : : Value
2022-03-15 11:26:31 +00:00
struct TVariantAlternativeIndex : VariantType : : template TAlternativeIndex < T > { } ;
NAMESPACE_MODULE_END ( Utility )
NAMESPACE_MODULE_END ( Redcraft )
NAMESPACE_REDCRAFT_END