2022-03-22 03:10:12 +00:00
# pragma once
# include "CoreTypes.h"
# include "Memory/Memory.h"
2022-04-27 14:50:56 +00:00
# include "Memory/Alignment.h"
2022-03-22 03:10:12 +00:00
# include "Templates/Utility.h"
2022-04-22 14:28:44 +00:00
# include "Templates/TypeHash.h"
2022-05-12 15:36:32 +00:00
# include "Memory/MemoryOperator.h"
2022-03-22 03:10:12 +00:00
# include "TypeTraits/TypeTraits.h"
# include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN ( Redcraft )
NAMESPACE_MODULE_BEGIN ( Utility )
2022-11-13 14:21:00 +00:00
// TAny's CustomStorage concept, see FAnyDefaultStorage.
template < typename T >
concept CAnyStorage = true ; // TODO
2022-03-31 09:36:48 +00:00
2022-11-13 14:21:00 +00:00
// TAny's default storage structure.
struct alignas ( 16 ) FAnyDefaultStorage
2022-03-22 03:10:12 +00:00
{
2022-11-13 14:21:00 +00:00
// The built-in copy/move operators are disabled and CopyCustom/MoveCustom is used instead of them.
// You can add custom variables like this.
//Type Variable;
//~ Begin CAnyStorage Interface
inline static constexpr size_t InlineSize = 64 - sizeof ( uintptr ) ;
inline static constexpr size_t InlineAlignment = 16 ;
constexpr void * InlineAllocation ( ) { return & InlineAllocationImpl ; }
constexpr const void * InlineAllocation ( ) const { return & InlineAllocationImpl ; }
constexpr void * & HeapAllocation ( ) { return HeapAllocationImpl ; }
constexpr void * HeapAllocation ( ) const { return HeapAllocationImpl ; }
constexpr uintptr & TypeInfo ( ) { return TypeInfoImpl ; }
constexpr uintptr TypeInfo ( ) const { return TypeInfoImpl ; }
constexpr void CopyCustom ( const FAnyDefaultStorage & InValue ) { /* Variable = InValue.Variable; */ } // You just need to copy the custom variables.
constexpr void MoveCustom ( FAnyDefaultStorage & & InValue ) { /* Variable = MoveTemp(InValue.Variable); */ } // You just need to move the custom variables.
//~ End CAnyStorage Interface
2022-03-22 03:10:12 +00:00
2022-11-13 14:21:00 +00:00
union
{
uint8 InlineAllocationImpl [ InlineSize ] ;
void * HeapAllocationImpl ;
} ;
uintptr TypeInfoImpl ;
} ;
2022-03-22 03:10:12 +00:00
2022-11-13 14:21:00 +00:00
static_assert ( CAnyStorage < FAnyDefaultStorage > ) ;
// You can add custom storage area through CustomStorage, such as TFunction.
// It is not recommended to use this, FAny is recommended.
template < CAnyStorage CustomStorage = FAnyDefaultStorage >
struct TAny
{
inline static constexpr size_t InlineSize = CustomStorage : : InlineSize ;
inline static constexpr size_t InlineAlignment = CustomStorage : : InlineAlignment ;
constexpr TAny ( ) { Storage . TypeInfo ( ) = 0 ; }
constexpr TAny ( FInvalid ) : TAny ( ) { }
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny ( const TAny & InValue )
2022-03-22 03:10:12 +00:00
{
2022-11-13 14:21:00 +00:00
Storage . CopyCustom ( InValue . Storage ) ;
Storage . TypeInfo ( ) = InValue . Storage . TypeInfo ( ) ;
2022-03-22 03:10:12 +00:00
if ( ! IsValid ( ) ) return ;
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
{
2022-06-21 15:31:46 +00:00
case ERepresentation : : Trivial :
2022-11-13 14:21:00 +00:00
Memory : : Memcpy ( Storage . InlineAllocation ( ) , InValue . Storage . InlineAllocation ( ) , Storage . InlineSize ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Small :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . CopyConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Big :
2022-11-13 14:21:00 +00:00
Storage . HeapAllocation ( ) = Memory : : Malloc ( GetTypeInfoImpl ( ) . TypeSize , GetTypeInfoImpl ( ) . TypeAlignment ) ;
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . CopyConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
default : check_no_entry ( ) ;
}
2022-03-22 03:10:12 +00:00
}
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny ( TAny & & InValue )
2022-03-22 03:10:12 +00:00
{
2022-11-13 14:21:00 +00:00
Storage . MoveCustom ( MoveTemp ( InValue . Storage ) ) ;
Storage . TypeInfo ( ) = InValue . Storage . TypeInfo ( ) ;
2022-03-22 03:10:12 +00:00
if ( ! IsValid ( ) ) return ;
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
2022-03-22 03:10:12 +00:00
{
2022-06-21 15:31:46 +00:00
case ERepresentation : : Trivial :
2022-11-13 14:21:00 +00:00
Memory : : Memcpy ( Storage . InlineAllocation ( ) , InValue . Storage . InlineAllocation ( ) , Storage . InlineSize ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Small :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . MoveConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Big :
2022-11-13 14:21:00 +00:00
Storage . HeapAllocation ( ) = InValue . Storage . HeapAllocation ( ) ;
InValue . Storage . TypeInfo ( ) = 0 ;
2022-04-30 15:38:09 +00:00
break ;
default : check_no_entry ( ) ;
2022-03-22 03:10:12 +00:00
}
}
2022-05-22 14:52:47 +00:00
template < typename T , typename . . . Types > requires CDestructible < TDecay < T > >
2022-06-21 15:31:46 +00:00
& & CConstructibleFrom < TDecay < T > , Types & & . . . >
2022-04-05 09:00:33 +00:00
FORCEINLINE explicit TAny ( TInPlaceType < T > , Types & & . . . Args )
2022-03-22 03:10:12 +00:00
{
2022-05-22 14:52:47 +00:00
using SelectedType = TDecay < T > ;
2022-04-03 14:55:17 +00:00
EmplaceImpl < SelectedType > ( Forward < Types > ( Args ) . . . ) ;
2022-03-22 03:10:12 +00:00
}
2022-05-22 14:52:47 +00:00
template < typename T > requires ( ! CSameAs < TDecay < T > , TAny > ) & & ( ! CTInPlaceType < TDecay < T > > )
& & CDestructible < TDecay < T > > & & CConstructibleFrom < TDecay < T > , T & & >
FORCEINLINE TAny ( T & & InValue ) : TAny ( InPlaceType < TDecay < T > > , Forward < T > ( InValue ) )
2022-03-22 03:10:12 +00:00
{ }
2022-04-05 09:00:33 +00:00
FORCEINLINE ~ TAny ( )
2022-03-22 03:10:12 +00:00
{
2022-04-05 09:00:33 +00:00
ResetImpl ( ) ;
2022-03-22 03:10:12 +00:00
}
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny & operator = ( const TAny & InValue )
2022-03-22 03:10:12 +00:00
{
2022-04-03 14:55:17 +00:00
if ( & InValue = = this ) return * this ;
2022-11-13 14:21:00 +00:00
Storage . CopyCustom ( InValue . Storage ) ;
2022-03-22 03:10:12 +00:00
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
}
2022-04-05 09:00:33 +00:00
else if ( GetTypeInfo ( ) = = InValue . GetTypeInfo ( ) )
2022-03-22 03:10:12 +00:00
{
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
{
2022-06-21 15:31:46 +00:00
case ERepresentation : : Trivial :
2022-11-13 14:21:00 +00:00
Memory : : Memcpy ( Storage . InlineAllocation ( ) , InValue . Storage . InlineAllocation ( ) , Storage . InlineSize ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Small :
case ERepresentation : : Big :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . CopyAssignImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
default : check_no_entry ( ) ;
}
2022-03-22 03:10:12 +00:00
}
else
{
2022-04-05 09:00:33 +00:00
ResetImpl ( ) ;
2022-03-22 03:10:12 +00:00
2022-11-13 14:21:00 +00:00
Storage . TypeInfo ( ) = InValue . Storage . TypeInfo ( ) ;
2022-03-22 03:10:12 +00:00
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
{
2022-06-21 15:31:46 +00:00
case ERepresentation : : Trivial :
2022-11-13 14:21:00 +00:00
Memory : : Memcpy ( Storage . InlineAllocation ( ) , InValue . Storage . InlineAllocation ( ) , Storage . InlineSize ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Small :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . CopyConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Big :
2022-11-13 14:21:00 +00:00
Storage . HeapAllocation ( ) = Memory : : Malloc ( GetTypeInfoImpl ( ) . TypeSize , GetTypeInfoImpl ( ) . TypeAlignment ) ;
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . CopyConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
default : check_no_entry ( ) ;
}
2022-03-22 03:10:12 +00:00
}
return * this ;
}
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny & operator = ( TAny & & InValue )
2022-03-22 03:10:12 +00:00
{
2022-04-03 14:55:17 +00:00
if ( & InValue = = this ) return * this ;
2022-11-13 14:21:00 +00:00
Storage . MoveCustom ( MoveTemp ( InValue . Storage ) ) ;
2022-03-22 03:10:12 +00:00
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
}
2022-04-05 09:00:33 +00:00
else if ( GetTypeInfo ( ) = = InValue . GetTypeInfo ( ) )
2022-03-22 03:10:12 +00:00
{
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
2022-03-22 03:10:12 +00:00
{
2022-06-21 15:31:46 +00:00
case ERepresentation : : Trivial :
2022-11-13 14:21:00 +00:00
Memory : : Memcpy ( Storage . InlineAllocation ( ) , InValue . Storage . InlineAllocation ( ) , Storage . InlineSize ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Small :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . MoveAssignImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Big :
2022-04-30 15:38:09 +00:00
ResetImpl ( ) ;
2022-11-13 14:21:00 +00:00
Storage . HeapAllocation ( ) = InValue . Storage . HeapAllocation ( ) ;
InValue . Storage . TypeInfo ( ) = 0 ;
2022-04-30 15:38:09 +00:00
break ;
default : check_no_entry ( ) ;
2022-03-22 03:10:12 +00:00
}
}
else
{
2022-04-05 09:00:33 +00:00
ResetImpl ( ) ;
2022-03-22 03:10:12 +00:00
2022-11-13 14:21:00 +00:00
Storage . TypeInfo ( ) = InValue . Storage . TypeInfo ( ) ;
2022-03-22 03:10:12 +00:00
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
{
2022-06-21 15:31:46 +00:00
case ERepresentation : : Trivial :
2022-11-13 14:21:00 +00:00
Memory : : Memcpy ( Storage . InlineAllocation ( ) , InValue . Storage . InlineAllocation ( ) , Storage . InlineSize ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Small :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . MoveConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Big :
2022-11-13 14:21:00 +00:00
Storage . HeapAllocation ( ) = InValue . Storage . HeapAllocation ( ) ;
InValue . Storage . TypeInfo ( ) = 0 ;
2022-04-30 15:38:09 +00:00
break ;
default : check_no_entry ( ) ;
}
2022-03-22 03:10:12 +00:00
}
return * this ;
}
2022-05-22 14:52:47 +00:00
template < typename T > requires ( ! CSameAs < TDecay < T > , TAny > ) & & ( ! CTInPlaceType < TDecay < T > > )
& & CDestructible < TDecay < T > > & & CConstructibleFrom < TDecay < T > , T & & >
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny & operator = ( T & & InValue )
2022-03-22 03:10:12 +00:00
{
2022-05-22 14:52:47 +00:00
using SelectedType = TDecay < T > ;
2022-03-22 03:10:12 +00:00
2022-04-05 09:00:33 +00:00
if ( HoldsAlternative < SelectedType > ( ) )
2022-03-22 03:10:12 +00:00
{
2022-04-30 15:38:09 +00:00
GetValue < SelectedType > ( ) = Forward < T > ( InValue ) ;
2022-03-22 03:10:12 +00:00
}
else
{
2022-04-30 15:38:09 +00:00
ResetImpl ( ) ;
2022-04-03 14:55:17 +00:00
EmplaceImpl < SelectedType > ( Forward < T > ( InValue ) ) ;
2022-03-22 03:10:12 +00:00
}
return * this ;
}
2022-05-22 14:52:47 +00:00
template < typename T , typename . . . Types > requires CDestructible < TDecay < T > >
2022-06-21 15:31:46 +00:00
& & CConstructibleFrom < TDecay < T > , Types & & . . . >
2022-05-22 14:52:47 +00:00
FORCEINLINE TDecay < T > & Emplace ( Types & & . . . Args )
2022-03-22 03:10:12 +00:00
{
2022-04-05 09:00:33 +00:00
ResetImpl ( ) ;
2022-03-22 03:10:12 +00:00
2022-05-22 14:52:47 +00:00
using SelectedType = TDecay < T > ;
2022-04-03 14:55:17 +00:00
EmplaceImpl < SelectedType > ( Forward < Types > ( Args ) . . . ) ;
2022-03-22 03:10:12 +00:00
return GetValue < SelectedType > ( ) ;
}
2022-11-13 14:21:00 +00:00
constexpr const type_info & GetTypeInfo ( ) const { return IsValid ( ) ? * GetTypeInfoImpl ( ) . NativeTypeInfo : typeid ( void ) ; }
2022-04-05 09:00:33 +00:00
2022-11-13 14:21:00 +00:00
constexpr bool IsValid ( ) const { return Storage . TypeInfo ( ) ! = 0 ; }
constexpr explicit operator bool ( ) const { return Storage . TypeInfo ( ) ! = 0 ; }
2022-03-22 03:10:12 +00:00
2022-05-12 15:36:32 +00:00
template < typename T > constexpr bool HoldsAlternative ( ) const { return IsValid ( ) ? GetTypeInfo ( ) = = typeid ( T ) : false ; }
2022-03-22 03:10:12 +00:00
2022-05-22 14:52:47 +00:00
template < typename T > requires CDestructible < TDecay < T > >
2022-04-30 15:38:09 +00:00
constexpr T & GetValue ( ) & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return * reinterpret_cast < T * > ( GetAllocation ( ) ) ; }
2022-03-22 03:10:12 +00:00
2022-05-22 14:52:47 +00:00
template < typename T > requires CDestructible < TDecay < T > >
2022-04-30 15:38:09 +00:00
constexpr T & & GetValue ( ) & & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return MoveTemp ( * reinterpret_cast < T * > ( GetAllocation ( ) ) ) ; }
2022-03-23 09:49:30 +00:00
2022-05-22 14:52:47 +00:00
template < typename T > requires CDestructible < TDecay < T > >
2022-04-30 15:38:09 +00:00
constexpr const T & GetValue ( ) const & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return * reinterpret_cast < const T * > ( GetAllocation ( ) ) ; }
2022-03-23 09:49:30 +00:00
2022-05-22 14:52:47 +00:00
template < typename T > requires CDestructible < TDecay < T > >
2022-04-30 15:38:09 +00:00
constexpr const T & & GetValue ( ) const & & { checkf ( HoldsAlternative < T > ( ) , TEXT ( " It is an error to call GetValue() on an wrong TAny. Please either check HoldsAlternative() or use Get(DefaultValue) instead. " ) ) ; return MoveTemp ( * reinterpret_cast < const T * > ( GetAllocation ( ) ) ) ; }
2022-03-23 09:49:30 +00:00
2022-05-22 14:52:47 +00:00
template < typename T > requires CSameAs < T , TDecay < T > > & & CDestructible < TDecay < T > >
2022-03-23 09:49:30 +00:00
constexpr T & Get ( T & DefaultValue ) & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
2022-05-22 14:52:47 +00:00
template < typename T > requires CSameAs < T , TDecay < T > > & & CDestructible < TDecay < T > >
2022-03-23 09:49:30 +00:00
constexpr const T & Get ( const T & DefaultValue ) const & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
2022-03-22 03:10:12 +00:00
2022-11-13 14:21:00 +00:00
constexpr CustomStorage & GetCustomStorage ( ) requires ( ! CSameAs < CustomStorage , FAnyDefaultStorage > ) { return Storage ; }
constexpr const CustomStorage & GetCustomStorage ( ) const requires ( ! CSameAs < CustomStorage , FAnyDefaultStorage > ) { return Storage ; }
2022-04-05 09:00:33 +00:00
FORCEINLINE void Reset ( )
2022-03-22 03:10:12 +00:00
{
2022-04-05 09:00:33 +00:00
ResetImpl ( ) ;
2022-11-13 14:21:00 +00:00
Storage . TypeInfo ( ) = 0 ;
2022-03-22 03:10:12 +00:00
}
2022-04-30 15:38:09 +00:00
FORCEINLINE size_t GetTypeHash ( ) const
{
2022-05-12 15:36:32 +00:00
using NAMESPACE_REDCRAFT : : GetTypeHash ;
2022-04-30 15:38:09 +00:00
if ( ! IsValid ( ) ) return 20090007 ;
2022-05-12 15:36:32 +00:00
return HashCombine ( GetTypeHash ( GetTypeInfo ( ) ) , GetTypeInfoImpl ( ) . HashImpl ( GetAllocation ( ) ) ) ;
2022-04-30 15:38:09 +00:00
}
FORCEINLINE void Swap ( TAny & InValue )
{
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 ( GetTypeInfo ( ) = = InValue . GetTypeInfo ( ) )
{
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . SwapImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
return ;
}
TAny Temp = MoveTemp ( * this ) ;
* this = MoveTemp ( InValue ) ;
InValue = MoveTemp ( Temp ) ;
}
2022-04-14 14:41:22 +00:00
2022-03-22 03:10:12 +00:00
private :
2022-11-13 14:21:00 +00:00
CustomStorage Storage ;
2022-04-30 15:38:09 +00:00
static constexpr uintptr_t RepresentationMask = 3 ;
2022-06-21 15:31:46 +00:00
enum class ERepresentation : uint8
2022-05-12 15:36:32 +00:00
{
2022-06-21 15:31:46 +00:00
Trivial , // Trivial & Inline
Small , // InlineAllocation
2022-05-12 15:36:32 +00:00
Big , // HeapAllocation
} ;
struct FTypeInfoImpl
{
2022-11-13 14:21:00 +00:00
const type_info * NativeTypeInfo ;
2022-05-12 15:36:32 +00:00
const size_t TypeSize ;
const size_t TypeAlignment ;
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 * ) ;
using FEqualityCompareImpl = bool ( * ) ( const void * , const void * ) ;
using FSynthThreeWayCompareImpl = partial_ordering ( * ) ( const void * , const void * ) ;
using FHashImpl = size_t ( * ) ( const void * ) ;
using FSwapImpl = void ( * ) ( void * , void * ) ;
const FCopyConstructImpl CopyConstructImpl ;
const FMoveConstructImpl MoveConstructImpl ;
const FCopyAssignImpl CopyAssignImpl ;
const FMoveAssignImpl MoveAssignImpl ;
const FDestroyImpl DestroyImpl ;
const FEqualityCompareImpl EqualityCompareImpl ;
const FSynthThreeWayCompareImpl SynthThreeWayCompareImpl ;
const FHashImpl HashImpl ;
const FSwapImpl SwapImpl ;
template < typename T >
constexpr FTypeInfoImpl ( TInPlaceType < T > )
2022-11-13 14:21:00 +00:00
: NativeTypeInfo ( & typeid ( T ) )
, TypeSize ( sizeof ( T ) )
, TypeAlignment ( alignof ( T ) )
2022-05-12 15:36:32 +00:00
, CopyConstructImpl ( [ ] ( void * A , const void * B ) { if constexpr ( requires ( T * A , const T * B ) { Memory : : CopyConstruct ( A , B ) ; } ) Memory : : CopyConstruct ( reinterpret_cast < T * > ( A ) , reinterpret_cast < const T * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not copy constructible. " ) , typeid ( Types ) . name ( ) ) ; } )
, MoveConstructImpl ( [ ] ( void * A , void * B ) { if constexpr ( requires ( T * A , T * B ) { Memory : : MoveConstruct ( A , B ) ; } ) Memory : : MoveConstruct ( reinterpret_cast < T * > ( A ) , reinterpret_cast < T * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not move constructible. " ) , typeid ( Types ) . name ( ) ) ; } )
, CopyAssignImpl ( [ ] ( void * A , const void * B ) { if constexpr ( requires ( T * A , const T * B ) { Memory : : CopyAssign ( A , B ) ; } ) Memory : : CopyAssign ( reinterpret_cast < T * > ( A ) , reinterpret_cast < const T * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not copy assignable. " ) , typeid ( Types ) . name ( ) ) ; } )
, MoveAssignImpl ( [ ] ( void * A , void * B ) { if constexpr ( requires ( T * A , T * B ) { Memory : : MoveAssign ( A , B ) ; } ) Memory : : MoveAssign ( reinterpret_cast < T * > ( A ) , reinterpret_cast < T * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not move assignable. " ) , typeid ( Types ) . name ( ) ) ; } )
, DestroyImpl ( [ ] ( void * A ) { if constexpr ( requires ( T * A ) { Memory : : Destruct ( A ) ; } ) Memory : : Destruct ( reinterpret_cast < T * > ( A ) ) ; else checkf ( false , TEXT ( " The type '%s' is not destructible. " ) , typeid ( Types ) . name ( ) ) ; } )
, EqualityCompareImpl ( [ ] ( const void * A , const void * B ) - > bool { if constexpr ( CEqualityComparable < T > ) return ( * reinterpret_cast < const T * > ( A ) = = * reinterpret_cast < const T * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not equality comparable. " ) , typeid ( T ) . name ( ) ) ; return false ; } )
, SynthThreeWayCompareImpl ( [ ] ( const void * A , const void * B ) - > partial_ordering { if constexpr ( CSynthThreeWayComparable < T > ) return NAMESPACE_REDCRAFT : : SynthThreeWayCompare ( * reinterpret_cast < const T * > ( A ) , * reinterpret_cast < const T * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not synth three-way comparable. " ) , typeid ( T ) . name ( ) ) ; return partial_ordering : : unordered ; } )
, HashImpl ( [ ] ( const void * A ) - > size_t { if constexpr ( CHashable < T > ) return NAMESPACE_REDCRAFT : : GetTypeHash ( * reinterpret_cast < const T * > ( A ) ) ; else checkf ( false , TEXT ( " The type '%s' is not hashable. " ) , typeid ( T ) . name ( ) ) ; return 1080551797 ; } )
, SwapImpl ( [ ] ( void * A , void * B ) - > void { if constexpr ( CSwappable < T > ) NAMESPACE_REDCRAFT : : Swap ( * reinterpret_cast < T * > ( A ) , * reinterpret_cast < T * > ( B ) ) ; else checkf ( false , TEXT ( " The type '%s' is not swappable. " ) , typeid ( T ) . name ( ) ) ; } )
{ }
} ;
2022-11-13 14:21:00 +00:00
constexpr ERepresentation GetRepresentation ( ) const { return static_cast < ERepresentation > ( Storage . TypeInfo ( ) & RepresentationMask ) ; }
constexpr const FTypeInfoImpl & GetTypeInfoImpl ( ) const { return * reinterpret_cast < const FTypeInfoImpl * > ( Storage . TypeInfo ( ) & ~ RepresentationMask ) ; }
2022-04-30 15:38:09 +00:00
2022-11-13 14:21:00 +00:00
constexpr void * GetAllocation ( ) { return GetRepresentation ( ) = = ERepresentation : : Trivial | | GetRepresentation ( ) = = ERepresentation : : Small ? Storage . InlineAllocation ( ) : Storage . HeapAllocation ( ) ; }
constexpr const void * GetAllocation ( ) const { return GetRepresentation ( ) = = ERepresentation : : Trivial | | GetRepresentation ( ) = = ERepresentation : : Small ? Storage . InlineAllocation ( ) : Storage . HeapAllocation ( ) ; }
2022-04-30 15:38:09 +00:00
2022-04-03 14:55:17 +00:00
template < typename SelectedType , typename . . . Types >
2022-04-05 05:20:00 +00:00
FORCEINLINE void EmplaceImpl ( Types & & . . . Args )
2022-04-03 14:55:17 +00:00
{
2022-05-12 15:36:32 +00:00
static constexpr const FTypeInfoImpl SelectedTypeInfo ( InPlaceType < SelectedType > ) ;
2022-11-13 14:21:00 +00:00
Storage . TypeInfo ( ) = reinterpret_cast < uintptr > ( & SelectedTypeInfo ) ;
2022-04-03 14:55:17 +00:00
2022-11-13 14:21:00 +00:00
constexpr bool bIsInlineStorable = sizeof ( SelectedType ) < = Storage . InlineSize & & alignof ( SelectedType ) < = Storage . InlineAlignment ;
2022-05-15 15:22:49 +00:00
constexpr bool bIsTriviallyStorable = bIsInlineStorable & & CTrivial < SelectedType > & & CTriviallyCopyable < SelectedType > ;
2022-04-30 15:38:09 +00:00
if constexpr ( bIsTriviallyStorable )
2022-04-03 14:55:17 +00:00
{
2022-11-13 14:21:00 +00:00
new ( Storage . InlineAllocation ( ) ) SelectedType ( Forward < Types > ( Args ) . . . ) ;
Storage . TypeInfo ( ) | = static_cast < uintptr > ( ERepresentation : : Trivial ) ;
2022-04-03 14:55:17 +00:00
}
2022-04-30 15:38:09 +00:00
else if constexpr ( bIsInlineStorable )
2022-04-03 14:55:17 +00:00
{
2022-11-13 14:21:00 +00:00
new ( Storage . InlineAllocation ( ) ) SelectedType ( Forward < Types > ( Args ) . . . ) ;
Storage . TypeInfo ( ) | = static_cast < uintptr > ( ERepresentation : : Small ) ;
2022-04-03 14:55:17 +00:00
}
else
{
2022-11-13 14:21:00 +00:00
Storage . HeapAllocation ( ) = new SelectedType ( Forward < Types > ( Args ) . . . ) ;
Storage . TypeInfo ( ) | = static_cast < uintptr > ( ERepresentation : : Big ) ;
2022-04-03 14:55:17 +00:00
}
}
2022-04-05 09:00:33 +00:00
FORCEINLINE void ResetImpl ( )
{
2022-04-30 15:38:09 +00:00
if ( ! IsValid ( ) ) return ;
switch ( GetRepresentation ( ) )
{
2022-06-21 15:31:46 +00:00
case ERepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Small :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . DestroyImpl ( GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-06-21 15:31:46 +00:00
case ERepresentation : : Big :
2022-05-12 15:36:32 +00:00
GetTypeInfoImpl ( ) . DestroyImpl ( GetAllocation ( ) ) ;
2022-11-13 14:21:00 +00:00
Memory : : Free ( Storage . HeapAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
default : check_no_entry ( ) ;
}
}
friend FORCEINLINE bool operator = = ( const TAny & LHS , const TAny & RHS )
{
if ( LHS . GetTypeInfo ( ) ! = RHS . GetTypeInfo ( ) ) return false ;
if ( LHS . IsValid ( ) = = false ) return true ;
2022-05-12 15:36:32 +00:00
return LHS . GetTypeInfoImpl ( ) . EqualityCompareImpl ( LHS . GetAllocation ( ) , RHS . GetAllocation ( ) ) ;
2022-04-05 09:00:33 +00:00
}
2022-04-30 15:38:09 +00:00
friend FORCEINLINE partial_ordering operator < = > ( const TAny & LHS , const TAny & RHS )
{
if ( LHS . GetTypeInfo ( ) ! = RHS . GetTypeInfo ( ) ) return partial_ordering : : unordered ;
if ( LHS . IsValid ( ) = = false ) return partial_ordering : : equivalent ;
2022-05-12 15:36:32 +00:00
return LHS . GetTypeInfoImpl ( ) . SynthThreeWayCompareImpl ( LHS . GetAllocation ( ) , RHS . GetAllocation ( ) ) ; ;
2022-04-30 15:38:09 +00:00
}
2022-11-13 14:21:00 +00:00
2022-03-22 03:10:12 +00:00
} ;
2022-11-13 14:21:00 +00:00
template < typename T , CAnyStorage StorageType >
constexpr bool operator = = ( const TAny < StorageType > & LHS , const T & RHS )
2022-03-22 03:10:12 +00:00
{
return LHS . template HoldsAlternative < T > ( ) ? LHS . template GetValue < T > ( ) = = RHS : false ;
}
2022-11-13 14:21:00 +00:00
template < CAnyStorage StorageType >
constexpr bool operator = = ( const TAny < StorageType > & LHS , FInvalid )
2022-03-22 03:10:12 +00:00
{
return ! LHS . IsValid ( ) ;
}
2022-05-20 15:35:36 +00:00
NAMESPACE_PRIVATE_BEGIN
2022-11-13 14:21:00 +00:00
template < typename T > struct TIsTAny : FFalse { } ;
template < CAnyStorage StorageType > struct TIsTAny < TAny < StorageType > > : FTrue { } ;
2022-03-31 09:36:48 +00:00
2022-05-20 15:35:36 +00:00
NAMESPACE_PRIVATE_END
2022-06-16 15:37:29 +00:00
template < typename T >
concept CTAny = NAMESPACE_PRIVATE : : TIsTAny < T > : : Value ;
2022-05-20 15:35:36 +00:00
2022-11-13 14:21:00 +00:00
using FAny = TAny < > ;
2022-03-22 03:10:12 +00:00
static_assert ( sizeof ( FAny ) = = 64 , " The byte size of FAny is unexpected " ) ;
NAMESPACE_MODULE_END ( Utility )
NAMESPACE_MODULE_END ( Redcraft )
NAMESPACE_REDCRAFT_END