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-12-03 15:11:05 +00:00
# include "Templates/Meta.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 )
2022-11-17 10:48:20 +00:00
template < typename . . . Ts > requires ( sizeof . . . ( Ts ) > 0 & & ( true & & . . . & & CDestructible < Ts > ) )
2022-11-15 11:28:43 +00:00
class TVariant ;
2022-06-16 15:37:29 +00:00
2022-03-15 11:26:31 +00:00
NAMESPACE_PRIVATE_BEGIN
2022-11-17 10:48:20 +00:00
template < typename T > struct TIsTVariant : FFalse { } ;
2022-11-16 11:13:37 +00:00
template < typename . . . Ts > struct TIsTVariant < TVariant < Ts . . . > > : FTrue { } ;
2022-06-16 15:37:29 +00:00
2022-12-03 15:11:05 +00:00
template < typename VariantType >
2022-06-16 15:37:29 +00:00
struct TVariantNumImpl ;
2022-11-16 11:13:37 +00:00
template < typename . . . Ts >
2022-12-03 15:11:05 +00:00
struct TVariantNumImpl < TVariant < Ts . . . > > : TConstant < size_t , Meta : : TSize < TTypeSequence < Ts . . . > > > { } ;
2022-06-16 15:37:29 +00:00
2022-12-03 15:11:05 +00:00
template < typename T , typename VariantType >
2022-06-16 15:37:29 +00:00
struct TVariantIndexImpl ;
2022-03-15 11:26:31 +00:00
2022-11-16 11:13:37 +00:00
template < typename T , typename . . . Ts >
2022-12-03 15:11:05 +00:00
struct TVariantIndexImpl < T , TVariant < Ts . . . > > : TConstant < size_t , Meta : : TIndex < T , TTypeSequence < Ts . . . > > > { } ;
2022-06-16 15:37:29 +00:00
2022-12-03 15:11:05 +00:00
template < size_t I , typename VariantType >
2022-06-16 15:37:29 +00:00
struct TVariantAlternativeImpl ;
2022-03-15 11:26:31 +00:00
2022-12-03 15:11:05 +00:00
template < size_t I , typename . . . Ts >
struct TVariantAlternativeImpl < I , TVariant < Ts . . . > >
2022-03-15 11:26:31 +00:00
{
2022-12-03 15:11:05 +00:00
using Type = Meta : : TType < I , TTypeSequence < Ts . . . > > ;
2022-03-15 11:26:31 +00:00
} ;
2022-12-03 15:12:29 +00:00
template < typename T , typename TSequence >
struct TVariantOverloadType
2022-03-15 11:26:31 +00:00
{
2022-12-03 15:12:29 +00:00
using FrontType = Meta : : TFront < TSequence > ;
using NextSequence = Meta : : TPop < TSequence > ;
using NextUniqueSequence = typename TVariantOverloadType < T , NextSequence > : : Type ;
2022-03-15 11:26:31 +00:00
2022-12-03 15:12:29 +00:00
// T_i x[] = { Forward<T>(t) };
static constexpr bool bConditional = requires { DeclVal < void ( FrontType ( & & ) [ 1 ] ) > ( ) ( { DeclVal < T > ( ) } ) ; } ;
2022-03-15 11:26:31 +00:00
2022-12-03 15:12:29 +00:00
using Type = TConditional < bConditional , Meta : : TPush < FrontType , NextUniqueSequence > , NextUniqueSequence > ;
2022-03-15 11:26:31 +00:00
} ;
template < typename T >
2022-12-03 15:12:29 +00:00
struct TVariantOverloadType < T , TTypeSequence < > >
2022-03-15 11:26:31 +00:00
{
2022-12-03 15:12:29 +00:00
using Type = TTypeSequence < > ;
2022-03-15 11:26:31 +00:00
} ;
2022-12-03 15:12:29 +00:00
template < typename T , typename . . . Ts >
using TVariantSelectedType = Meta : : TOverloadResolution < T , typename NAMESPACE_PRIVATE : : TVariantOverloadType < T , TTypeSequence < Ts . . . > > : : Type > ;
2022-03-15 11:26:31 +00:00
NAMESPACE_PRIVATE_END
2022-06-16 15:37:29 +00:00
template < typename T >
2022-11-17 12:57:54 +00:00
concept CTVariant = NAMESPACE_PRIVATE : : TIsTVariant < TRemoveCV < T > > : : Value ;
2022-06-16 15:37:29 +00:00
2022-11-17 12:57:54 +00:00
template < CTVariant T >
2022-12-03 15:11:05 +00:00
inline constexpr size_t TVariantNum = NAMESPACE_PRIVATE : : TVariantNumImpl < TRemoveCV < T > > : : Value ;
2022-06-16 15:37:29 +00:00
2022-11-17 12:57:54 +00:00
template < typename T , CTVariant U >
2022-12-03 15:11:05 +00:00
inline constexpr size_t TVariantIndex = NAMESPACE_PRIVATE : : TVariantIndexImpl < T , TRemoveCV < U > > : : Value ;
2022-03-15 11:26:31 +00:00
2022-11-17 12:57:54 +00:00
template < size_t I , CTVariant U >
2022-12-03 15:11:05 +00:00
using TVariantAlternative = TCopyCV < U , typename NAMESPACE_PRIVATE : : TVariantAlternativeImpl < I , TRemoveCV < U > > : : Type > ;
2022-03-15 11:26:31 +00:00
2022-11-17 10:48:20 +00:00
template < typename . . . Ts > requires ( sizeof . . . ( Ts ) > 0 & & ( true & & . . . & & CDestructible < Ts > ) )
2022-11-15 11:28:43 +00:00
class TVariant
2022-06-16 15:37:29 +00:00
{
2022-11-15 11:28:43 +00:00
public :
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant ( ) : TypeIndex ( 0xFF ) { } ;
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant ( FInvalid ) : TVariant ( ) { } ;
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant ( const TVariant & InValue ) requires ( true & & . . . & & CTriviallyCopyConstructible < Ts > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant ( const TVariant & InValue ) requires ( ( true & & . . . & & CCopyConstructible < Ts > ) & & ! ( true & & . . . & & CTriviallyCopyConstructible < Ts > ) )
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-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant ( TVariant & & InValue ) requires ( true & & . . . & & CTriviallyMoveConstructible < Ts > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant ( TVariant & & InValue ) requires ( ( true & & . . . & & CMoveConstructible < Ts > ) & & ! ( true & & . . . & & CTriviallyMoveConstructible < Ts > ) )
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-11-16 14:03:54 +00:00
template < size_t I , typename . . . ArgTypes > requires ( I < sizeof . . . ( Ts )
& & CConstructibleFrom < TVariantAlternative < I , TVariant < Ts . . . > > , ArgTypes . . . > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr explicit TVariant ( TInPlaceIndex < I > , ArgTypes & & . . . Args )
2022-03-15 11:26:31 +00:00
: TypeIndex ( I )
{
2022-11-16 11:13:37 +00:00
using SelectedType = TVariantAlternative < I , TVariant < Ts . . . > > ;
2022-12-12 14:07:12 +00:00
new ( & Value ) SelectedType ( Forward < ArgTypes > ( Args ) . . . ) ;
2022-03-15 11:26:31 +00:00
}
2022-11-16 14:03:54 +00:00
template < typename T , typename . . . ArgTypes > requires ( CConstructibleFrom < T , ArgTypes . . . > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr explicit TVariant ( TInPlaceType < T > , ArgTypes & & . . . Args )
2022-11-16 11:13:37 +00:00
: TVariant ( InPlaceIndex < TVariantIndex < T , TVariant < Ts . . . > > > , Forward < ArgTypes > ( Args ) . . . )
2022-03-15 11:26:31 +00:00
{ }
2022-12-03 15:12:29 +00:00
template < typename T > requires ( requires { typename NAMESPACE_PRIVATE : : TVariantSelectedType < T , Ts . . . > ; }
2022-11-16 14:03:54 +00:00
& & ! CTInPlaceType < TRemoveCVRef < T > > & & ! CTInPlaceIndex < TRemoveCVRef < T > >
2022-11-21 15:28:19 +00:00
& & ! CBaseOf < TVariant , TRemoveCVRef < T > > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant ( T & & InValue ) : TVariant ( InPlaceType < NAMESPACE_PRIVATE : : TVariantSelectedType < T , Ts . . . > > , Forward < T > ( InValue ) )
2022-03-15 11:26:31 +00:00
{ }
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr ~ TVariant ( ) requires ( true & & . . . & & CTriviallyDestructible < Ts > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr ~ TVariant ( ) requires ( ! ( true & & . . . & & CTriviallyDestructible < Ts > ) )
2022-03-15 11:26:31 +00:00
{
2022-11-17 15:17:50 +00:00
Reset ( ) ;
2022-03-15 11:26:31 +00:00
}
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant & operator = ( const TVariant & InValue ) requires ( true & & . . . & & ( CTriviallyCopyConstructible < Ts > & & CTriviallyCopyAssignable < Ts > ) ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant & operator = ( const TVariant & InValue ) requires ( ( true & & . . . & & ( CCopyConstructible < Ts > & & CCopyAssignable < Ts > ) )
2022-11-17 15:17:50 +00:00
& & ! ( true & & . . . & & ( CTriviallyCopyConstructible < Ts > & & CTriviallyCopyAssignable < Ts > ) ) )
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-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant & operator = ( TVariant & & InValue ) requires ( true & & . . . & & ( CTriviallyMoveConstructible < Ts > & & CTriviallyMoveAssignable < Ts > ) ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant & operator = ( TVariant & & InValue ) requires ( ( true & & . . . & & ( CMoveConstructible < Ts > & & CMoveAssignable < Ts > ) )
2022-11-17 15:17:50 +00:00
& & ! ( true & & . . . & & ( CTriviallyMoveConstructible < Ts > & & CTriviallyMoveAssignable < Ts > ) ) )
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 ;
}
2022-12-03 15:12:29 +00:00
template < typename T > requires ( requires { typename NAMESPACE_PRIVATE : : TVariantSelectedType < T , Ts . . . > ; } )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariant & operator = ( T & & InValue )
2022-03-15 11:26:31 +00:00
{
2022-12-03 15:12:29 +00:00
using SelectedType = NAMESPACE_PRIVATE : : TVariantSelectedType < T , Ts . . . > ;
2022-03-15 11:26:31 +00:00
2022-11-16 11:13:37 +00:00
if ( GetIndex ( ) = = TVariantIndex < SelectedType , TVariant < Ts . . . > > ) GetValue < SelectedType > ( ) = Forward < T > ( InValue ) ;
2022-03-15 11:26:31 +00:00
else
{
Reset ( ) ;
2022-12-12 14:07:12 +00:00
new ( & Value ) SelectedType ( Forward < T > ( InValue ) ) ;
2022-11-16 11:13:37 +00:00
TypeIndex = TVariantIndex < SelectedType , TVariant < Ts . . . > > ;
2022-03-15 11:26:31 +00:00
}
return * this ;
}
2022-11-16 14:03:54 +00:00
template < size_t I , typename . . . ArgTypes > requires ( I < sizeof . . . ( Ts )
& & CConstructibleFrom < TVariantAlternative < I , TVariant < Ts . . . > > , ArgTypes . . . > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TVariantAlternative < I , TVariant < Ts . . . > > & Emplace ( ArgTypes & & . . . Args )
2022-03-15 11:26:31 +00:00
{
Reset ( ) ;
2022-11-16 11:13:37 +00:00
using SelectedType = TVariantAlternative < I , TVariant < Ts . . . > > ;
2022-12-12 14:07:12 +00:00
SelectedType * Result = new ( & Value ) SelectedType ( Forward < ArgTypes > ( Args ) . . . ) ;
2022-03-15 11:26:31 +00:00
TypeIndex = I ;
return * Result ;
}
2022-11-16 14:03:54 +00:00
template < typename T , typename . . . ArgTypes > requires ( CConstructibleFrom < T , ArgTypes . . . > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr T & Emplace ( ArgTypes & & . . . Args )
2022-03-15 11:26:31 +00:00
{
2022-11-16 11:13:37 +00:00
return Emplace < TVariantIndex < T , TVariant < Ts . . . > > > ( Forward < ArgTypes > ( Args ) . . . ) ;
2022-03-15 11:26:31 +00:00
}
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr const type_info & GetTypeInfo ( ) const { return IsValid ( ) ? * TypeInfos [ GetIndex ( ) ] : typeid ( void ) ; }
2022-05-03 10:22:41 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr size_t GetIndex ( ) const { return TypeIndex ! = 0xFF ? TypeIndex : INDEX_NONE ; }
FORCEINLINE constexpr bool IsValid ( ) const { return TypeIndex ! = 0xFF ; }
FORCEINLINE constexpr explicit operator bool ( ) const { return TypeIndex ! = 0xFF ; }
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
template < size_t I > FORCEINLINE constexpr bool HoldsAlternative ( ) const { return IsValid ( ) ? GetIndex ( ) = = I : false ; }
template < typename T > FORCEINLINE constexpr bool HoldsAlternative ( ) const { return IsValid ( ) ? GetIndex ( ) = = TVariantIndex < T , TVariant < Ts . . . > > : false ; }
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) FORCEINLINE constexpr decltype ( auto ) 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 < TVariantAlternative < I , TVariant < Ts . . . > > * > ( & Value ) ; }
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) FORCEINLINE constexpr decltype ( auto ) 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 < TVariantAlternative < I , TVariant < Ts . . . > > * > ( & Value ) ) ; }
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) FORCEINLINE constexpr decltype ( auto ) 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 TVariantAlternative < I , TVariant < Ts . . . > > * > ( & Value ) ; }
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) FORCEINLINE constexpr decltype ( auto ) 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 TVariantAlternative < I , TVariant < Ts . . . > > * > ( & Value ) ) ; }
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
template < typename T > FORCEINLINE constexpr decltype ( auto ) 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 > FORCEINLINE constexpr decltype ( auto ) 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 > FORCEINLINE constexpr decltype ( auto ) 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 > FORCEINLINE constexpr decltype ( auto ) 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-12-13 14:02:39 +00:00
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) FORCEINLINE constexpr decltype ( auto ) Get ( TVariantAlternative < I , TVariant < Ts . . . > > & DefaultValue ) & { return HoldsAlternative < I > ( ) ? GetValue < I > ( ) : DefaultValue ; }
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) FORCEINLINE constexpr decltype ( auto ) Get ( const TVariantAlternative < I , TVariant < Ts . . . > > & DefaultValue ) const & { return HoldsAlternative < I > ( ) ? GetValue < I > ( ) : DefaultValue ; }
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
template < typename T > FORCEINLINE constexpr decltype ( auto ) Get ( T & DefaultValue ) & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
template < typename T > FORCEINLINE constexpr decltype ( auto ) Get ( const T & DefaultValue ) const & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr void Reset ( )
2022-03-15 11:26:31 +00:00
{
2022-03-17 01:22:48 +00:00
if ( GetIndex ( ) = = INDEX_NONE ) return ;
2022-03-15 11:26:31 +00:00
2022-11-16 11:13:37 +00:00
if constexpr ( ! ( true & & . . . & & CTriviallyDestructible < Ts > ) )
2022-03-23 09:49:30 +00:00
{
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
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr size_t GetTypeHash ( ) const requires ( true & & . . . & & CHashable < Ts > )
2022-04-22 14:28:44 +00:00
{
if ( ! IsValid ( ) ) return 114514 ;
2022-05-12 15:36:32 +00:00
using NAMESPACE_REDCRAFT : : GetTypeHash ;
using FHashImpl = size_t ( * ) ( const void * ) ;
2022-11-16 11:13:37 +00:00
constexpr FHashImpl HashImpl [ ] = { [ ] ( const void * This ) - > size_t { return GetTypeHash ( * reinterpret_cast < const Ts * > ( This ) ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
return HashCombine ( GetTypeHash ( GetIndex ( ) ) , HashImpl [ GetIndex ( ) ] ( & Value ) ) ;
2022-04-22 14:28:44 +00:00
}
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr void Swap ( TVariant & InValue ) requires ( true & & . . . & & ( CMoveConstructible < Ts > & & CSwappable < Ts > ) )
2022-04-14 14:41:22 +00:00
{
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 * ) ;
2022-11-16 11:13:37 +00:00
constexpr FSwapImpl SwapImpl [ ] = { [ ] ( void * A , void * B ) { Swap ( * reinterpret_cast < Ts * > ( A ) , * reinterpret_cast < Ts * > ( B ) ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
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-11-16 11:13:37 +00:00
static constexpr const type_info * TypeInfos [ ] = { & typeid ( Ts ) . . . } ;
2022-05-12 15:36:32 +00:00
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 * ) ;
2022-11-16 11:13:37 +00:00
static constexpr FCopyConstructImpl CopyConstructImpl [ ] = { [ ] ( void * A , const void * B ) { if constexpr ( requires ( Ts * A , const Ts * B ) { Memory : : CopyConstruct ( A , B ) ; } ) Memory : : CopyConstruct ( reinterpret_cast < Ts * > ( A ) , reinterpret_cast < const Ts * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not copy constructible. " ) , typeid ( Ts ) . name ( ) ) ; } . . . } ;
static constexpr FMoveConstructImpl MoveConstructImpl [ ] = { [ ] ( void * A , void * B ) { if constexpr ( requires ( Ts * A , Ts * B ) { Memory : : MoveConstruct ( A , B ) ; } ) Memory : : MoveConstruct ( reinterpret_cast < Ts * > ( A ) , reinterpret_cast < Ts * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not move constructible. " ) , typeid ( Ts ) . name ( ) ) ; } . . . } ;
static constexpr FCopyAssignImpl CopyAssignImpl [ ] = { [ ] ( void * A , const void * B ) { if constexpr ( requires ( Ts * A , const Ts * B ) { Memory : : CopyAssign ( A , B ) ; } ) Memory : : CopyAssign ( reinterpret_cast < Ts * > ( A ) , reinterpret_cast < const Ts * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not copy assignable. " ) , typeid ( Ts ) . name ( ) ) ; } . . . } ;
static constexpr FMoveAssignImpl MoveAssignImpl [ ] = { [ ] ( void * A , void * B ) { if constexpr ( requires ( Ts * A , Ts * B ) { Memory : : MoveAssign ( A , B ) ; } ) Memory : : MoveAssign ( reinterpret_cast < Ts * > ( A ) , reinterpret_cast < Ts * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not move assignable. " ) , typeid ( Ts ) . name ( ) ) ; } . . . } ;
2022-11-16 14:03:54 +00:00
static constexpr FDestroyImpl DestroyImpl [ ] = { [ ] ( void * A ) { if constexpr ( requires ( Ts * A ) { Memory : : Destruct ( A ) ; } ) Memory : : Destruct ( reinterpret_cast < Ts * > ( A ) ) ; else checkf ( false , TEXT ( " The type '%s' is not destructible. " ) , typeid ( Ts ) . name ( ) ) ; } . . . } ;
2022-03-15 11:26:31 +00:00
2022-11-16 11:13:37 +00:00
TAlignedUnion < 1 , Ts . . . > Value ;
2022-04-22 14:28:44 +00:00
uint8 TypeIndex ;
2022-03-15 11:26:31 +00:00
2022-12-13 14:02:39 +00:00
friend FORCEINLINE constexpr bool operator = = ( const TVariant & LHS , const TVariant & RHS ) requires ( true & & . . . & & CEqualityComparable < Ts > )
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 * ) ;
2022-11-16 11:13:37 +00:00
constexpr FCompareImpl CompareImpl [ ] = { [ ] ( const void * LHS , const void * RHS ) - > bool { return * reinterpret_cast < const Ts * > ( LHS ) = = * reinterpret_cast < const Ts * > ( RHS ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
return CompareImpl [ LHS . GetIndex ( ) ] ( & LHS . Value , & RHS . Value ) ;
2022-05-03 10:22:41 +00:00
}
2022-12-13 14:02:39 +00:00
friend FORCEINLINE constexpr partial_ordering operator < = > ( const TVariant & LHS , const TVariant & RHS ) requires ( true & & . . . & & CSynthThreeWayComparable < Ts > )
2022-05-03 10:22:41 +00:00
{
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 * ) ;
2022-11-16 11:13:37 +00:00
constexpr FCompareImpl CompareImpl [ ] = { [ ] ( const void * LHS , const void * RHS ) - > partial_ordering { return SynthThreeWayCompare ( * reinterpret_cast < const Ts * > ( LHS ) , * reinterpret_cast < const Ts * > ( RHS ) ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
return CompareImpl [ LHS . GetIndex ( ) ] ( & LHS . Value , & RHS . Value ) ;
2022-03-15 11:26:31 +00:00
}
} ;
2022-11-21 15:28:19 +00:00
template < typename T , typename . . . Ts > requires ( ! CBaseOf < TVariant < Ts . . . > , T > & & CEqualityComparable < T > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr bool operator = = ( const TVariant < Ts . . . > & LHS , const T & RHS )
2022-03-15 11:26:31 +00:00
{
return LHS . template HoldsAlternative < T > ( ) ? LHS . template GetValue < T > ( ) = = RHS : false ;
}
2022-11-16 11:13:37 +00:00
template < typename . . . Ts >
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr bool operator = = ( const TVariant < Ts . . . > & LHS , FInvalid )
2022-03-22 03:12:05 +00:00
{
return ! LHS . IsValid ( ) ;
}
2022-12-03 15:14:25 +00:00
NAMESPACE_PRIVATE_BEGIN
template < typename F , typename . . . VariantTypes >
struct TVariantVisitImpl
{
struct GetTotalNum
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr size_t Do ( )
2022-12-03 15:14:25 +00:00
{
if ( sizeof . . . ( VariantTypes ) = = 0 ) return 0 ;
constexpr size_t VariantNums [ ] = { TVariantNum < TRemoveReference < VariantTypes > > . . . } ;
size_t Result = 1 ;
for ( size_t Index = 0 ; Index < sizeof . . . ( VariantTypes ) ; + + Index )
{
Result * = VariantNums [ Index ] ;
}
return Result ;
} ;
} ;
struct EncodeIndices
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr size_t Do ( initializer_list < size_t > Indices )
2022-12-03 15:14:25 +00:00
{
constexpr size_t VariantNums [ ] = { TVariantNum < TRemoveReference < VariantTypes > > . . . } ;
size_t Result = 0 ;
for ( size_t Index = 0 ; Index < sizeof . . . ( VariantTypes ) ; + + Index )
{
Result * = VariantNums [ Index ] ;
Result + = GetData ( Indices ) [ Index ] ;
}
return Result ;
} ;
} ;
struct DecodeExtent
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr size_t Do ( size_t EncodedIndex , size_t Extent )
2022-12-03 15:14:25 +00:00
{
constexpr size_t VariantNums [ ] = { TVariantNum < TRemoveReference < VariantTypes > > . . . } ;
for ( size_t Index = Extent + 1 ; Index < sizeof . . . ( VariantTypes ) ; + + Index )
{
EncodedIndex / = VariantNums [ Index ] ;
}
return EncodedIndex % VariantNums [ Extent ] ;
} ;
} ;
template < size_t EncodedIndex , typename >
struct InvokeEncoded ;
template < size_t EncodedIndex , size_t . . . ExtentIndices >
struct InvokeEncoded < EncodedIndex , TIndexSequence < ExtentIndices . . . > >
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr decltype ( auto ) Do ( F & & Func , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
return Invoke ( Forward < F > ( Func ) , Forward < VariantTypes > ( Variants ) . template GetValue < DecodeExtent : : Do ( EncodedIndex , ExtentIndices ) > ( ) . . . ) ;
}
template < typename Ret >
struct Result
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr Ret Do ( F & & Func , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
return InvokeResult < Ret > ( Forward < F > ( Func ) , Forward < VariantTypes > ( Variants ) . template GetValue < DecodeExtent : : Do ( EncodedIndex , ExtentIndices ) > ( ) . . . ) ;
}
} ;
} ;
template < typename >
struct InvokeVariant ;
template < size_t . . . EncodedIndices >
struct InvokeVariant < TIndexSequence < EncodedIndices . . . > >
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr decltype ( auto ) Do ( F & & Func , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
using ExtentIndices = TIndexSequenceFor < VariantTypes . . . > ;
using ResultType = TCommonType < decltype ( InvokeEncoded < EncodedIndices , ExtentIndices > : : Do ( Forward < F > ( Func ) , Forward < VariantTypes > ( Variants ) . . . ) ) . . . > ;
using InvokeImplType = ResultType ( * ) ( F & & , VariantTypes & & . . . ) ;
constexpr InvokeImplType InvokeImpl [ ] = { InvokeEncoded < EncodedIndices , ExtentIndices > : : template Result < ResultType > : : Do . . . } ;
return InvokeImpl [ EncodeIndices : : Do ( { Variants . GetIndex ( ) . . . } ) ] ( Forward < F > ( Func ) , Forward < VariantTypes > ( Variants ) . . . ) ;
}
template < typename Ret >
struct Result
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr Ret Do ( F & & Func , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
using ExtentIndices = TIndexSequenceFor < VariantTypes . . . > ;
using InvokeImplType = Ret ( * ) ( F & & , VariantTypes & & . . . ) ;
constexpr InvokeImplType InvokeImpl [ ] = { InvokeEncoded < EncodedIndices , ExtentIndices > : : template Result < Ret > : : Do . . . } ;
return InvokeImpl [ EncodeIndices : : Do ( { Variants . GetIndex ( ) . . . } ) ] ( Forward < F > ( Func ) , Forward < VariantTypes > ( Variants ) . . . ) ;
}
} ;
} ;
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr decltype ( auto ) Do ( F & & Func , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
return InvokeVariant < TMakeIndexSequence < GetTotalNum : : Do ( ) > > : : Do ( Forward < F > ( Func ) , Forward < VariantTypes > ( Variants ) . . . ) ;
}
template < typename Ret >
struct Result
{
2022-12-13 14:02:39 +00:00
FORCEINLINE static constexpr Ret Do ( F & & Func , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
return InvokeVariant < TMakeIndexSequence < GetTotalNum : : Do ( ) > > : : template Result < Ret > : : Do ( Forward < F > ( Func ) , Forward < VariantTypes > ( Variants ) . . . ) ;
}
} ;
} ;
NAMESPACE_PRIVATE_END
template < typename F , typename FirstVariantType , typename . . . VariantTypes >
requires ( CTVariant < TRemoveReference < FirstVariantType > > & & ( true & & . . . & & CTVariant < TRemoveReference < VariantTypes > > ) )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr decltype ( auto ) Visit ( F & & Func , FirstVariantType & & FirstVariant , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
checkf ( ( true & & . . . & & Variants . IsValid ( ) ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
return NAMESPACE_PRIVATE : : TVariantVisitImpl < F , FirstVariantType , VariantTypes . . . > : : Do ( Forward < F > ( Func ) , Forward < FirstVariantType > ( FirstVariant ) , Forward < VariantTypes > ( Variants ) . . . ) ;
}
template < typename Ret , typename F , typename FirstVariantType , typename . . . VariantTypes >
requires ( CTVariant < TRemoveReference < FirstVariantType > > & & ( true & & . . . & & CTVariant < TRemoveReference < VariantTypes > > ) )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr Ret Visit ( F & & Func , FirstVariantType & & FirstVariant , VariantTypes & & . . . Variants )
2022-12-03 15:14:25 +00:00
{
checkf ( ( true & & . . . & & Variants . IsValid ( ) ) , TEXT ( " It is an error to call Visit() on an wrong TVariant. Please either check IsValid(). " ) ) ;
return NAMESPACE_PRIVATE : : TVariantVisitImpl < F , FirstVariantType , VariantTypes . . . > : : template Result < Ret > : : Do ( Forward < F > ( Func ) , Forward < FirstVariantType > ( FirstVariant ) , Forward < VariantTypes > ( Variants ) . . . ) ;
}
2022-03-15 11:26:31 +00:00
NAMESPACE_MODULE_END ( Utility )
NAMESPACE_MODULE_END ( Redcraft )
NAMESPACE_REDCRAFT_END