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-04-22 14:28:44 +00:00
constexpr TVariant ( ) : TypeIndex ( 0xFF ) { } ;
2022-03-15 11:26:31 +00:00
constexpr TVariant ( FInvalid ) : TVariant ( ) { } ;
2022-11-17 15:17:50 +00:00
constexpr TVariant ( const TVariant & InValue ) requires ( true & & . . . & & CTriviallyCopyConstructible < Ts > ) = default ;
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-11-17 15:17:50 +00:00
constexpr TVariant ( TVariant & & InValue ) requires ( true & & . . . & & CTriviallyMoveConstructible < Ts > ) = default ;
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-03-15 11:26:31 +00:00
constexpr explicit TVariant ( TInPlaceIndex < I > , ArgTypes & & . . . Args )
: TypeIndex ( I )
{
2022-11-16 11:13:37 +00:00
using SelectedType = TVariantAlternative < I , TVariant < Ts . . . > > ;
2022-03-15 11:26:31 +00:00
new ( & Value ) SelectedType ( Forward < ArgTypes > ( Args ) . . . ) ;
}
2022-11-16 14:03:54 +00:00
template < typename T , typename . . . ArgTypes > requires ( CConstructibleFrom < T , ArgTypes . . . > )
2022-03-15 11:26:31 +00:00
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-03 15:12:29 +00:00
constexpr TVariant ( T & & InValue ) : TVariant ( InPlaceType < NAMESPACE_PRIVATE : : TVariantSelectedType < T , Ts . . . > > , Forward < T > ( InValue ) )
2022-03-15 11:26:31 +00:00
{ }
2022-11-17 15:17:50 +00:00
constexpr ~ TVariant ( ) requires ( true & & . . . & & CTriviallyDestructible < Ts > ) = default ;
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-11-17 15:17:50 +00:00
constexpr TVariant & operator = ( const TVariant & InValue ) requires ( true & & . . . & & ( CTriviallyCopyConstructible < Ts > & & CTriviallyCopyAssignable < Ts > ) ) = default ;
constexpr TVariant & operator = ( const TVariant & InValue ) requires ( ( true & & . . . & & ( CCopyConstructible < Ts > & & CCopyAssignable < Ts > ) )
& & ! ( 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-11-17 15:17:50 +00:00
constexpr TVariant & operator = ( TVariant & & InValue ) requires ( true & & . . . & & ( CTriviallyMoveConstructible < Ts > & & CTriviallyMoveAssignable < Ts > ) ) = default ;
constexpr TVariant & operator = ( TVariant & & InValue ) requires ( ( true & & . . . & & ( CMoveConstructible < Ts > & & CMoveAssignable < Ts > ) )
& & ! ( 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-03-15 11:26:31 +00:00
constexpr TVariant & operator = ( T & & InValue )
{
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 ( ) ;
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-11-16 11:13:37 +00:00
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-03-15 11:26:31 +00:00
SelectedType * Result = new ( & Value ) SelectedType ( Forward < ArgTypes > ( Args ) . . . ) ;
TypeIndex = I ;
return * Result ;
}
2022-11-16 14:03:54 +00:00
template < typename T , typename . . . ArgTypes > requires ( CConstructibleFrom < T , ArgTypes . . . > )
2022-03-15 11:26:31 +00:00
constexpr T & Emplace ( ArgTypes & & . . . Args )
{
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-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
2022-11-21 15:28:19 +00:00
template < size_t I > constexpr bool HoldsAlternative ( ) const { return IsValid ( ) ? GetIndex ( ) = = I : false ; }
2022-11-16 11:13:37 +00:00
template < typename T > constexpr bool HoldsAlternative ( ) const { return IsValid ( ) ? GetIndex ( ) = = TVariantIndex < T , TVariant < Ts . . . > > : false ; }
2022-03-15 11:26:31 +00:00
2022-11-16 11:13:37 +00:00
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) 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 ) ) 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 ) ) 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 ) ) 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-06-16 15:37:29 +00:00
template < typename T > 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 > 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 > 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 > 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-11-16 11:13:37 +00:00
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) constexpr decltype ( auto ) Get ( TVariantAlternative < I , TVariant < Ts . . . > > & DefaultValue ) & { return HoldsAlternative < I > ( ) ? GetValue < I > ( ) : DefaultValue ; }
template < size_t I > requires ( I < sizeof . . . ( Ts ) ) 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-06-16 15:37:29 +00:00
template < typename T > constexpr decltype ( auto ) Get ( T & DefaultValue ) & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
template < typename T > constexpr decltype ( auto ) Get ( const T & DefaultValue ) const & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
2022-03-15 11:26:31 +00:00
2022-11-16 11:13:37 +00:00
template < typename F > requires ( true & & . . . & & CInvocable < F , Ts > )
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
2022-11-16 11:13:37 +00:00
using ReturnType = TCommonType < TInvokeResult < F , Ts > . . . > ;
2022-05-12 15:36:32 +00:00
using FInvokeImpl = ReturnType ( * ) ( F & & , void * ) ;
2022-11-16 11:13:37 +00:00
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , * reinterpret_cast < Ts * > ( This ) ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
2022-03-15 11:26:31 +00:00
}
2022-11-16 11:13:37 +00:00
template < typename F > requires ( true & & . . . & & CInvocable < F , Ts > )
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
2022-11-16 11:13:37 +00:00
using ReturnType = TCommonType < TInvokeResult < F , Ts > . . . > ;
2022-05-12 15:36:32 +00:00
using FInvokeImpl = ReturnType ( * ) ( F & & , void * ) ;
2022-11-16 11:13:37 +00:00
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < Ts * > ( This ) ) ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
2022-03-15 11:26:31 +00:00
}
2022-11-16 11:13:37 +00:00
template < typename F > requires ( true & & . . . & & CInvocable < F , Ts > )
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
2022-11-16 11:13:37 +00:00
using ReturnType = TCommonType < TInvokeResult < F , Ts > . . . > ;
2022-05-12 15:36:32 +00:00
using FInvokeImpl = ReturnType ( * ) ( F & & , const void * ) ;
2022-11-16 11:13:37 +00:00
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , const void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , * reinterpret_cast < const Ts * > ( This ) ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
2022-03-15 11:26:31 +00:00
}
2022-11-16 11:13:37 +00:00
template < typename F > requires ( true & & . . . & & CInvocable < F , Ts > )
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
2022-11-16 11:13:37 +00:00
using ReturnType = TCommonType < TInvokeResult < F , Ts > . . . > ;
2022-05-12 15:36:32 +00:00
using FInvokeImpl = ReturnType ( * ) ( F & & , const void * ) ;
2022-11-16 11:13:37 +00:00
static constexpr FInvokeImpl InvokeImpl [ ] = { [ ] ( F & & Func , const void * This ) - > ReturnType { return InvokeResult < ReturnType > ( Forward < F > ( Func ) , MoveTemp ( * reinterpret_cast < const Ts * > ( This ) ) ) ; } . . . } ;
2022-05-12 15:36:32 +00:00
return InvokeImpl [ GetIndex ( ) ] ( Forward < F > ( Func ) , & Value ) ;
2022-03-15 11:26:31 +00:00
}
2022-11-16 11:13:37 +00:00
template < typename R , typename F > requires ( true & & . . . & & CInvocableResult < R , F , Ts > )
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-11-16 11:13:37 +00:00
template < typename R , typename F > requires ( true & & . . . & & CInvocableResult < R , F , Ts > )
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-11-16 11:13:37 +00:00
template < typename R , typename F > requires ( true & & . . . & & CInvocableResult < R , F , Ts > )
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-11-16 11:13:37 +00:00
template < typename R , typename F > requires ( true & & . . . & & CInvocableResult < R , F , Ts > )
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-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-11-16 11:13:37 +00:00
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-11-16 11:13:37 +00:00
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-11-16 11:13:37 +00:00
friend 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-11-16 11:13:37 +00:00
friend 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-11-16 11:13:37 +00:00
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 >
constexpr bool operator = = ( const TVariant < Ts . . . > & LHS , FInvalid )
2022-03-22 03:12:05 +00:00
{
return ! LHS . IsValid ( ) ;
}
2022-03-15 11:26:31 +00:00
NAMESPACE_MODULE_END ( Utility )
NAMESPACE_MODULE_END ( Redcraft )
NAMESPACE_REDCRAFT_END