2022-03-09 15:17:54 +00:00
# pragma once
# include "CoreTypes.h"
2022-03-26 11:31:45 +00:00
# include "Templates/Utility.h"
2022-03-31 08:40:31 +00:00
# include "Templates/TypeHash.h"
2022-03-09 15:17:54 +00:00
# include "TypeTraits/TypeTraits.h"
2022-05-03 10:22:41 +00:00
# include "Miscellaneous/Compare.h"
2022-03-09 15:17:54 +00:00
# include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN ( Redcraft )
NAMESPACE_MODULE_BEGIN ( Utility )
2024-11-02 07:27:21 +00:00
/** The class template manages an optional contained value or reference, i.e. a value or reference that may or may not be present. */
template < typename OptionalType , bool = CReference < OptionalType > > requires ( CDestructible < TRemoveReference < OptionalType > > )
2022-12-16 11:30:55 +00:00
class TOptional ;
NAMESPACE_PRIVATE_BEGIN
2022-12-18 11:11:53 +00:00
template < typename T > struct TIsTOptional : FFalse { } ;
template < typename T > struct TIsTOptional < TOptional < T > > : FTrue { } ;
2022-12-16 11:30:55 +00:00
template < typename T , typename U >
concept CTOptionalAllowUnwrappable =
! ( 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-12-18 11:11:53 +00:00
template < typename T > concept CTOptional = NAMESPACE_PRIVATE : : TIsTOptional < TRemoveCV < T > > : : Value ;
2022-12-29 13:55:02 +00:00
/** The class template manages an optional contained value, i.e. a value that may or may not be present. */
2024-11-02 07:27:21 +00:00
template < typename T > requires ( ! CReference < T > )
class TOptional < T , false > final
2022-03-09 15:17:54 +00:00
{
public :
2024-12-16 11:34:47 +00:00
using FValueType = T ;
2024-11-02 07:27:21 +00:00
2024-12-16 11:34:47 +00:00
static_assert ( ! CReference < FValueType > ) ;
2022-03-09 15:17:54 +00:00
2022-12-29 13:55:02 +00:00
/** Constructs an object that does not contain a value. */
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TOptional ( ) : bIsValid ( false ) { }
2022-03-09 15:17:54 +00:00
2022-12-29 13:55:02 +00:00
/** Constructs an object that does not contain a value. */
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr TOptional ( FInvalid ) : TOptional ( ) { }
2022-03-13 15:18:07 +00:00
2024-11-02 07:27:21 +00:00
/** Constructs an object with initial content an object, direct-initialized from Forward<U>(InValue). */
2024-12-17 13:49:37 +00:00
template < typename U = T > requires ( CConstructibleFrom < T , U & & >
& & ! CSameAs < TRemoveCVRef < U > , FInPlace > & & ! CSameAs < TOptional , TRemoveCVRef < U > > )
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr explicit ( ! CConvertibleTo < U & & , T > ) TOptional ( U & & InValue )
: TOptional ( InPlace , Forward < U > ( InValue ) )
2022-12-29 13:55:02 +00:00
{ }
2024-10-30 08:00:39 +00:00
2022-12-29 13:55:02 +00:00
/** Constructs an object with initial content an object, direct-non-list-initialized from Forward<Ts>(Args).... */
2024-11-02 07:27:21 +00:00
template < typename . . . Ts > requires ( CConstructibleFrom < T , Ts . . . > )
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr explicit TOptional ( FInPlace , Ts & & . . . Args )
2022-03-09 15:17:54 +00:00
: bIsValid ( true )
{
2024-12-16 11:34:47 +00:00
new ( & Value ) FValueType ( Forward < Ts > ( Args ) . . . ) ;
2022-03-09 15:17:54 +00:00
}
2024-10-30 08:00:39 +00:00
2022-12-31 11:19:30 +00:00
/** Constructs an object with initial content an object, direct-non-list-initialized from IL, Forward<Ts>(Args).... */
2024-11-02 07:27:21 +00:00
template < typename W , typename . . . Ts > requires ( CConstructibleFrom < T , initializer_list < W > , Ts . . . > )
FORCEINLINE constexpr explicit TOptional ( FInPlace , initializer_list < W > IL , Ts & & . . . Args )
2022-12-31 11:19:30 +00:00
: bIsValid ( true )
{
2024-12-16 11:34:47 +00:00
new ( & Value ) FValueType ( IL , Forward < Ts > ( Args ) . . . ) ;
2022-12-31 11:19:30 +00:00
}
2022-03-09 15:17:54 +00:00
2022-12-29 13:55:02 +00:00
/** Copies content of other into a new instance. */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr TOptional ( const TOptional & InValue ) requires ( CTriviallyCopyConstructible < T > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-29 13:55:02 +00:00
/** Copies content of other into a new instance. */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr TOptional ( const TOptional & InValue ) requires ( CCopyConstructible < T > & & ! CTriviallyCopyConstructible < T > )
2022-03-13 15:18:07 +00:00
: bIsValid ( InValue . IsValid ( ) )
{
2024-12-16 11:34:47 +00:00
if ( InValue . IsValid ( ) ) new ( & Value ) FValueType ( InValue . GetValue ( ) ) ;
2022-03-13 15:18:07 +00:00
}
2022-12-29 13:55:02 +00:00
/** Moves content of other into a new instance. */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr TOptional ( TOptional & & InValue ) requires ( CTriviallyMoveConstructible < T > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-29 13:55:02 +00:00
/** Moves content of other into a new instance. */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr TOptional ( TOptional & & InValue ) requires ( CMoveConstructible < T > & & ! CTriviallyMoveConstructible < T > )
2022-03-13 15:18:07 +00:00
: bIsValid ( InValue . IsValid ( ) )
{
2024-12-16 11:34:47 +00:00
if ( InValue . IsValid ( ) ) new ( & Value ) FValueType ( MoveTemp ( InValue . GetValue ( ) ) ) ;
2022-03-13 15:18:07 +00:00
}
2022-03-09 15:17:54 +00:00
2022-12-29 13:55:02 +00:00
/** Converting copy constructor. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( CConstructibleFrom < T , const U & > & & NAMESPACE_PRIVATE : : CTOptionalAllowUnwrappable < U , T > )
FORCEINLINE constexpr explicit ( ! CConvertibleTo < const U & , T > ) TOptional ( const TOptional < U > & InValue )
2022-03-13 15:18:07 +00:00
: bIsValid ( InValue . IsValid ( ) )
2022-03-09 15:17:54 +00:00
{
2024-12-16 11:34:47 +00:00
if ( InValue . IsValid ( ) ) new ( & Value ) FValueType ( InValue . GetValue ( ) ) ;
2022-03-09 15:17:54 +00:00
}
2022-12-29 13:55:02 +00:00
/** Converting move constructor. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( CConstructibleFrom < T , U & & > & & NAMESPACE_PRIVATE : : CTOptionalAllowUnwrappable < U , T > )
FORCEINLINE constexpr explicit ( ! CConvertibleTo < U & & , T > ) TOptional ( TOptional < U > & & InValue )
2022-03-13 15:18:07 +00:00
: bIsValid ( InValue . IsValid ( ) )
2022-03-09 15:17:54 +00:00
{
2024-12-16 11:34:47 +00:00
if ( InValue . IsValid ( ) ) new ( & Value ) FValueType ( MoveTemp ( InValue . GetValue ( ) ) ) ;
2022-03-09 15:17:54 +00:00
}
2022-12-29 13:55:02 +00:00
/** Destroys the contained object, if any, as if by a call to Reset(). */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr ~ TOptional ( ) requires ( CTriviallyDestructible < T > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-29 13:55:02 +00:00
/** Destroys the contained object, if any, as if by a call to Reset(). */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr ~ TOptional ( ) requires ( ! CTriviallyDestructible < T > )
2022-03-09 15:17:54 +00:00
{
2022-11-17 15:17:50 +00:00
Reset ( ) ;
2022-03-09 15:17:54 +00:00
}
2022-12-29 13:55:02 +00:00
/** Assigns by copying the state of 'InValue'. */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr TOptional & operator = ( const TOptional & InValue ) requires ( CTriviallyCopyConstructible < T > & & CTriviallyCopyAssignable < T > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-29 13:55:02 +00:00
/** Assigns by copying the state of 'InValue'. */
2024-11-02 07:27:21 +00:00
constexpr TOptional & operator = ( const TOptional & InValue ) requires ( CCopyConstructible < T > & & CCopyAssignable < T >
& & ! CTriviallyCopyConstructible < T > & & ! CTriviallyCopyAssignable < T > )
2022-03-09 15:17:54 +00:00
{
2022-03-13 15:18:07 +00:00
if ( & InValue = = this ) return * this ;
2022-03-09 15:17:54 +00:00
2022-03-13 15:18:07 +00:00
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
return * this ;
}
2022-03-09 15:17:54 +00:00
2022-03-13 15:18:07 +00:00
if ( IsValid ( ) ) GetValue ( ) = InValue . GetValue ( ) ;
2024-10-30 08:00:39 +00:00
else
2022-03-09 15:17:54 +00:00
{
2024-12-16 11:34:47 +00:00
new ( & Value ) FValueType ( InValue . GetValue ( ) ) ;
2022-03-09 15:17:54 +00:00
bIsValid = true ;
}
return * this ;
}
2022-12-29 13:55:02 +00:00
/** Assigns by moving the state of 'InValue'. */
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr TOptional & operator = ( TOptional & & InValue ) requires ( CTriviallyMoveConstructible < T > & & CTriviallyMoveAssignable < T > ) = default ;
2022-11-17 15:17:50 +00:00
2022-12-29 13:55:02 +00:00
/** Assigns by moving the state of 'InValue'. */
2024-11-02 07:27:21 +00:00
constexpr TOptional & operator = ( TOptional & & InValue ) requires ( CMoveConstructible < T > & & CMoveAssignable < T >
& & ! CTriviallyMoveConstructible < T > & & ! CTriviallyMoveAssignable < T > )
2022-03-09 15:17:54 +00:00
{
2022-03-13 15:18:07 +00:00
if ( & InValue = = this ) return * this ;
2022-03-09 15:17:54 +00:00
2022-03-13 15:18:07 +00:00
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
return * this ;
}
2022-03-09 15:17:54 +00:00
2022-03-13 15:18:07 +00:00
if ( IsValid ( ) ) GetValue ( ) = MoveTemp ( InValue . GetValue ( ) ) ;
else
2022-03-09 15:17:54 +00:00
{
2024-12-16 11:34:47 +00:00
new ( & Value ) FValueType ( MoveTemp ( InValue . GetValue ( ) ) ) ;
2022-03-09 15:17:54 +00:00
bIsValid = true ;
}
return * this ;
}
2022-12-29 13:55:02 +00:00
/** Assigns by copying the state of 'InValue'. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( CConstructibleFrom < T , const U & >
& & CAssignableFrom < T & , const U & > & & NAMESPACE_PRIVATE : : CTOptionalAllowUnwrappable < U , T > )
constexpr TOptional & operator = ( const TOptional < U > & InValue )
2022-03-09 15:17:54 +00:00
{
2022-03-13 15:18:07 +00:00
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
return * this ;
}
2022-03-09 15:17:54 +00:00
2022-03-13 15:18:07 +00:00
if ( IsValid ( ) ) GetValue ( ) = InValue . GetValue ( ) ;
else
{
2024-12-16 11:34:47 +00:00
new ( & Value ) FValueType ( InValue . GetValue ( ) ) ;
2022-03-13 15:18:07 +00:00
bIsValid = true ;
}
2022-03-09 15:17:54 +00:00
return * this ;
}
2022-12-29 13:55:02 +00:00
/** Assigns by moving the state of 'InValue'. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( CConstructibleFrom < T , U & & >
& & CAssignableFrom < T & , U & & > & & NAMESPACE_PRIVATE : : CTOptionalAllowUnwrappable < U , T > )
constexpr TOptional & operator = ( TOptional < U > & & InValue )
2022-03-13 15:18:07 +00:00
{
if ( ! InValue . IsValid ( ) )
{
Reset ( ) ;
return * this ;
}
if ( IsValid ( ) ) GetValue ( ) = MoveTemp ( InValue . GetValue ( ) ) ;
else
{
2024-12-16 11:34:47 +00:00
new ( & Value ) FValueType ( MoveTemp ( InValue . GetValue ( ) ) ) ;
2022-03-13 15:18:07 +00:00
bIsValid = true ;
}
return * this ;
}
2022-12-29 13:55:02 +00:00
/** Assigns the value of 'InValue'. */
2024-11-02 07:27:21 +00:00
template < typename U = T > requires ( CConstructibleFrom < T , U & & > & & CAssignableFrom < T & , U & & > )
FORCEINLINE constexpr TOptional & operator = ( U & & InValue )
2022-03-13 15:18:07 +00:00
{
2024-11-02 07:27:21 +00:00
if ( IsValid ( ) ) GetValue ( ) = Forward < U > ( InValue ) ;
2022-03-13 15:18:07 +00:00
else
{
2024-12-16 11:34:47 +00:00
new ( & Value ) FValueType ( Forward < U > ( InValue ) ) ;
2022-03-13 15:18:07 +00:00
bIsValid = true ;
}
return * this ;
}
2024-10-30 08:00:39 +00:00
2022-12-29 13:55:02 +00:00
/** Check if the two optional are equivalent. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( CWeaklyEqualityComparable < T , U > )
NODISCARD friend FORCEINLINE constexpr bool operator = = ( const TOptional & LHS , const TOptional < U > & RHS )
2022-12-18 11:11:53 +00:00
{
if ( LHS . IsValid ( ) ! = RHS . IsValid ( ) ) return false ;
if ( LHS . IsValid ( ) = = false ) return true ;
return * LHS = = * RHS ;
}
2022-12-29 13:55:02 +00:00
/** Check the order relationship between two optional. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( CSynthThreeWayComparable < T , U > )
NODISCARD friend FORCEINLINE constexpr partial_ordering operator < = > ( const TOptional & LHS , const TOptional < U > & RHS )
2022-12-18 11:11:53 +00:00
{
if ( LHS . IsValid ( ) ! = RHS . IsValid ( ) ) return partial_ordering : : unordered ;
if ( LHS . IsValid ( ) = = false ) return partial_ordering : : equivalent ;
return SynthThreeWayCompare ( * LHS , * RHS ) ;
}
2022-12-29 13:55:02 +00:00
/** Check if the optional value is equivalent to 'InValue'. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( ! CTOptional < U > & & CWeaklyEqualityComparable < T , U > )
NODISCARD FORCEINLINE constexpr bool operator = = ( const U & InValue ) const &
2022-12-18 11:11:53 +00:00
{
return IsValid ( ) ? GetValue ( ) = = InValue : false ;
}
2022-12-29 13:55:02 +00:00
/** Check that the optional value is in ordered relationship with 'InValue'. */
2024-11-02 07:27:21 +00:00
template < typename U > requires ( ! CTOptional < U > & & CSynthThreeWayComparable < T , U > )
NODISCARD FORCEINLINE constexpr partial_ordering operator < = > ( const U & InValue ) const &
2022-12-18 11:11:53 +00:00
{
return IsValid ( ) ? SynthThreeWayCompare ( GetValue ( ) , InValue ) : partial_ordering : : unordered ;
}
2022-12-29 13:55:02 +00:00
/** @return true if instance does not contain a value, otherwise false. */
NODISCARD FORCEINLINE constexpr bool operator = = ( FInvalid ) const & { return ! IsValid ( ) ; }
/**
* Changes the contained object to one constructed from the arguments .
* First destroys the current contained object ( if any ) by Reset ( ) ,
* then constructs an object , direct - non - list - initialized from Forward < Ts > ( Args ) . . . , as the contained object .
*
2022-12-31 11:19:30 +00:00
* @ param Args - The arguments to be passed to the constructor of the object .
*
* @ return A reference to the new object .
*/
2024-11-02 07:27:21 +00:00
template < typename . . . Ts > requires ( CConstructibleFrom < T , Ts . . . > )
FORCEINLINE constexpr T & Emplace ( Ts & & . . . Args )
2022-12-31 11:19:30 +00:00
{
Reset ( ) ;
2024-12-16 11:34:47 +00:00
T * Result = new ( & Value ) FValueType ( Forward < Ts > ( Args ) . . . ) ;
2022-12-31 11:19:30 +00:00
bIsValid = true ;
return * Result ;
}
2024-10-30 08:00:39 +00:00
2022-12-31 11:19:30 +00:00
/**
* Changes the contained object to one constructed from the arguments .
* First destroys the current contained object ( if any ) by Reset ( ) ,
* then constructs an object , direct - non - list - initialized from IL , Forward < Ts > ( Args ) . . . , as the contained object .
*
* @ param IL , Args - The arguments to be passed to the constructor of the object .
2022-12-29 13:55:02 +00:00
*
* @ return A reference to the new object .
*/
2024-11-02 07:27:21 +00:00
template < typename W , typename . . . Ts > requires ( CConstructibleFrom < T , initializer_list < W > , Ts . . . > )
FORCEINLINE constexpr T & Emplace ( initializer_list < W > IL , Ts & & . . . Args )
2022-03-09 15:17:54 +00:00
{
Reset ( ) ;
2024-12-16 11:34:47 +00:00
T * Result = new ( & Value ) FValueType ( IL , Forward < Ts > ( Args ) . . . ) ;
2022-03-09 15:17:54 +00:00
bIsValid = true ;
return * Result ;
}
2022-12-29 13:55:02 +00:00
/** @return true if instance contains a value, otherwise false. */
NODISCARD FORCEINLINE constexpr bool IsValid ( ) const { return bIsValid ; }
NODISCARD FORCEINLINE constexpr explicit operator bool ( ) const { return bIsValid ; }
/** @return The contained object. */
2024-11-02 07:27:21 +00:00
NODISCARD FORCEINLINE constexpr T & 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 * reinterpret_cast < T * > ( & Value ) ; }
NODISCARD FORCEINLINE constexpr T & & 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 MoveTemp ( * reinterpret_cast < T * > ( & Value ) ) ; }
NODISCARD FORCEINLINE constexpr const T & 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 * reinterpret_cast < const T * > ( & Value ) ; }
NODISCARD FORCEINLINE constexpr const T & & 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 MoveTemp ( * reinterpret_cast < const T * > ( & Value ) ) ; }
2022-03-09 15:17:54 +00:00
2024-11-03 03:06:42 +00:00
/** @return The contained object. */
NODISCARD FORCEINLINE constexpr T & operator * ( ) & { checkf ( IsValid ( ) , TEXT ( " It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead. " ) ) ; return * reinterpret_cast < T * > ( & Value ) ; }
NODISCARD FORCEINLINE constexpr T & & operator * ( ) & & { checkf ( IsValid ( ) , TEXT ( " It is an error to call GetValue() on an unset TOptional. Please either check IsValid() or use Get(DefaultValue) instead. " ) ) ; return MoveTemp ( * reinterpret_cast < T * > ( & Value ) ) ; }
NODISCARD FORCEINLINE constexpr const T & operator * ( ) 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 * reinterpret_cast < const T * > ( & Value ) ; }
NODISCARD FORCEINLINE constexpr const T & & operator * ( ) 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 MoveTemp ( * reinterpret_cast < const T * > ( & Value ) ) ; }
2022-12-29 13:55:02 +00:00
/** @return The pointer to the contained object. */
2024-11-02 07:27:21 +00:00
NODISCARD FORCEINLINE constexpr const T * operator - > ( ) const { return & GetValue ( ) ; }
NODISCARD FORCEINLINE constexpr T * operator - > ( ) { return & GetValue ( ) ; }
2022-03-09 15:17:54 +00:00
2022-12-29 13:55:02 +00:00
/** @return The contained object when IsValid() returns true, 'DefaultValue' otherwise. */
2024-11-02 07:27:21 +00:00
NODISCARD FORCEINLINE constexpr T & Get ( T & DefaultValue ) & { return IsValid ( ) ? GetValue ( ) : DefaultValue ; }
NODISCARD FORCEINLINE constexpr const T & Get ( const T & DefaultValue ) const & { return IsValid ( ) ? GetValue ( ) : DefaultValue ; }
2022-03-09 15:17:54 +00:00
2022-12-29 13:55:02 +00:00
/** If not empty, destroys the contained object. */
2022-12-13 14:02:39 +00:00
FORCEINLINE constexpr void Reset ( )
2022-03-09 15:17:54 +00:00
{
if ( bIsValid )
{
bIsValid = false ;
2024-12-16 11:34:47 +00:00
reinterpret_cast < T * > ( & Value ) - > ~ FValueType ( ) ;
2022-03-09 15:17:54 +00:00
}
}
2022-12-29 13:55:02 +00:00
/** Overloads the GetTypeHash algorithm for TOptional. */
2024-11-02 07:27:21 +00:00
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash ( const TOptional & A ) requires ( CHashable < T > )
2022-04-22 14:28:44 +00:00
{
2022-12-19 10:00:52 +00:00
if ( ! A . IsValid ( ) ) return 2824517378 ;
return GetTypeHash ( A . GetValue ( ) ) ;
2022-04-22 14:28:44 +00:00
}
2022-12-29 13:55:02 +00:00
/** Overloads the Swap algorithm for TOptional. */
2024-11-02 07:27:21 +00:00
friend constexpr void Swap ( TOptional & A , TOptional & B ) requires ( CMoveConstructible < T > & & CSwappable < T > )
2022-04-14 14:41:22 +00:00
{
2022-12-19 10:00:52 +00:00
if ( ! A . IsValid ( ) & & ! B . IsValid ( ) ) return ;
2022-04-14 14:41:22 +00:00
2022-12-19 10:00:52 +00:00
if ( A . IsValid ( ) & & ! B . IsValid ( ) )
2022-04-14 14:41:22 +00:00
{
2022-12-19 10:00:52 +00:00
B = MoveTemp ( A ) ;
A . Reset ( ) ;
2022-04-14 14:41:22 +00:00
}
2022-12-19 10:00:52 +00:00
else if ( ! A . IsValid ( ) & & B . IsValid ( ) )
2022-04-14 14:41:22 +00:00
{
2022-12-19 10:00:52 +00:00
A = MoveTemp ( B ) ;
B . Reset ( ) ;
}
else
{
Swap ( A . GetValue ( ) , B . GetValue ( ) ) ;
2022-04-14 14:41:22 +00:00
}
}
2022-03-09 15:17:54 +00:00
private :
2024-11-02 07:27:21 +00:00
TAlignedStorage < sizeof ( T ) , alignof ( T ) > Value ;
2022-03-09 15:17:54 +00:00
bool bIsValid ;
} ;
2024-11-02 07:27:21 +00:00
/** The class template manages an optional contained reference, i.e. a reference that may or may not be present. */
template < typename T > requires ( CLValueReference < T > )
class TOptional < T , true > final
{
public :
2024-12-16 11:34:47 +00:00
using FValueType = TRemoveReference < T > ;
2024-11-02 07:27:21 +00:00
2024-12-16 11:34:47 +00:00
static_assert ( ! CReference < FValueType > ) ;
2024-11-02 07:27:21 +00:00
/** Constructs an object that does not contain a reference. */
FORCEINLINE constexpr TOptional ( ) : Ptr ( nullptr ) { }
/** Constructs an object that does not contain a reference. */
FORCEINLINE constexpr TOptional ( FInvalid ) : TOptional ( ) { }
/** Constructs an object with initial content an object, direct-initialized from Forward<U>(InValue). */
template < typename U = T > requires ( CConstructibleFrom < T , U > )
& & ( ! CSameAs < TRemoveCVRef < U > , FInPlace > ) & & ( ! CSameAs < TOptional , TRemoveCVRef < U > > )
FORCEINLINE constexpr explicit ( ! CConvertibleTo < U & & , T > ) TOptional ( U & & InValue )
: Ptr ( AddressOf ( static_cast < T > ( Forward < U > ( InValue ) ) ) )
{ }
/** Copies content of other into a new instance. */
FORCEINLINE constexpr TOptional ( const TOptional & ) = default ;
FORCEINLINE constexpr TOptional ( TOptional & & ) = default ;
/** Converting constructor. */
template < typename U > requires ( CConstructibleFrom < T , U > & & NAMESPACE_PRIVATE : : CTOptionalAllowUnwrappable < U , T > )
FORCEINLINE constexpr explicit ( ! CConvertibleTo < U , T > ) TOptional ( TOptional < U , true > InValue )
: Ptr ( InValue . IsValid ( ) ? AddressOf ( static_cast < T > ( InValue . GetValue ( ) ) ) : nullptr )
{ }
/** Converting constructor. */
2024-12-16 11:34:47 +00:00
template < typename U > requires ( ! CConst < FValueType > & & CConstructibleFrom < T , U & > & & NAMESPACE_PRIVATE : : CTOptionalAllowUnwrappable < U , T > )
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr explicit ( ! CConvertibleTo < U & , T > ) TOptional ( TOptional < U , false > & InValue )
: Ptr ( InValue . IsValid ( ) ? AddressOf ( static_cast < T > ( InValue . GetValue ( ) ) ) : nullptr )
{ }
/** Converting constructor. */
2024-12-16 11:34:47 +00:00
template < typename U > requires ( CConst < FValueType > & & CConstructibleFrom < T , const U & > & & NAMESPACE_PRIVATE : : CTOptionalAllowUnwrappable < U , T > )
2024-11-02 07:27:21 +00:00
FORCEINLINE constexpr explicit ( ! CConvertibleTo < const U & , T > ) TOptional ( const TOptional < U , false > & InValue )
: Ptr ( InValue . IsValid ( ) ? AddressOf ( static_cast < T > ( InValue . GetValue ( ) ) ) : nullptr )
{ }
/** Assigns by copying the state of 'InValue'. */
FORCEINLINE constexpr TOptional & operator = ( const TOptional & ) = default ;
FORCEINLINE constexpr TOptional & operator = ( TOptional & & ) = default ;
/** Destructor. */
FORCEINLINE constexpr ~ TOptional ( ) = default ;
/** Check if the two optional are equivalent. */
template < typename U > requires ( CWeaklyEqualityComparable < T , U > )
NODISCARD friend FORCEINLINE constexpr bool operator = = ( TOptional LHS , TOptional < U , true > RHS )
{
if ( LHS . IsValid ( ) ! = RHS . IsValid ( ) ) return false ;
if ( LHS . IsValid ( ) = = false ) return true ;
return * LHS = = * RHS ;
}
/** Check the order relationship between two optional. */
template < typename U > requires ( CSynthThreeWayComparable < T , U > )
NODISCARD friend FORCEINLINE constexpr partial_ordering operator < = > ( TOptional LHS , TOptional < U , true > RHS )
{
if ( LHS . IsValid ( ) ! = RHS . IsValid ( ) ) return partial_ordering : : unordered ;
if ( LHS . IsValid ( ) = = false ) return partial_ordering : : equivalent ;
return SynthThreeWayCompare ( * LHS , * RHS ) ;
}
/** Check if the optional reference is equivalent to 'InValue'. */
template < typename U > requires ( ! CTOptional < U > & & CWeaklyEqualityComparable < T , U > )
NODISCARD FORCEINLINE constexpr bool operator = = ( const U & InValue ) const &
{
return IsValid ( ) ? GetValue ( ) = = InValue : false ;
}
/** Check that the optional reference is in ordered relationship with 'InValue'. */
template < typename U > requires ( ! CTOptional < U > & & CSynthThreeWayComparable < T , U > )
NODISCARD FORCEINLINE constexpr partial_ordering operator < = > ( const U & InValue ) const &
{
return IsValid ( ) ? SynthThreeWayCompare ( GetValue ( ) , InValue ) : partial_ordering : : unordered ;
}
/** @return true if instance does not contain a reference, otherwise false. */
NODISCARD FORCEINLINE constexpr bool operator = = ( FInvalid ) const & { return ! IsValid ( ) ; }
/** @return true if instance contains a reference, otherwise false. */
NODISCARD FORCEINLINE constexpr bool IsValid ( ) const { return Ptr ! = nullptr ; }
NODISCARD FORCEINLINE constexpr explicit operator bool ( ) const { return Ptr ! = nullptr ; }
/** @return The contained object. */
NODISCARD FORCEINLINE constexpr T 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 * Ptr ; }
/** @return The pointer to the contained object. */
NODISCARD FORCEINLINE constexpr auto operator - > ( ) const { return Ptr ; }
/** @return The contained object. */
NODISCARD FORCEINLINE constexpr T operator * ( ) const { return GetValue ( ) ; }
/** @return The contained object when IsValid() returns true, 'DefaultValue' otherwise. */
NODISCARD FORCEINLINE constexpr T Get ( T DefaultValue ) const { return IsValid ( ) ? GetValue ( ) : DefaultValue ; }
/** If not empty, destroys the contained object. */
FORCEINLINE constexpr void Reset ( )
{
Ptr = nullptr ;
}
/** Overloads the GetTypeHash algorithm for TOptional. */
NODISCARD friend FORCEINLINE constexpr size_t GetTypeHash ( const TOptional & A ) requires ( CHashable < T > )
{
if ( ! A . IsValid ( ) ) return 2824517378 ;
return GetTypeHash ( A . GetValue ( ) ) ;
}
private :
2024-12-16 11:34:47 +00:00
FValueType * Ptr ;
2024-11-02 07:27:21 +00:00
} ;
2022-03-09 15:17:54 +00:00
template < typename T >
2022-04-13 14:35:30 +00:00
TOptional ( T ) - > TOptional < T > ;
2022-03-09 15:17:54 +00:00
2022-12-29 13:55:02 +00:00
/** Creates an optional object from value. */
2023-02-20 10:53:59 +00:00
template < typename T > requires ( CDestructible < TDecay < T > > & & CConstructibleFrom < TDecay < T > , T > )
NODISCARD FORCEINLINE constexpr TOptional < TDecay < T > > MakeOptional ( T & & InValue )
2022-03-09 15:17:54 +00:00
{
2023-02-20 10:53:59 +00:00
return TOptional < TDecay < T > > ( Forward < T > ( InValue ) ) ;
2022-03-09 15:17:54 +00:00
}
2023-02-20 10:53:59 +00:00
/** Creates an optional object constructed in-place from Args.... */
2022-11-16 14:03:54 +00:00
template < typename T , typename . . . Ts > requires ( CDestructible < T > & & CConstructibleFrom < T , Ts . . . > )
2022-12-29 13:55:02 +00:00
NODISCARD FORCEINLINE constexpr TOptional < T > MakeOptional ( Ts & & . . . Args )
2022-03-09 15:17:54 +00:00
{
return TOptional < T > ( InPlace , Forward < T > ( Args ) . . . ) ;
}
2023-02-20 10:53:59 +00:00
/** Creates an optional object constructed in-place from IL, Args.... */
template < typename T , typename U , typename . . . Ts > requires ( CDestructible < T > & & CConstructibleFrom < T , initializer_list < U > , Ts . . . > )
NODISCARD FORCEINLINE constexpr TOptional < T > MakeOptional ( initializer_list < U > IL , Ts & & . . . Args )
{
return TOptional < T > ( InPlace , IL , Forward < T > ( Args ) . . . ) ;
}
2022-03-09 15:17:54 +00:00
NAMESPACE_MODULE_END ( Utility )
NAMESPACE_MODULE_END ( Redcraft )
NAMESPACE_REDCRAFT_END