2022-02-09 13:46:39 +00:00
# pragma once
# include "CoreTypes.h"
# include "Templates/Invoke.h"
# include "Templates/Utility.h"
2022-05-03 14:20:08 +00:00
# include "Templates/Optional.h"
2022-02-09 13:46:39 +00:00
# include "TypeTraits/TypeTraits.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN ( Redcraft )
NAMESPACE_MODULE_BEGIN ( Utility )
2022-05-15 15:10:02 +00:00
template < typename ReferencedType > requires ( CObject < ReferencedType > | | CFunction < ReferencedType > )
2022-11-15 11:28:43 +00:00
class TReferenceWrapper
2022-02-09 13:46:39 +00:00
{
public :
2022-05-03 14:20:08 +00:00
using Type = ReferencedType ;
2022-02-09 13:46:39 +00:00
2022-11-16 14:03:54 +00:00
template < typename T = ReferencedType > requires ( CConvertibleTo < T , ReferencedType & > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper ( T & & Object )
2022-11-15 14:15:10 +00:00
{
ReferencedType & Reference = Forward < T > ( Object ) ;
Pointer = AddressOf ( Reference ) ;
}
2022-02-09 13:46:39 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper ( const TReferenceWrapper & ) = default ;
2022-12-13 14:11:10 +00:00
FORCEINLINE constexpr TReferenceWrapper ( TReferenceWrapper & & ) = default ;
2022-05-03 14:20:08 +00:00
2022-11-16 14:03:54 +00:00
template < typename T = ReferencedType > requires ( CConvertibleTo < T & , ReferencedType & > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper ( const TReferenceWrapper < T > & InValue )
2022-05-03 14:20:08 +00:00
: Pointer ( InValue . Pointer )
{ }
2022-02-09 13:46:39 +00:00
2022-12-13 14:11:10 +00:00
template < typename T = ReferencedType > requires ( CAssignableFrom < ReferencedType & , T & & > )
FORCEINLINE constexpr TReferenceWrapper & operator = ( T & & Object ) { Get ( ) = Forward < T > ( Object ) ; return * this ; }
FORCEINLINE constexpr TReferenceWrapper & operator = ( const TReferenceWrapper & ) = delete ;
FORCEINLINE constexpr TReferenceWrapper & operator = ( TReferenceWrapper & & ) = delete ;
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr operator ReferencedType & ( ) const { return * Pointer ; }
FORCEINLINE constexpr ReferencedType & Get ( ) const { return * Pointer ; }
2022-02-09 13:46:39 +00:00
2022-11-16 11:13:37 +00:00
template < typename . . . Ts >
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TInvokeResult < ReferencedType & , Ts . . . > operator ( ) ( Ts & & . . . Args ) const
2022-02-09 13:46:39 +00:00
{
2022-11-16 11:13:37 +00:00
return Invoke ( Get ( ) , Forward < Ts > ( Args ) . . . ) ;
2022-02-09 13:46:39 +00:00
}
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr size_t GetTypeHash ( ) const requires ( CHashable < ReferencedType > )
2022-05-03 14:20:08 +00:00
{
return NAMESPACE_REDCRAFT : : GetTypeHash ( Get ( ) ) ;
}
2022-02-09 13:46:39 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr void Swap ( TReferenceWrapper & InValue )
2022-05-03 14:20:08 +00:00
{
ReferencedType * Temp = Pointer ;
Pointer = InValue . Pointer ;
InValue . Pointer = Temp ;
}
2022-02-09 13:46:39 +00:00
private :
2022-05-03 14:20:08 +00:00
ReferencedType * Pointer ;
2022-11-15 11:28:43 +00:00
template < typename T > requires ( CObject < T > | | CFunction < T > ) friend class TReferenceWrapper ;
2022-05-03 14:20:08 +00:00
// Optimize TOptional with these hacking
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper ( FInvalid ) : Pointer ( nullptr ) { } ;
2022-11-16 14:03:54 +00:00
template < typename T > requires ( CDestructible < T > ) friend class TOptional ;
2022-02-09 13:46:39 +00:00
} ;
template < typename T >
TReferenceWrapper ( T & ) - > TReferenceWrapper < T > ;
2022-04-24 15:08:00 +00:00
template < typename T >
void Ref ( const T & & ) = delete ;
template < typename T >
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper < T > Ref ( T & InValue )
2022-04-24 15:08:00 +00:00
{
return TReferenceWrapper < T > ( InValue ) ;
}
template < typename T >
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper < T > Ref ( TReferenceWrapper < T > InValue )
2022-04-24 15:08:00 +00:00
{
return Ref ( InValue . Get ( ) ) ;
}
template < typename T >
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper < const T > Ref ( const T & InValue )
2022-04-24 15:08:00 +00:00
{
return TReferenceWrapper < const T > ( InValue ) ;
}
template < typename T >
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TReferenceWrapper < const T > Ref ( TReferenceWrapper < T > InValue )
2022-04-24 15:08:00 +00:00
{
return Ref ( InValue . Get ( ) ) ;
}
2022-05-20 15:35:36 +00:00
NAMESPACE_PRIVATE_BEGIN
2022-06-16 15:37:29 +00:00
template < typename T > struct TIsTReferenceWrapperImpl : FFalse { } ;
template < typename T > struct TIsTReferenceWrapperImpl < TReferenceWrapper < T > > : FTrue { } ;
template < typename T > struct TUnwrapReferenceImpl { using Type = T ; } ;
template < typename T > struct TUnwrapReferenceImpl < TReferenceWrapper < T > > { using Type = T & ; } ;
template < typename T > struct TUnwrapRefDecayImpl { using Type = typename TUnwrapReferenceImpl < TDecay < T > > : : Type ; } ;
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 >
2022-11-17 12:57:54 +00:00
concept CTReferenceWrapper = NAMESPACE_PRIVATE : : TIsTReferenceWrapperImpl < TRemoveCV < T > > : : Value ;
2022-05-20 15:35:36 +00:00
2022-06-16 15:37:29 +00:00
template < typename T >
using TUnwrapReference = typename NAMESPACE_PRIVATE : : TUnwrapReferenceImpl < T > : : Type ;
2022-03-26 11:33:28 +00:00
2022-06-16 15:37:29 +00:00
template < typename T >
using TUnwrapRefDecay = typename NAMESPACE_PRIVATE : : TUnwrapRefDecayImpl < T > : : Type ;
2022-03-26 11:33:28 +00:00
2022-12-16 11:30:55 +00:00
NAMESPACE_PRIVATE_BEGIN
template < typename T , typename U >
concept CTOptionalRefAllowUnwrappable =
! ( CConstructibleFrom < U , TOptional < T > & >
| | CConstructibleFrom < U , const TOptional < T > & >
| | CConstructibleFrom < U , TOptional < T > & & >
| | CConstructibleFrom < U , const TOptional < T > & & >
| | CConvertibleTo < TOptional < T > & , U >
| | CConvertibleTo < const TOptional < T > & , U >
| | CConvertibleTo < TOptional < T > & & , U >
| | CConvertibleTo < const TOptional < T > & & , U >
| | CAssignableFrom < U & , TOptional < T > & >
| | CAssignableFrom < U & , const TOptional < T > & >
| | CAssignableFrom < U & , TOptional < T > & & >
| | CAssignableFrom < U & , const TOptional < T > & & > ) ;
NAMESPACE_PRIVATE_END
2022-05-03 14:20:08 +00:00
template < typename ReferencedType >
2022-11-15 11:28:43 +00:00
class TOptional < TReferenceWrapper < ReferencedType > >
2022-05-03 14:20:08 +00:00
{
private :
using OptionalType = TReferenceWrapper < ReferencedType > ;
public :
using ValueType = OptionalType ;
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TOptional ( ) : Reference ( Invalid ) { }
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TOptional ( FInvalid ) : TOptional ( ) { }
2022-05-03 14:20:08 +00:00
2022-11-16 14:03:54 +00:00
template < typename . . . Ts > requires ( CConstructibleFrom < OptionalType , Ts . . . > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr explicit TOptional ( FInPlace , Ts & & . . . Args )
2022-11-16 11:13:37 +00:00
: Reference ( Forward < Ts > ( Args ) . . . )
2022-05-03 14:20:08 +00:00
{ }
2022-11-16 14:03:54 +00:00
template < typename T = OptionalType > requires ( CConstructibleFrom < OptionalType , T & & >
2022-11-21 15:28:19 +00:00
& & ! CSameAs < TRemoveCVRef < T > , FInPlace > & & ! CBaseOf < TOptional , TRemoveCVRef < T > > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr explicit ( ! CConvertibleTo < T & & , OptionalType > ) TOptional ( T & & InValue )
2022-05-03 14:20:08 +00:00
: TOptional ( InPlace , Forward < T > ( InValue ) )
{ }
2022-12-13 14:02:39 +00:00
FORCEINLINE TOptional ( const TOptional & InValue ) = default ;
FORCEINLINE TOptional ( TOptional & & InValue ) = default ;
2022-05-03 14:20:08 +00:00
2022-12-16 11:30:55 +00:00
template < typename T = OptionalType > requires ( CConstructibleFrom < OptionalType , const T & > & & NAMESPACE_PRIVATE : : CTOptionalRefAllowUnwrappable < T , OptionalType > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr explicit ( ! CConvertibleTo < const T & , OptionalType > ) TOptional ( const TOptional < T > & InValue )
2022-05-03 14:20:08 +00:00
: Reference ( InValue . Reference )
{ }
2022-12-13 14:02:39 +00:00
FORCEINLINE ~ TOptional ( ) = default ;
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE TOptional & operator = ( const TOptional & InValue ) = default ;
FORCEINLINE TOptional & operator = ( TOptional & & InValue ) = default ;
2022-05-03 14:20:08 +00:00
2022-11-16 14:03:54 +00:00
template < typename T = OptionalType > requires ( CConstructibleFrom < OptionalType , const T & >
2022-12-16 11:30:55 +00:00
& & CAssignableFrom < OptionalType & , const T & > & & NAMESPACE_PRIVATE : : CTOptionalRefAllowUnwrappable < T , OptionalType > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TOptional & operator = ( const TOptional < T > & InValue )
2022-05-03 14:20:08 +00:00
{
Reference = InValue . Reference ;
return * this ;
}
2022-11-16 14:03:54 +00:00
template < typename T = OptionalType > requires ( CConstructibleFrom < OptionalType , T & & > & & CAssignableFrom < OptionalType & , T & & > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TOptional & operator = ( T & & InValue )
2022-05-03 14:20:08 +00:00
{
Reference = InValue ;
return * this ;
}
2022-11-16 14:03:54 +00:00
template < typename . . . ArgTypes > requires ( CConstructibleFrom < OptionalType , ArgTypes . . . > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr OptionalType & Emplace ( ArgTypes & & . . . Args )
2022-05-03 14:20:08 +00:00
{
Reference = TReferenceWrapper < ReferencedType > ( Forward < ArgTypes > ( Args ) . . . ) ;
return Reference ;
}
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr bool IsValid ( ) const { return Reference . Pointer ! = nullptr ; }
FORCEINLINE constexpr explicit operator bool ( ) const { return Reference . Pointer ! = nullptr ; }
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr OptionalType & GetValue ( ) & { checkf ( IsValid ( ) , TEXT ( " It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead. " ) ) ; return Reference ; }
FORCEINLINE constexpr OptionalType & & GetValue ( ) & & { checkf ( IsValid ( ) , TEXT ( " It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead. " ) ) ; return Reference ; }
FORCEINLINE constexpr const OptionalType & GetValue ( ) const & { checkf ( IsValid ( ) , TEXT ( " It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead. " ) ) ; return Reference ; }
FORCEINLINE constexpr const OptionalType & & GetValue ( ) const & & { checkf ( IsValid ( ) , TEXT ( " It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead. " ) ) ; return Reference ; }
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr const OptionalType * operator - > ( ) const { return & GetValue ( ) ; }
FORCEINLINE constexpr OptionalType * operator - > ( ) { return & GetValue ( ) ; }
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr OptionalType & operator * ( ) & { return GetValue ( ) ; }
FORCEINLINE constexpr OptionalType & & operator * ( ) & & { return GetValue ( ) ; }
FORCEINLINE constexpr const OptionalType & operator * ( ) const & { return GetValue ( ) ; }
FORCEINLINE constexpr const OptionalType & & operator * ( ) const & & { return GetValue ( ) ; }
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr OptionalType & Get ( OptionalType & DefaultValue ) & { return IsValid ( ) ? GetValue ( ) : DefaultValue ; }
FORCEINLINE constexpr const OptionalType & Get ( const OptionalType & DefaultValue ) const & { return IsValid ( ) ? GetValue ( ) : DefaultValue ; }
2022-05-03 14:20:08 +00:00
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr void Reset ( )
2022-05-03 14:20:08 +00:00
{
Reference = Invalid ;
}
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr size_t GetTypeHash ( ) const requires ( CHashable < ReferencedType > )
2022-05-03 14:20:08 +00:00
{
if ( ! IsValid ( ) ) return 2824517378 ;
return Reference . GetTypeHash ( ) ;
}
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr void Swap ( TOptional & InValue )
2022-05-03 14:20:08 +00:00
{
Reference . Swap ( InValue . Reference ) ;
}
private :
TReferenceWrapper < ReferencedType > Reference ;
2022-11-16 14:03:54 +00:00
template < typename T > requires ( CDestructible < T > ) friend class TOptional ;
2022-05-03 14:20:08 +00:00
} ;
2022-02-09 13:46:39 +00:00
NAMESPACE_MODULE_END ( Utility )
NAMESPACE_MODULE_END ( Redcraft )
NAMESPACE_REDCRAFT_END