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-12 15:36:32 +00:00
# include "Memory/MemoryOperator.h"
2022-05-03 10:22:41 +00:00
# include "Miscellaneous/Compare.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 ;
} ;
NAMESPACE_PRIVATE_END
2022-05-15 14:56:53 +00:00
template < typename . . . Types > requires ( true & & . . . & & 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-12 15:36:32 +00:00
if ( IsValid ( ) ) CopyConstructImpl [ 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-04-22 14:28:44 +00:00
: TypeIndex ( static_cast < uint8 > ( InValue . GetIndex ( ) ) )
2022-03-15 11:26:31 +00:00
{
2022-05-12 15:36:32 +00:00
if ( IsValid ( ) ) MoveConstructImpl [ 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
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-12 15:36:32 +00:00
if ( GetIndex ( ) = = InValue . GetIndex ( ) ) CopyAssignImpl [ InValue . GetIndex ( ) ] ( & Value , & InValue . Value ) ;
2022-03-15 11:26:31 +00:00
else
{
Reset ( ) ;
2022-05-12 15:36:32 +00:00
CopyConstructImpl [ InValue . GetIndex ( ) ] ( & 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-12 15:36:32 +00:00
if ( GetIndex ( ) = = InValue . GetIndex ( ) ) MoveAssignImpl [ InValue . GetIndex ( ) ] ( & Value , & InValue . Value ) ;
2022-03-15 11:26:31 +00:00
else
{
Reset ( ) ;
2022-05-12 15:36:32 +00:00
MoveConstructImpl [ InValue . GetIndex ( ) ] ( & 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-12 15:36:32 +00:00
constexpr const type_info & GetTypeInfo ( ) const { return IsValid ( ) ? * TypeInfos [ GetIndex ( ) ] : typeid ( void ) ; }
2022-05-03 10:22:41 +00:00
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-05-12 15:36:32 +00:00
FORCEINLINE decltype ( auto ) Visit ( F & & Func ) &
2022-03-15 11:26:31 +00:00
{
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-05-12 15:36:32 +00:00
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
using FInvokeImpl = ReturnType ( * ) ( F & & , void * ) ;
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , * reinterpret_cast < Types * > ( This ) ) ; } . . . } ;
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
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-05-12 15:36:32 +00:00
FORCEINLINE decltype ( auto ) Visit ( F & & Func ) & &
2022-03-15 11:26:31 +00:00
{
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-05-12 15:36:32 +00:00
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
using FInvokeImpl = ReturnType ( * ) ( F & & , void * ) ;
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < Types * > ( This ) ) ) ; } . . . } ;
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
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-05-12 15:36:32 +00:00
FORCEINLINE decltype ( auto ) Visit ( F & & Func ) const &
2022-03-15 11:26:31 +00:00
{
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-05-12 15:36:32 +00:00
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
using FInvokeImpl = ReturnType ( * ) ( F & & , const void * ) ;
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , const void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , * reinterpret_cast < const Types * > ( This ) ) ; } . . . } ;
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
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-05-12 15:36:32 +00:00
FORCEINLINE decltype ( auto ) Visit ( F & & Func ) const & &
2022-03-15 11:26:31 +00:00
{
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-05-12 15:36:32 +00:00
using ReturnType = typename TCommonType < typename TInvokeResult < F , Types > : : Type . . . > : : Type ;
using FInvokeImpl = ReturnType ( * ) ( F & & , const void * ) ;
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , const void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < const Types * > ( This ) ) ) ; } . . . } ;
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
2022-03-15 11:26:31 +00:00
}
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-05-12 15:36:32 +00:00
FORCEINLINE R Visit ( F & & Func ) & { return Visit ( Forward < F > ( Func ) ) ; }
2022-03-15 11:26:31 +00:00
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-05-12 15:36:32 +00:00
FORCEINLINE R Visit ( F & & Func ) & & { return MoveTemp ( * this ) . Visit ( Forward < F > ( Func ) ) ; }
2022-03-15 11:26:31 +00:00
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-05-12 15:36:32 +00:00
FORCEINLINE R Visit ( F & & Func ) const & { return Visit ( Forward < F > ( Func ) ) ; }
2022-03-15 11:26:31 +00:00
2022-03-23 09:49:30 +00:00
template < typename R , typename F > requires ( true & & . . . & & TIsInvocableResult < R , F , Types > : : Value )
2022-05-12 15:36:32 +00:00
FORCEINLINE R Visit ( F & & Func ) const & & { return MoveTemp ( * this ) . Visit ( Forward < F > ( Func ) ) ; }
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 ) )
{
2022-05-12 15:36:32 +00:00
DestroyImpl [ GetIndex ( ) ] ( & 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-12 15:36:32 +00:00
using NAMESPACE_REDCRAFT : : GetTypeHash ;
using FHashImpl = size_t ( * ) ( const void * ) ;
constexpr FHashImpl HashImpl [ ] = { [ ] ( const void * This ) - > size_t { return GetTypeHash ( * reinterpret_cast < const Types * > ( This ) ) ; } . . . } ;
return HashCombine ( GetTypeHash ( GetIndex ( ) ) , HashImpl [ GetIndex ( ) ] ( & 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-12 15:36:32 +00:00
using NAMESPACE_REDCRAFT : : Swap ;
using FSwapImpl = void ( * ) ( void * , void * ) ;
constexpr FSwapImpl SwapImpl [ ] = { [ ] ( void * A , void * B ) { Swap ( * reinterpret_cast < Types * > ( A ) , * reinterpret_cast < Types * > ( B ) ) ; } . . . } ;
SwapImpl [ GetIndex ( ) ] ( & 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
2022-05-12 15:36:32 +00:00
static constexpr const type_info * TypeInfos [ ] = { & typeid ( Types ) . . . } ;
using FCopyConstructImpl = void ( * ) ( void * , const void * ) ;
using FMoveConstructImpl = void ( * ) ( void * , void * ) ;
using FCopyAssignImpl = void ( * ) ( void * , const void * ) ;
using FMoveAssignImpl = void ( * ) ( void * , void * ) ;
using FDestroyImpl = void ( * ) ( void * ) ;
static constexpr FCopyConstructImpl CopyConstructImpl [ ] = { [ ] ( void * A , const void * B ) { if constexpr ( requires ( Types * A , const Types * B ) { Memory : : CopyConstruct ( A , B ) ; } ) Memory : : CopyConstruct ( reinterpret_cast < Types * > ( A ) , reinterpret_cast < const Types * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not copy constructible. " ) , typeid ( Types ) . name ( ) ) ; } . . . } ;
static constexpr FMoveConstructImpl MoveConstructImpl [ ] = { [ ] ( void * A , void * B ) { if constexpr ( requires ( Types * A , Types * B ) { Memory : : MoveConstruct ( A , B ) ; } ) Memory : : MoveConstruct ( reinterpret_cast < Types * > ( A ) , reinterpret_cast < Types * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not move constructible. " ) , typeid ( Types ) . name ( ) ) ; } . . . } ;
static constexpr FCopyAssignImpl CopyAssignImpl [ ] = { [ ] ( void * A , const void * B ) { if constexpr ( requires ( Types * A , const Types * B ) { Memory : : CopyAssign ( A , B ) ; } ) Memory : : CopyAssign ( reinterpret_cast < Types * > ( A ) , reinterpret_cast < const Types * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not copy assignable. " ) , typeid ( Types ) . name ( ) ) ; } . . . } ;
static constexpr FMoveAssignImpl MoveAssignImpl [ ] = { [ ] ( void * A , void * B ) { if constexpr ( requires ( Types * A , Types * B ) { Memory : : MoveAssign ( A , B ) ; } ) Memory : : MoveAssign ( reinterpret_cast < Types * > ( A ) , reinterpret_cast < Types * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not move assignable. " ) , typeid ( Types ) . name ( ) ) ; } . . . } ;
static constexpr FDestroyImpl DestroyImpl [ ] = { [ ] ( void * A ) { if constexpr ( requires ( Types * A ) { Memory : : Destruct ( A ) ; } ) Memory : : Destruct ( reinterpret_cast < Types * > ( A ) ) ; else checkf ( false , TEXT ( " The type '%s' is not destructible. " ) , typeid ( Types ) . name ( ) ) ; } . . . } ;
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-12 15:36:32 +00:00
using FCompareImpl = bool ( * ) ( const void * , const void * ) ;
constexpr FCompareImpl CompareImpl [ ] = { [ ] ( const void * LHS , const void * RHS ) - > bool { return * reinterpret_cast < const Types * > ( LHS ) = = * reinterpret_cast < const Types * > ( RHS ) ; } . . . } ;
return CompareImpl [ LHS . GetIndex ( ) ] ( & LHS . Value , & RHS . Value ) ;
2022-05-03 10:22:41 +00:00
}
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 ;
2022-05-12 15:36:32 +00:00
using FCompareImpl = partial_ordering ( * ) ( const void * , const void * ) ;
constexpr FCompareImpl CompareImpl [ ] = { [ ] ( const void * LHS , const void * RHS ) - > partial_ordering { return SynthThreeWayCompare ( * reinterpret_cast < const Types * > ( LHS ) , * reinterpret_cast < const Types * > ( RHS ) ) ; } . . . } ;
return CompareImpl [ LHS . GetIndex ( ) ] ( & 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