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