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"
2022-04-30 15:38:09 +00:00
// NOTE: Disable alignment limit warning
# pragma warning(disable : 4359)
2022-03-22 03:10:12 +00:00
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN ( Redcraft )
NAMESPACE_MODULE_BEGIN ( Utility )
2022-04-30 15:38:09 +00:00
inline constexpr size_t ANY_DEFAULT_INLINE_SIZE = 64 - sizeof ( uintptr ) ;
2022-04-05 05:20:00 +00:00
inline constexpr size_t ANY_DEFAULT_INLINE_ALIGNMENT = 16 ;
2022-03-31 09:36:48 +00:00
2022-04-27 14:50:56 +00:00
template < size_t InlineSize , size_t InlineAlignment = ANY_DEFAULT_INLINE_ALIGNMENT > requires ( Memory : : IsValidAlignment ( InlineAlignment ) )
2022-04-30 15:38:09 +00:00
struct alignas ( InlineAlignment ) TAny
2022-03-22 03:10:12 +00:00
{
2022-04-30 15:38:09 +00:00
constexpr TAny ( ) : TypeInfo ( 0 ) { }
2022-03-22 03:10:12 +00:00
2022-04-03 14:55:17 +00:00
constexpr TAny ( FInvalid ) : TAny ( ) { }
2022-03-22 03:10:12 +00:00
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny ( const TAny & InValue )
2022-04-30 15:38:09 +00:00
: TypeInfo ( InValue . TypeInfo )
2022-03-22 03:10:12 +00:00
{
if ( ! IsValid ( ) ) return ;
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
{
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
Memory : : Memcpy ( InlineAllocation , InValue . InlineAllocation ) ;
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Small :
GetTypeInfoImpl ( ) . CopyConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Big :
HeapAllocation = Memory : : Malloc ( GetTypeInfoImpl ( ) . TypeSize , GetTypeInfoImpl ( ) . TypeAlignment ) ;
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-04-30 15:38:09 +00:00
: TypeInfo ( InValue . 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-05-12 15:36:32 +00:00
case EAnyRepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
Memory : : Memcpy ( InlineAllocation , InValue . InlineAllocation ) ;
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Small :
GetTypeInfoImpl ( ) . MoveConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Big :
2022-04-30 15:38:09 +00:00
HeapAllocation = InValue . HeapAllocation ;
InValue . TypeInfo = 0 ;
break ;
default : check_no_entry ( ) ;
2022-03-22 03:10:12 +00:00
}
}
2022-05-16 14:42:17 +00:00
template < typename T , typename . . . Types > requires CDestructible < typename TDecay < T > : : Type >
& & CConstructible < typename TDecay < T > : : Type , Types . . . >
2022-04-05 09:00:33 +00:00
FORCEINLINE explicit TAny ( TInPlaceType < T > , Types & & . . . Args )
2022-03-22 03:10:12 +00:00
{
using SelectedType = typename TDecay < T > : : Type ;
2022-04-03 14:55:17 +00:00
EmplaceImpl < SelectedType > ( Forward < Types > ( Args ) . . . ) ;
2022-03-22 03:10:12 +00:00
}
2022-05-16 15:09:04 +00:00
template < typename T > requires ( ! CSameAs < typename TDecay < T > : : Type , TAny > ) & & ( ! TIsTInPlaceType < typename TDecay < T > : : Type > : : Value )
2022-05-16 14:42:17 +00:00
& & CDestructible < typename TDecay < T > : : Type > & & CConstructible < typename TDecay < T > : : Type , T & & >
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny ( T & & InValue ) : TAny ( InPlaceType < typename TDecay < T > : : Type > , 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-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-05-12 15:36:32 +00:00
case EAnyRepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
Memory : : Memcpy ( InlineAllocation , InValue . InlineAllocation ) ;
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Small :
case EAnyRepresentation : : Big :
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
TypeInfo = InValue . TypeInfo ;
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
{
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
Memory : : Memcpy ( InlineAllocation , InValue . InlineAllocation ) ;
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Small :
GetTypeInfoImpl ( ) . CopyConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Big :
HeapAllocation = Memory : : Malloc ( GetTypeInfoImpl ( ) . TypeSize , GetTypeInfoImpl ( ) . TypeAlignment ) ;
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-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-05-12 15:36:32 +00:00
case EAnyRepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
Memory : : Memcpy ( InlineAllocation , InValue . InlineAllocation ) ;
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Small :
GetTypeInfoImpl ( ) . MoveAssignImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Big :
2022-04-30 15:38:09 +00:00
ResetImpl ( ) ;
HeapAllocation = InValue . HeapAllocation ;
InValue . TypeInfo = 0 ;
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
TypeInfo = InValue . TypeInfo ;
2022-04-30 15:38:09 +00:00
switch ( GetRepresentation ( ) )
{
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
Memory : : Memcpy ( InlineAllocation , InValue . InlineAllocation ) ;
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Small :
GetTypeInfoImpl ( ) . MoveConstructImpl ( GetAllocation ( ) , InValue . GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Big :
2022-04-30 15:38:09 +00:00
HeapAllocation = InValue . HeapAllocation ;
InValue . TypeInfo = 0 ;
break ;
default : check_no_entry ( ) ;
}
2022-03-22 03:10:12 +00:00
}
return * this ;
}
2022-05-16 15:09:04 +00:00
template < typename T > requires ( ! CSameAs < typename TDecay < T > : : Type , TAny > ) & & ( ! TIsTInPlaceType < typename TDecay < T > : : Type > : : Value )
2022-05-16 14:42:17 +00:00
& & CDestructible < typename TDecay < T > : : Type > & & CConstructible < typename TDecay < T > : : Type , T & & >
2022-04-05 09:00:33 +00:00
FORCEINLINE TAny & operator = ( T & & InValue )
2022-03-22 03:10:12 +00:00
{
using SelectedType = typename TDecay < T > : : Type ;
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-16 14:42:17 +00:00
template < typename T , typename . . . Types > requires CDestructible < typename TDecay < T > : : Type >
& & CConstructible < typename TDecay < T > : : Type , T & & >
2022-04-05 09:00:33 +00:00
FORCEINLINE typename TDecay < T > : : Type & 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
using SelectedType = typename TDecay < T > : : Type ;
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-05-12 15:36:32 +00:00
constexpr const type_info & GetTypeInfo ( ) const { return IsValid ( ) ? * GetTypeInfoImpl ( ) . TypeInfo : typeid ( void ) ; }
2022-04-05 09:00:33 +00:00
2022-04-30 15:38:09 +00:00
constexpr bool IsValid ( ) const { return TypeInfo ! = 0 ; }
constexpr explicit operator bool ( ) const { return 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-16 14:42:17 +00:00
template < typename T > requires CDestructible < typename TDecay < T > : : Type >
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-16 14:42:17 +00:00
template < typename T > requires CDestructible < typename TDecay < T > : : Type >
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-16 14:42:17 +00:00
template < typename T > requires CDestructible < typename TDecay < T > : : Type >
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-16 14:42:17 +00:00
template < typename T > requires CDestructible < typename TDecay < T > : : Type >
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-16 15:09:04 +00:00
template < typename T > requires CSameAs < T , typename TDecay < T > : : Type > & & CDestructible < typename TDecay < T > : : Type >
2022-03-23 09:49:30 +00:00
constexpr T & Get ( T & DefaultValue ) & { return HoldsAlternative < T > ( ) ? GetValue < T > ( ) : DefaultValue ; }
2022-05-16 15:09:04 +00:00
template < typename T > requires CSameAs < T , typename TDecay < T > : : Type > & & CDestructible < typename TDecay < T > : : Type >
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-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-04-30 15:38:09 +00:00
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-04-30 15:38:09 +00:00
static constexpr uintptr_t RepresentationMask = 3 ;
2022-05-12 15:36:32 +00:00
enum class EAnyRepresentation : uint8
{
Trivial , // Trivial
// Inline, // InlineAllocation
Small , // Trivial & Inline
Big , // HeapAllocation
} ;
struct FTypeInfoImpl
{
const type_info * TypeInfo ;
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 > )
: TypeInfo ( & typeid ( T ) )
, TypeSize ( sizeof ( T ) )
, TypeAlignment ( alignof ( T ) )
, 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-03-22 03:10:12 +00:00
union
{
2022-04-30 15:38:09 +00:00
TAlignedStorage < InlineSize , 1 > : : Type InlineAllocation ;
void * HeapAllocation ;
2022-03-22 03:10:12 +00:00
} ;
2022-04-30 15:38:09 +00:00
uintptr TypeInfo ;
2022-05-12 15:36:32 +00:00
constexpr EAnyRepresentation GetRepresentation ( ) const { return static_cast < EAnyRepresentation > ( TypeInfo & RepresentationMask ) ; }
constexpr const FTypeInfoImpl & GetTypeInfoImpl ( ) const { return * reinterpret_cast < const FTypeInfoImpl * > ( TypeInfo & ~ RepresentationMask ) ; }
2022-04-30 15:38:09 +00:00
2022-05-12 15:36:32 +00:00
constexpr void * GetAllocation ( ) { return GetRepresentation ( ) = = EAnyRepresentation : : Trivial | | GetRepresentation ( ) = = EAnyRepresentation : : Small ? & InlineAllocation : HeapAllocation ; }
constexpr const void * GetAllocation ( ) const { return GetRepresentation ( ) = = EAnyRepresentation : : Trivial | | GetRepresentation ( ) = = EAnyRepresentation : : Small ? & InlineAllocation : 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 > ) ;
TypeInfo = reinterpret_cast < uintptr > ( & SelectedTypeInfo ) ;
2022-04-03 14:55:17 +00:00
2022-04-30 15:38:09 +00:00
constexpr bool bIsInlineStorable = sizeof ( SelectedType ) < = InlineSize & & alignof ( SelectedType ) < = 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-04-30 15:38:09 +00:00
new ( & InlineAllocation ) SelectedType ( Forward < Types > ( Args ) . . . ) ;
2022-05-12 15:36:32 +00:00
TypeInfo | = static_cast < uintptr > ( EAnyRepresentation : : 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-04-30 15:38:09 +00:00
new ( & InlineAllocation ) SelectedType ( Forward < Types > ( Args ) . . . ) ;
2022-05-12 15:36:32 +00:00
TypeInfo | = static_cast < uintptr > ( EAnyRepresentation : : Small ) ;
2022-04-03 14:55:17 +00:00
}
else
{
2022-04-30 15:38:09 +00:00
HeapAllocation = new SelectedType ( Forward < Types > ( Args ) . . . ) ;
2022-05-12 15:36:32 +00:00
TypeInfo | = static_cast < uintptr > ( EAnyRepresentation : : 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-05-12 15:36:32 +00:00
case EAnyRepresentation : : Trivial :
2022-04-30 15:38:09 +00:00
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Small :
GetTypeInfoImpl ( ) . DestroyImpl ( GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
break ;
2022-05-12 15:36:32 +00:00
case EAnyRepresentation : : Big :
GetTypeInfoImpl ( ) . DestroyImpl ( GetAllocation ( ) ) ;
2022-04-30 15:38:09 +00:00
Memory : : Free ( HeapAllocation ) ;
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-04-22 14:28:44 +00:00
2022-03-22 03:10:12 +00:00
} ;
template < typename T , size_t InlineSize , size_t InlineAlignment >
constexpr bool operator = = ( const TAny < InlineSize , InlineAlignment > & LHS , const T & RHS )
{
return LHS . template HoldsAlternative < T > ( ) ? LHS . template GetValue < T > ( ) = = RHS : false ;
}
template < size_t InlineSize , size_t InlineAlignment >
constexpr bool operator = = ( const TAny < InlineSize , InlineAlignment > & LHS , FInvalid )
{
return ! LHS . IsValid ( ) ;
}
2022-03-31 09:36:48 +00:00
template < typename T > struct TIsTAny : FFalse { } ;
template < size_t InlineSize , size_t InlineAlignment > struct TIsTAny < TAny < InlineSize , InlineAlignment > > : FTrue { } ;
using FAny = TAny < ANY_DEFAULT_INLINE_SIZE > ;
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