@ -1,6 +1,6 @@
# pragma once
# include <optional>
# include <utility>
# include <concepts>
@ -21,6 +21,18 @@ namespace exopt::types { namespace optional [[gnu::visibility("internal")]] {
constexpr static inline auto sentinel = nullptr ;
} ;
template < typename T >
struct null_optimise < std : : reference_wrapper < T > > { constexpr static inline bool value = true ;
using held_type = T * ;
using type = std : : reference_wrapper < T > ;
constexpr static decltype ( auto ) convert_to_held ( std : : add_rvalue_reference_t < type > t ) noexcept { return std : : addressof ( t . get ( ) ) ; }
constexpr static decltype ( auto ) convert_from_held ( std : : add_rvalue_reference_t < held_type > t ) noexcept { return std : : ref < T > ( * t ) ; }
constexpr static inline auto sentinel = nullptr ;
} ;
template < typename T >
struct null_optimise < ptr : : Unique < T > > { constexpr static inline bool value = true ;
using held_type = T __restrict__ * ;
@ -233,6 +245,7 @@ namespace exopt::types { namespace optional [[gnu::visibility("internal")]] {
constexpr ~ none_t ( ) noexcept = default ;
constexpr none_t ( std : : nullptr_t ) noexcept : none_t ( ) { }
constexpr none_t ( std : : nullopt_t ) noexcept : none_t ( ) { }
constexpr operator std : : nullptr_t ( ) const noexcept { return nullptr ; }
} ;
@ -268,6 +281,14 @@ namespace exopt::types { namespace optional [[gnu::visibility("internal")]] {
constexpr static inline bool is_null_optimised = has_null_opt < T > ;
constexpr friend void swap ( Option & a , Option & b ) noexcept {
using std : : swap ;
swap ( a . inner_ , b . inner_ ) ; //XXX: Swap the values if possible?
}
constexpr Option ( std : : optional < T > & & opt ) noexcept requires ( ! std : : is_void_v < T > )
: inner_ ( bool ( opt ) ? std : : move ( * opt ) : nullptr ) { }
constexpr explicit Option ( std : : nullptr_t ) noexcept : inner_ ( nullptr ) { }
constexpr Option ( none_t ) noexcept : Option ( nullptr ) { }
constexpr ~ Option ( ) noexcept ( std : : is_nothrow_destructible_v < T > ) { }
@ -541,6 +562,24 @@ namespace exopt::types { namespace optional [[gnu::visibility("internal")]] {
// ---
} ;
template < typename T , typename U > requires ( requires ( T & & p ) { static_cast < U & & > ( p ) ; } )
constexpr Option < U > static_opt_cast ( Option < T > & & p ) noexcept
{
if ( bool ( p ) ) return Option < U > { static_cast < U & & > ( std : : move ( * p ) ) } ;
return Option < U > { nullptr } ;
}
template < typename T , typename U > requires ( requires ( T & & p ) { static_cast < U & & > ( p ) ; } )
constexpr Option < U > dynamic_opt_cast ( Option < T > & & p )
{
if ( T * ptr = p . try_get_value ( ) )
if ( U * pv = dynamic_cast < U * > ( ptr ) )
return Option < U > { std : : move ( * pv ) } ;
return Option < U > { nullptr } ;
}
static_assert ( sizeof ( Option < void * > ) > sizeof ( void * ) , " Option<T*>: Bad null_opt size " ) ;
static_assert ( alignof ( Option < void * > ) = = alignof ( void * ) , " Option<T*>: Bad null_opt align " ) ;
static_assert ( sizeof ( Option < ptr : : NonNull < int > > ) = = sizeof ( int * ) , " Option<NonNull<T>>: Bad null_opt size " ) ;
@ -557,4 +596,5 @@ namespace exopt::types { namespace optional [[gnu::visibility("internal")]] {
}
using optional : : Option ;
}