2022-03-15 11:26:31 +00:00
# pragma once
# include "CoreTypes.h"
# include "Templates/Invoke.h"
2022-03-31 08:40:31 +00:00
# include "Templates/TypeHash.h"
2022-03-15 11:26:31 +00:00
# include "Templates/Utility.h"
# include "TypeTraits/TypeTraits.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 T >
constexpr void VariantDestroy ( void * InValue )
{
2022-03-23 09:49:30 +00:00
if constexpr ( ! TIsTriviallyDestructible < T > : : Value )
2022-03-15 11:26:31 +00:00
{
typedef T DestructOptionalType ;
reinterpret_cast < T * > ( InValue ) - > DestructOptionalType : : ~ DestructOptionalType ( ) ;
}
}
using FVariantDestroyFunc = void ( * ) ( void * ) ;
template < typename T >
constexpr void VariantCopyConstruct ( void * Target , const void * Source )
{
if constexpr ( ! TIsCopyConstructible < T > : : Value | | TIsConst < T > : : Value ) check_no_entry ( ) ;
2022-03-21 10:40:30 +00:00
else new ( reinterpret_cast < T * > ( Target ) ) T ( * reinterpret_cast < const T * > ( Source ) ) ;
2022-03-15 11:26:31 +00:00
}
using FVariantCopyConstructFunc = void ( * ) ( void * , const void * ) ;
template < typename T >
constexpr void VariantMoveConstruct ( void * Target , void * Source )
{
if constexpr ( ! TIsMoveConstructible < T > : : Value | | TIsConst < T > : : Value ) check_no_entry ( ) ;
2022-03-21 10:40:30 +00:00
else new ( reinterpret_cast < T * > ( Target ) ) T ( MoveTemp ( * reinterpret_cast < T * > ( Source ) ) ) ;
2022-03-15 11:26:31 +00:00
}
using FVariantMoveConstructFunc = void ( * ) ( void * , void * ) ;
template < typename T >
constexpr void VariantCopyAssign ( void * Target , const void * Source )
{
if constexpr ( ! TIsCopyAssignable < T > : : Value | | TIsConst < T > : : Value ) check_no_entry ( ) ;
2022-03-21 10:40:30 +00:00
else * reinterpret_cast < T * > ( Target ) = * reinterpret_cast < const T * > ( Source ) ;
2022-03-15 11:26:31 +00:00
}
using FVariantCopyAssignFunc = void ( * ) ( void * , const void * ) ;
template < typename T >
constexpr void VariantMoveAssign ( void * Target , void * Source )
{
if constexpr ( ! TIsMoveAssignable < T > : : Value | | TIsConst < T > : : Value ) check_no_entry ( ) ;
2022-03-21 10:40:30 +00:00
else * reinterpret_cast < T * > ( Target ) = MoveTemp ( * reinterpret_cast < T * > ( Source ) ) ;
2022-03-15 11:26:31 +00:00
}
using FVariantMoveAssignFunc = void ( * ) ( void * , void * ) ;
template < typename T >
constexpr bool VariantEqualityOperator ( const void * LHS , const void * RHS )
{
if constexpr ( ! CEqualityComparable < T > ) check_no_entry ( ) ;
else return * reinterpret_cast < const T * > ( LHS ) = = * reinterpret_cast < const T * > ( RHS ) ;
return false ;
}
using FVariantEqualityOperatorFunc = bool ( * ) ( const void * , const void * ) ;
template < typename T >
constexpr bool VariantInequalityOperator ( const void * LHS , const void * RHS )
{
if constexpr ( ! CEqualityComparable < T > ) check_no_entry ( ) ;
else return * reinterpret_cast < const T * > ( LHS ) ! = * reinterpret_cast < const T * > ( RHS ) ;
return false ;
}
using FVariantInequalityOperatorFunc = bool ( * ) ( const void * , const void * ) ;
template < typename . . . Types >
struct TVariantHelper
{
static constexpr FVariantDestroyFunc DestroyFuncs [ ] = { VariantDestroy < Types > . . . } ;
static constexpr FVariantCopyConstructFunc CopyConstructFuncs [ ] = { VariantCopyConstruct < Types > . . . } ;
static constexpr FVariantMoveConstructFunc MoveConstructFuncs [ ] = { VariantMoveConstruct < Types > . . . } ;
static constexpr FVariantCopyAssignFunc CopyAssignFuncs [ ] = { VariantCopyAssign < Types > . . . } ;
static constexpr FVariantMoveAssignFunc MoveAssignFuncs [ ] = { VariantMoveAssign < Types > . . . } ;
static constexpr FVariantEqualityOperatorFunc EqualityOperatorFuncs [ ] = { VariantEqualityOperator < Types > . . . } ;
static constexpr FVariantInequalityOperatorFunc InequalityOperatorFuncs [ ] = { VariantInequalityOperator < Types > . . . } ;
} ;
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-03-21 10:40:30 +00:00
template < typename . . . Types > requires ( true & & . . . & & ( TIsObject < Types > : : Value & & ! TIsArray < Types > : : Value & & TIsDestructible < Types > : : Value ) )
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-03-17 01:22:48 +00:00
constexpr TVariant ( ) : TypeIndex ( INDEX_NONE ) { } ;
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-03-15 11:26:31 +00:00
: TypeIndex ( InValue . GetIndex ( ) )
{
2022-03-17 01:22:48 +00:00
if ( GetIndex ( ) ! = INDEX_NONE ) FHelper : : CopyConstructFuncs [ InValue . GetIndex ( ) ] ( & 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-03-15 11:26:31 +00:00
: TypeIndex ( InValue . GetIndex ( ) )
{
2022-03-17 01:22:48 +00:00
if ( GetIndex ( ) ! = INDEX_NONE ) FHelper : : MoveConstructFuncs [ InValue . GetIndex ( ) ] ( & 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
& & ( ! TIsInPlaceTypeSpecialization < typename TRemoveCVRef < T > : : Type > : : Value ) & & ( ! TIsInPlaceIndexSpecialization < typename TRemoveCVRef < T > : : Type > : : Value )
& & ( ! 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 ;
}
if ( GetIndex ( ) = = InValue . GetIndex ( ) ) FHelper : : CopyAssignFuncs [ InValue . GetIndex ( ) ] ( & Value , & InValue . Value ) ;
else
{
Reset ( ) ;
FHelper : : CopyConstructFuncs [ InValue . GetIndex ( ) ] ( & Value , & InValue . Value ) ;
TypeIndex = InValue . GetIndex ( ) ;
}
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 ;
}
if ( GetIndex ( ) = = InValue . GetIndex ( ) ) FHelper : : MoveAssignFuncs [ InValue . GetIndex ( ) ] ( & Value , & InValue . Value ) ;
else
{
Reset ( ) ;
FHelper : : MoveConstructFuncs [ InValue . GetIndex ( ) ] ( & Value , & InValue . Value ) ;
TypeIndex = InValue . GetIndex ( ) ;
}
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 ) . . . ) ;
}
constexpr size_t GetIndex ( ) const { return TypeIndex ; }
2022-03-17 01:22:48 +00:00
constexpr bool IsValid ( ) const { return GetIndex ( ) ! = INDEX_NONE ; }
constexpr explicit operator bool ( ) const { return GetIndex ( ) ! = INDEX_NONE ; }
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 ; }
constexpr void * GetData ( ) { return & Value ; }
constexpr const void * GetData ( ) const { return & Value ; }
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 ;
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
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 ;
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
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 ;
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
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 ;
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
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 ) &
{
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
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 ) & &
{
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
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 &
{
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
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 & &
{
checkf ( IsValid ( ) , " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ;
return R ( NAMESPACE_PRIVATE : : TVariantVisitHelper < R , F , Types . . . > : : VisitConstRValueFuncs [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ) ;
}
2022-03-31 08:40:31 +00:00
constexpr size_t GetTypeHash ( ) const requires ( true & & . . . & & CHashable < Types > )
{
if ( ! IsValid ( ) ) return NAMESPACE_REDCRAFT : : GetTypeHash ( nullptr ) ;
return Visit ( [ ] ( auto & & A ) { return NAMESPACE_REDCRAFT : : GetTypeHash ( A ) ; } ) ;
}
2022-03-15 11:26:31 +00:00
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 ) )
{
FHelper : : DestroyFuncs [ GetIndex ( ) ] ( & Value ) ;
}
2022-03-15 11:26:31 +00:00
2022-03-17 01:22:48 +00:00
TypeIndex = INDEX_NONE ;
2022-03-15 11:26:31 +00:00
}
private :
using FHelper = NAMESPACE_PRIVATE : : TVariantHelper < Types . . . > ;
TAlignedUnion < 1 , Types . . . > : : Type Value ;
size_t TypeIndex ;
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 ;
return FHelper : : EqualityOperatorFuncs [ LHS . GetIndex ( ) ] ( & LHS . Value , & RHS . Value ) ;
}
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 true ;
if ( LHS . IsValid ( ) = = false ) return false ;
return FHelper : : InequalityOperatorFuncs [ LHS . GetIndex ( ) ] ( & LHS . Value , & RHS . Value ) ;
}
} ;
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-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 : true ;
}
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 T & LHS , const TVariant < Types . . . > & RHS )
{
return RHS . template HoldsAlternative < T > ( ) ? LHS = = RHS . template GetValue < T > ( ) : false ;
}
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 T & LHS , const TVariant < Types . . . > & RHS )
{
return RHS . template HoldsAlternative < T > ( ) ? LHS ! = RHS . template GetValue < T > ( ) : true ;
}
2022-03-22 03:12:05 +00:00
template < typename . . . Types >
constexpr bool operator = = ( const TVariant < Types . . . > & LHS , FInvalid )
{
return ! LHS . IsValid ( ) ;
}
template < typename . . . Types >
constexpr bool operator ! = ( const TVariant < Types . . . > & LHS , FInvalid )
{
return LHS . IsValid ( ) ;
}
template < typename . . . Types >
constexpr bool operator = = ( FInvalid , const TVariant < Types . . . > & RHS )
{
return ! RHS . IsValid ( ) ;
}
template < typename . . . Types >
constexpr bool operator ! = ( FInvalid , const TVariant < Types . . . > & RHS )
{
return RHS . IsValid ( ) ;
}
2022-03-15 11:26:31 +00:00
template < typename . . . Types > requires ( true & & . . . & & ( TIsMoveConstructible < Types > : : Value & & TIsSwappable < Types > : : Value ) )
constexpr void Swap ( TVariant < Types . . . > & A , TVariant < Types . . . > & B )
{
if ( ! A & & ! B ) return ;
if ( A & & ! B )
{
B = MoveTemp ( A ) ;
A . Reset ( ) ;
return ;
}
if ( B & & ! A )
{
A = MoveTemp ( B ) ;
B . Reset ( ) ;
return ;
}
TVariant < Types . . . > Temp = MoveTemp ( A ) ;
A = MoveTemp ( B ) ;
B = MoveTemp ( Temp ) ;
}
template < typename T > struct TIsVariantSpecialization : FFalse { } ;
template < typename . . . Types > struct TIsVariantSpecialization < TVariant < Types . . . > > : FTrue { } ;
2022-03-30 04:06:05 +00:00
template < typename VariantType > requires TIsVariantSpecialization < typename TRemoveCVRef < VariantType > : : Type > : : Value
struct TVariantAlternativeSize : TConstant < size_t , VariantType : : AlternativeSize > { } ;
2022-03-15 11:26:31 +00:00
template < size_t I , typename VariantType > requires TIsVariantSpecialization < typename TRemoveCVRef < VariantType > : : Type > : : Value
struct TVariantAlternativeType { using Type = typename TCopyCV < typename TRemoveReference < VariantType > : : Type , typename TRemoveCVRef < VariantType > : : Type : : template TAlternativeType < I > : : Type > : : Type ; } ;
template < typename T , typename VariantType > requires TIsVariantSpecialization < typename TRemoveCVRef < VariantType > : : Type > : : Value
struct TVariantAlternativeIndex : VariantType : : template TAlternativeIndex < T > { } ;
NAMESPACE_MODULE_END ( Utility )
NAMESPACE_MODULE_END ( Redcraft )
NAMESPACE_REDCRAFT_END