12 #ifndef NONSTD_EXPECTED_LITE_HPP 13 #define NONSTD_EXPECTED_LITE_HPP 15 #define expected_lite_MAJOR 0 16 #define expected_lite_MINOR 2 17 #define expected_lite_PATCH 0 19 #define expected_lite_VERSION expected_STRINGIFY(expected_lite_MAJOR) "." expected_STRINGIFY(expected_lite_MINOR) "." expected_STRINGIFY(expected_lite_PATCH) 21 #define expected_STRINGIFY( x ) expected_STRINGIFY_( x ) 22 #define expected_STRINGIFY_( x ) #x 26 #define nsel_EXPECTED_DEFAULT 0 27 #define nsel_EXPECTED_NONSTD 1 28 #define nsel_EXPECTED_STD 2 30 #if !defined( nsel_CONFIG_SELECT_EXPECTED ) 31 # define nsel_CONFIG_SELECT_EXPECTED ( nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD ) 52 # define nsel_P0323R 5 58 #ifndef nsel_CPLUSPLUS 59 # if defined(_MSVC_LANG ) && !defined(__clang__) 60 # define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) 62 # define nsel_CPLUSPLUS __cplusplus 66 #define nsel_CPP98_OR_GREATER ( nsel_CPLUSPLUS >= 199711L ) 67 #define nsel_CPP11_OR_GREATER ( nsel_CPLUSPLUS >= 201103L ) 68 #define nsel_CPP14_OR_GREATER ( nsel_CPLUSPLUS >= 201402L ) 69 #define nsel_CPP17_OR_GREATER ( nsel_CPLUSPLUS >= 201703L ) 70 #define nsel_CPP20_OR_GREATER ( nsel_CPLUSPLUS >= 202000L ) 74 #if nsel_CPP20_OR_GREATER && defined(__has_include ) 75 # if __has_include( <expected> ) 76 # define nsel_HAVE_STD_EXPECTED 1 78 # define nsel_HAVE_STD_EXPECTED 0 81 # define nsel_HAVE_STD_EXPECTED 0 84 #define nsel_USES_STD_EXPECTED ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) ) 90 #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES 91 #define nonstd_lite_HAVE_IN_PLACE_TYPES 1 95 #if nsel_CPP17_OR_GREATER 104 using std::in_place_t;
105 using std::in_place_type_t;
106 using std::in_place_index_t;
108 #define nonstd_lite_in_place_t( T) std::in_place_t 109 #define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T> 110 #define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K> 112 #define nonstd_lite_in_place( T) std::in_place_t{} 113 #define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{} 114 #define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{} 118 #else // nsel_CPP17_OR_GREATER 128 template< std::
size_t K >
141 template< std::
size_t K >
153 template< std::
size_t K >
161 #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) 162 #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> ) 163 #define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> ) 165 #define nonstd_lite_in_place( T) nonstd::in_place_type<T> 166 #define nonstd_lite_in_place_type( T) nonstd::in_place_type<T> 167 #define nonstd_lite_in_place_index(K) nonstd::in_place_index<K> 171 #endif // nsel_CPP17_OR_GREATER 172 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES 178 #if nsel_USES_STD_EXPECTED 188 #else // nsel_USES_STD_EXPECTED 192 #include <functional> 193 #include <initializer_list> 196 #include <system_error> 197 #include <type_traits> 200 #if nsel_CPP11_OR_GREATER 201 # define nsel_constexpr constexpr 203 # define nsel_constexpr 206 #if nsel_CPP14_OR_GREATER 207 # define nsel_constexpr14 constexpr 209 # define nsel_constexpr14 212 #if nsel_CPP17_OR_GREATER 213 # define nsel_inline17 inline 215 # define nsel_inline17 220 #define nsel_REQUIRES_A(...) \ 221 , typename std::enable_if<__VA_ARGS__, void*>::type = nullptr 223 #define nsel_REQUIRES_0(...) \ 224 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 > 226 #define nsel_REQUIRES_R(R, ...) \ 227 typename std::enable_if<__VA_ARGS__, R>::type 229 #define nsel_REQUIRES_T(...) \ 230 , typename = typename std::enable_if< (__VA_ARGS__), nonstd::expected_lite::detail::enabler >::type 245 #if defined(_MSC_VER) && !defined(__clang__) 246 # define nsel_COMPILER_MSVC_VER (_MSC_VER ) 247 # define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) ) 249 # define nsel_COMPILER_MSVC_VER 0 250 # define nsel_COMPILER_MSVC_VERSION 0 253 #define nsel_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) 255 #if defined(__clang__) 256 # define nsel_COMPILER_CLANG_VERSION nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) 258 # define nsel_COMPILER_CLANG_VERSION 0 261 #if defined(__GNUC__) && !defined(__clang__) 262 # define nsel_COMPILER_GNUC_VERSION nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 264 # define nsel_COMPILER_GNUC_VERSION 0 273 # define nsel_HAS_CPP0X _HAS_CPP0X 275 # define nsel_HAS_CPP0X 0 283 # pragma clang diagnostic push 284 #elif defined __GNUC__ 285 # pragma GCC diagnostic push 288 #if nsel_COMPILER_MSVC_VERSION >= 140 289 # pragma warning( push ) 290 # define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(disable: codes) ) 292 # define nsel_DISABLE_MSVC_WARNINGS(codes) 296 # define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") 297 #elif defined __GNUC__ 298 # define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") 299 #elif nsel_COMPILER_MSVC_VERSION >= 140 300 # define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) ) 302 # define nsel_RESTORE_WARNINGS() 314 namespace
nonstd {
namespace expected_lite {
320 template<
typename T >
323 typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
330 template<
typename T,
typename E >
337 enum class enabler{};
341 template<
typename T,
typename E >
344 friend class expected<T,E>;
347 using value_type = T;
348 using error_type = E;
354 template<
class ...Args>
355 void construct_value(Args&& ...args)
357 new(&m_value) value_type(std::forward<Args>(args)...);
360 void destruct_value()
362 m_value.~value_type();
365 void construct_error( error_type
const & e )
367 new( &m_error ) error_type( e );
370 void construct_error( error_type && e )
372 new( &m_error ) error_type( std::move( e ) );
375 void destruct_error()
377 m_error.~error_type();
380 constexpr value_type
const & value()
const &
385 value_type & value() &
390 constexpr value_type
const && value()
const &&
392 return std::move( m_value );
397 return std::move( m_value );
400 value_type
const * value_ptr()
const 405 value_type * value_ptr()
410 error_type
const & error()
const 427 template<
typename E >
428 union storage_t<void, E>
430 friend class expected<void,E>;
433 using value_type = void;
434 using error_type = E;
440 void construct_error( error_type
const & e )
442 new( &m_error ) error_type( e );
445 void construct_error( error_type && e )
447 new( &m_error ) error_type( std::move( e ) );
450 void destruct_error()
452 m_error.~error_type();
455 error_type
const & error()
const 474 template<
typename E = std::exception_ptr >
475 class unexpected_type
477 template< typename E >
478 class unexpected_type
482 using error_type = E;
484 unexpected_type() =
delete;
485 constexpr unexpected_type( unexpected_type
const &) =
default;
486 constexpr unexpected_type( unexpected_type &&) =
default;
487 nsel_constexpr14 unexpected_type& operator=( unexpected_type
const &) =
default;
490 template<
typename E2
492 std::is_constructible<E,E2&&>::value
495 constexpr
explicit unexpected_type( E2 && error )
496 : m_error( std::forward<E2>( error ) )
499 template<
typename E2 >
500 constexpr
explicit unexpected_type( unexpected_type<E2>
const & error
502 std::is_constructible<E,E2 const &>::value
503 && !std::is_convertible<E2 const &, E>::value )
508 template<
typename E2 >
509 constexpr unexpected_type( unexpected_type<E2>
const & error
511 std::is_constructible<E,E2 const &>::value
512 && std::is_convertible<E2 const &, E>::value )
517 template<
typename E2 >
518 constexpr
explicit unexpected_type( unexpected_type<E2> && error
520 std::is_constructible<E,E2&&>::value
521 && !std::is_convertible<E2&&, E>::value )
526 template<
typename E2 >
527 constexpr unexpected_type( unexpected_type<E2> && error
529 std::is_constructible<E,E2&&>::value
530 && std::is_convertible<E2&&, E>::value )
540 constexpr E
const & value()
const & noexcept
547 return std::move( m_error );
550 constexpr E
const && value()
const && noexcept
552 return std::move( m_error );
560 void swap( unexpected_type & other ) noexcept (
562 std::is_nothrow_move_constructible<E>::value
563 && std::is_nothrow_swappable<E&>::value
565 std::is_nothrow_move_constructible<E>::value
566 && noexcept (
std::swap( std::declval<E&>(), std::declval<E&>() ) )
571 swap( m_error, other.m_error );
583 class unexpected_type< std::exception_ptr >
586 using error_type = std::exception_ptr;
588 unexpected_type() =
delete;
592 explicit unexpected_type( std::exception_ptr
const & error )
596 explicit unexpected_type(std::exception_ptr && error )
597 : m_error( std::move( error ) )
600 template<
typename E >
601 explicit unexpected_type( E error )
602 : m_error( std::make_exception_ptr( error ) )
605 std::exception_ptr
const & value()
const 610 std::exception_ptr & value()
616 std::exception_ptr m_error;
619 #endif // nsel_P0323R 623 template<
typename E >
624 constexpr
bool operator==( unexpected_type<E>
const & x, unexpected_type<E>
const & y )
626 return x.value() == y.value();
629 template<
typename E >
630 constexpr
bool operator!=( unexpected_type<E>
const & x, unexpected_type<E>
const & y )
637 template<
typename E >
638 constexpr
bool operator<( unexpected_type<E>
const & x, unexpected_type<E>
const & y )
640 return x.value() < y.value();
643 template<
typename E >
644 constexpr
bool operator>( unexpected_type<E>
const & x, unexpected_type<E>
const & y )
649 template<
typename E >
650 constexpr
bool operator<=( unexpected_type<E>
const & x, unexpected_type<E>
const & y )
655 template<
typename E >
656 constexpr
bool operator>=( unexpected_type<E>
const & x, unexpected_type<E>
const & y )
663 template<
typename E >
664 void swap( unexpected_type<E> & x, unexpected_type<E> & y) noexcept ( noexcept ( x.swap(y) ) )
671 inline constexpr
bool operator<( unexpected_type<std::exception_ptr>
const & , unexpected_type<std::exception_ptr>
const & )
676 inline constexpr
bool operator>( unexpected_type<std::exception_ptr>
const & , unexpected_type<std::exception_ptr>
const & )
681 inline constexpr
bool operator<=( unexpected_type<std::exception_ptr>
const & x, unexpected_type<std::exception_ptr>
const & y )
686 inline constexpr
bool operator>=( unexpected_type<std::exception_ptr>
const & x, unexpected_type<std::exception_ptr>
const & y )
691 #endif // nsel_P0323R 697 template<
typename E>
698 struct is_unexpected : std::false_type {};
700 template<
typename E>
701 struct is_unexpected< unexpected_type<E> > : std::true_type {};
703 #endif // nsel_P0323R 709 template<
typename E>
711 make_unexpected( E && value ) -> unexpected_type< typename std::decay<E>::type >
713 return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
719 make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
721 return unexpected_type< std::exception_ptr >( std::current_exception() );
724 #endif // nsel_P0323R 729 using in_place_unexpected_t = unexpect_t;
736 template<
typename E >
737 class bad_expected_access;
740 class bad_expected_access< void > :
public std::exception
743 explicit bad_expected_access()
748 template<
typename E >
749 class bad_expected_access :
public bad_expected_access< void >
752 using error_type = E;
754 explicit bad_expected_access( error_type error )
758 virtual char const * what()
const noexcept
override 760 return "bad_expected_access";
768 constexpr error_type
const & error()
const &
775 return std::move( m_error );
778 constexpr error_type
const && error()
const &&
780 return std::move( m_error );
789 template<
typename Error >
792 static void rethrow( Error
const & e )
794 throw bad_expected_access<Error>{ e };
799 struct error_traits< std::exception_ptr >
801 static void rethrow( std::exception_ptr
const & e )
803 std::rethrow_exception( e );
808 struct error_traits< std::error_code >
810 static void rethrow( std::error_code
const & e )
812 throw std::system_error( e );
820 using expected_lite::unexpected_type;
822 namespace expected_lite {
827 template<
typename T,
typename E = std::exception_ptr >
830 template< typename T, typename E >
835 using value_type = T;
836 using error_type = E;
837 using unexpected_type = nonstd::unexpected_type<E>;
839 template<
typename U >
842 using type = expected<U, error_type>;
848 std::is_default_constructible<T>::value
852 std::is_nothrow_default_constructible<T>::value
856 contained.construct_value( value_type() );
865 : has_value_( other.has_value_ )
867 if ( has_value() ) contained.construct_value( other.contained.value() );
868 else contained.construct_error( other.contained.error() );
877 std::is_nothrow_move_constructible<T>::value
878 && std::is_nothrow_move_constructible<E>::value
880 : has_value_( other.has_value_ )
882 if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
883 else contained.construct_error( std::move( other.contained.error() ) );
886 template<
typename U,
typename G >
889 std::is_constructible<T, const U&>::value
890 && std::is_constructible<E, const G&>::value
891 && !std::is_constructible<T, expected<U, G>&>::value
892 && !std::is_constructible<T, expected<U, G>&&>::value
893 && !std::is_constructible<T,
const expected<U, G>&>::value
894 && !std::is_constructible<T,
const expected<U, G>&&>::value
895 && !std::is_convertible<expected<U, G>&, T>::value
896 && !std::is_convertible<expected<U, G>&&, T>::value
897 && !std::is_convertible<
const expected<U, G>&, T>::value
898 && !std::is_convertible<
const expected<U, G>&&, T>::value
899 && (!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) )
901 : has_value_( other.has_value_ )
903 if ( has_value() ) contained.construct_value( other.contained.value() );
904 else contained.construct_error( other.contained.error() );
907 template<
typename U,
typename G >
910 std::is_constructible<T, const U&>::value
911 && std::is_constructible<E, const G&>::value
912 && !std::is_constructible<T, expected<U, G>&>::value
913 && !std::is_constructible<T, expected<U, G>&&>::value
914 && !std::is_constructible<T,
const expected<U, G>&>::value
915 && !std::is_constructible<T,
const expected<U, G>&&>::value
916 && !std::is_convertible<expected<U, G>&, T>::value
917 && !std::is_convertible<expected<U, G>&&, T>::value
918 && !std::is_convertible<
const expected<U, G>&, T>::value
919 && !std::is_convertible<
const expected<U, G>&&, T>::value
920 && !(!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) )
922 : has_value_( other.has_value_ )
924 if ( has_value() ) contained.construct_value( other.contained.value() );
925 else contained.construct_error( other.contained.error() );
928 template<
typename U,
typename G >
931 std::is_constructible<T, U>::value
932 && std::is_constructible<E, G>::value
933 && !std::is_constructible<T, expected<U, G>&>::value
934 && !std::is_constructible<T, expected<U, G>&&>::value
935 && !std::is_constructible<T,
const expected<U, G>&>::value
936 && !std::is_constructible<T,
const expected<U, G>&&>::value
937 && !std::is_convertible<expected<U, G>&, T>::value
938 && !std::is_convertible<expected<U, G>&&, T>::value
939 && !std::is_convertible<
const expected<U, G>&, T>::value
940 && !std::is_convertible<
const expected<U, G>&&, T>::value
941 && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) )
943 : has_value_( other.has_value_ )
945 if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
946 else contained.construct_error( std::move( other.contained.error() ) );
949 template<
typename U,
typename G >
952 std::is_constructible<T, U>::value
953 && std::is_constructible<E, G>::value
954 && !std::is_constructible<T, expected<U, G>&>::value
955 && !std::is_constructible<T, expected<U, G>&&>::value
956 && !std::is_constructible<T,
const expected<U, G>&>::value
957 && !std::is_constructible<T,
const expected<U, G>&&>::value
958 && !std::is_convertible<expected<U, G>&, T>::value
959 && !std::is_convertible<expected<U, G>&&, T>::value
960 && !std::is_convertible<
const expected<U, G>&, T>::value
961 && !std::is_convertible<
const expected<U, G>&&, T>::value
962 && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) )
964 : has_value_( other.has_value_ )
966 if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
967 else contained.construct_error( std::move( other.contained.error() ) );
976 contained.construct_value( value );
979 template<
typename U = T >
982 std::is_constructible<T,U&&>::value
984 && !std::is_same<expected<T,E>,
typename std20::remove_cvref<U>::type>::value
985 && !std::is_same<nonstd::unexpected_type<E>,
typename std20::remove_cvref<U>::type>::value
986 && !std::is_convertible<U&&,T>::value
990 std::is_nothrow_move_constructible<U>::value &&
991 std::is_nothrow_move_constructible<E>::value
995 contained.construct_value( std::forward<U>( value ) );
998 template<
typename U = T >
1001 std::is_constructible<T,U&&>::value
1003 && !std::is_same<expected<T,E>,
typename std20::remove_cvref<U>::type>::value
1004 && !std::is_same<nonstd::unexpected_type<E>,
typename std20::remove_cvref<U>::type>::value
1005 && std::is_convertible<U&&,T>::value
1009 std::is_nothrow_move_constructible<U>::value &&
1010 std::is_nothrow_move_constructible<E>::value
1012 : has_value_(
true )
1014 contained.construct_value( std::forward<U>( value ) );
1017 template<
typename... Args
1019 std::is_constructible<T, Args&&...>::value
1023 : has_value_(
true )
1025 contained.construct_value( std::forward<Args>( args )... );
1028 template<
typename U,
typename... Args
1030 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
1034 : has_value_(
true )
1036 contained.construct_value( il, std::forward<Args>( args )... );
1039 template<
typename G = E >
1040 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G>
const & error
1042 !std::is_convertible<const G&, E>::value )
1044 : has_value_(
false )
1046 contained.construct_error( error.value() );
1049 template<
typename G = E >
1052 std::is_convertible<const G&, E>::value )
1054 : has_value_(
false )
1056 contained.construct_error( error.value() );
1059 template<
typename G = E >
1062 !std::is_convertible<G&&, E>::value )
1064 : has_value_(
false )
1066 contained.construct_error( std::move( error.value() ) );
1069 template<
typename G = E >
1072 std::is_convertible<G&&, E>::value )
1074 : has_value_(
false )
1076 contained.construct_error( std::move( error.value() ) );
1079 template<
typename... Args
1081 std::is_constructible<E, Args&&...>::value
1085 : has_value_(
false )
1087 contained.construct_error( std::forward<Args>( args )... );
1090 template<
typename U,
typename... Args
1092 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
1095 nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
1096 : has_value_(
false )
1098 contained.construct_error( il, std::forward<Args>( args )... );
1105 if ( has_value() ) contained.destruct_value();
1106 else contained.destruct_error();
1117 expected operator=( expected
const & other )
1119 expected( other ).swap( *
this );
1129 expected & operator=( expected && other ) noexcept
1131 std::is_nothrow_move_assignable<T>::value &&
1132 std::is_nothrow_move_constructible<T>::value&&
1133 std::is_nothrow_move_assignable<E>::value &&
1134 std::is_nothrow_move_constructible<E>::value )
1136 expected( std::move( other ) ).swap( *
this );
1140 template<
typename U
1142 std::is_constructible<T,U>::value &&
1143 std::is_assignable<T&, U>::value
1146 expected & operator=( U && value )
1148 expected( std::forward<U>( value ) ).swap( *
this );
1156 expected & operator=( unexpected_type
const & uvalue )
1158 expected( std::move( uvalue ) ).swap( *
this );
1166 expected & operator=( unexpected_type && uvalue )
1168 expected( std::move( uvalue ) ).swap( *
this );
1172 template<
typename... Args
1174 std::is_constructible<T, Args&&...>::value
1177 void emplace( Args &&... args )
1182 template<
typename U,
typename... Args
1184 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1187 void emplace( std::initializer_list<U> il, Args &&... args )
1198 void swap( expected & other ) noexcept
1201 std::is_nothrow_move_constructible<T>::value && std::is_nothrow_swappable<T&>::value &&
1202 std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value
1204 std::is_nothrow_move_constructible<T>::value && noexcept (
std::swap( std::declval<T&>(), std::declval<T&>() ) ) &&
1205 std::is_nothrow_move_constructible<E>::value && noexcept (
std::swap( std::declval<E&>(), std::declval<E&>() ) )
1211 if (
bool(*
this) &&
bool(other) ) {
swap( contained.value(), other.contained.value() ); }
1212 else if ( !
bool(*
this) && ! bool(other) ) {
swap( contained.error(), other.contained.error() ); }
1213 else if (
bool(*
this) && ! bool(other) ) { error_type t( std::move( other.error() ) );
1214 other.contained.destruct_error();
1215 other.contained.construct_value( std::move( contained.value() ) );
1216 contained.destruct_value();
1217 contained.construct_error( std::move( t ) );
1218 swap( has_value_, other.has_value_ ); }
1219 else if ( !
bool(*
this) &&
bool(other) ) { other.swap( *
this ); }
1224 constexpr value_type
const * operator ->()
const 1226 return assert( has_value() ), contained.value_ptr();
1229 value_type * operator ->()
1231 return assert( has_value() ), contained.value_ptr();
1234 constexpr value_type
const & operator *()
const &
1236 return assert( has_value() ), contained.value();
1239 value_type & operator *() &
1241 return assert( has_value() ), contained.value();
1244 constexpr value_type
const && operator *()
const &&
1246 return assert( has_value() ), std::move( contained.value() );
1251 return assert( has_value() ), std::move( contained.value() );
1254 constexpr
explicit operator bool()
const noexcept
1259 constexpr
bool has_value()
const noexcept
1264 constexpr value_type
const & value()
const &
1267 ? ( contained.value() )
1268 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
1271 value_type & value() &
1274 ? ( contained.value() )
1275 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
1278 constexpr value_type
const && value()
const &&
1280 return std::move( has_value()
1281 ? ( contained.value() )
1282 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
1287 return std::move( has_value()
1288 ? ( contained.value() )
1289 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
1292 constexpr error_type
const & error()
const &
1294 return assert( ! has_value() ), contained.error();
1297 error_type & error() &
1299 return assert( ! has_value() ), contained.error();
1302 constexpr error_type
const && error()
const &&
1304 return assert( ! has_value() ), std::move( contained.error() );
1307 error_type && error() &&
1309 return assert( ! has_value() ), std::move( contained.error() );
1312 constexpr unexpected_type get_unexpected()
const 1314 return make_unexpected( contained.error() );
1317 template<
typename Ex >
1318 bool has_exception()
const 1320 using ContainedEx =
typename std::remove_reference< decltype( get_unexpected().value() ) >::type;
1321 return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
1324 template<
typename U
1326 std::is_copy_constructible<T>::value &&
1327 std::is_convertible<U&&, T>::value
1330 value_type value_or( U && v )
const &
1334 :
static_cast<T
>( std::forward<U>( v ) );
1337 template<
typename U
1339 std::is_move_constructible<T>::value &&
1340 std::is_convertible<U&&, T>::value
1343 value_type value_or( U && v ) &&
1346 ? std::move( contained.value() )
1347 : static_cast<T>( std::forward<U>( v ) );
1383 detail::storage_t<T,E> contained;
1388 template<
typename E >
1389 class expected<void, E>
1392 using value_type = void;
1393 using error_type = E;
1394 using unexpected_type = nonstd::unexpected_type<E>;
1398 constexpr expected() noexcept
1399 : has_value_(
true )
1404 : has_value_( other.has_value_ )
1406 if ( ! has_value() ) contained.construct_error( other.contained.error() );
1410 std::is_move_constructible<E>::value
1416 : has_value_( other.has_value_ )
1418 if ( ! has_value() ) contained.construct_error( std::move( other.contained.error() ) );
1422 : has_value_(
true )
1426 template<
typename G = E >
1427 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G>
const & error
1429 !std::is_convertible<const G&, E>::value
1432 : has_value_(
false )
1434 contained.construct_error( error.value() );
1437 template<
typename G = E >
1440 std::is_convertible<const G&, E>::value
1443 : has_value_(
false )
1445 contained.construct_error( error.value() );
1448 template<
typename G = E >
1451 !std::is_convertible<G&&, E>::value
1454 : has_value_(
false )
1456 contained.construct_error( std::move( error.value() ) );
1459 template<
typename G = E >
1462 std::is_convertible<G&&, E>::value
1465 : has_value_(
false )
1467 contained.construct_error( std::move( error.value() ) );
1470 template<
typename... Args
1472 std::is_constructible<E, Args&&...>::value
1476 : has_value_(
false )
1478 contained.construct_error( std::forward<Args>( args )... );
1481 template<
typename U,
typename... Args
1483 std::is_constructible<U, std::initializer_list<U>, Args&&...>::value
1486 nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
1487 : has_value_(
false )
1489 contained.construct_error( il, std::forward<Args>( args )... );
1497 if ( ! has_value() ) contained.destruct_error();
1506 expected & operator=( expected
const & other )
1508 expected( other ).swap( *
this );
1516 expected & operator=( expected && other ) noexcept
1518 std::is_nothrow_move_assignable<E>::value &&
1519 std::is_nothrow_move_constructible<E>::value )
1521 expected( std::move( other ) ).swap( *
this );
1533 void swap( expected & other ) noexcept
1536 std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value
1538 std::is_nothrow_move_constructible<E>::value && noexcept (
std::swap( std::declval<E&>(), std::declval<E&>() ) )
1544 if ( !
bool(*
this) && !
bool(other) ) {
swap( contained.error(), other.contained.error() ); }
1545 else if (
bool(*
this) && ! bool(other) ) { contained.construct_error( std::move( other.error() ) );
1546 swap( has_value_, other.has_value_ ); }
1547 else if ( !
bool(*
this) &&
bool(other) ) { other.swap( *
this ); }
1552 constexpr
explicit operator bool()
const noexcept
1557 constexpr
bool has_value()
const noexcept
1565 constexpr error_type
const & error()
const &
1567 return assert( ! has_value() ), contained.error();
1570 error_type & error() &
1572 return assert( ! has_value() ), contained.error();
1575 constexpr error_type
const && error()
const &&
1577 return assert( ! has_value() ), std::move( contained.error() );
1580 error_type && error() &&
1582 return assert( ! has_value() ), std::move( contained.error() );
1585 constexpr unexpected_type get_unexpected()
const 1587 return make_unexpected( contained.error() );
1590 template<
typename Ex >
1591 bool has_exception()
const 1593 return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value;
1619 detail::storage_t<void,E> contained;
1624 template<
typename T,
typename E >
1625 constexpr
bool operator==( expected<T,E>
const & x, expected<T,E>
const & y )
1627 return bool(x) != bool(y) ?
false : bool(x) ==
false ?
true : *x == *y;
1630 template<
typename T,
typename E >
1631 constexpr
bool operator!=( expected<T,E>
const & x, expected<T,E>
const & y )
1636 template<
typename T,
typename E >
1637 constexpr
bool operator<( expected<T,E>
const & x, expected<T,E>
const & y )
1639 return (!y) ?
false : (!x) ?
true : *x < *y;
1642 template<
typename T,
typename E >
1643 constexpr
bool operator>( expected<T,E>
const & x, expected<T,E>
const & y )
1648 template<
typename T,
typename E >
1649 constexpr
bool operator<=( expected<T,E>
const & x, expected<T,E>
const & y )
1654 template<
typename T,
typename E >
1655 constexpr
bool operator>=( expected<T,E>
const & x, expected<T,E>
const & y )
1662 template<
typename T,
typename E >
1663 constexpr
bool operator==( expected<T,E>
const & x, unexpected_type<E>
const & u )
1665 return (!x) ? x.get_unexpected() == u :
false;
1668 template<
typename T,
typename E >
1669 constexpr
bool operator==( unexpected_type<E>
const & u, expected<T,E>
const & x )
1674 template<
typename T,
typename E >
1675 constexpr
bool operator!=( expected<T,E>
const & x, unexpected_type<E>
const & u )
1677 return ! ( x == u );
1680 template<
typename T,
typename E >
1681 constexpr
bool operator!=( unexpected_type<E>
const & u, expected<T,E>
const & x )
1683 return ! ( x == u );
1686 template<
typename T,
typename E >
1687 constexpr
bool operator<( expected<T,E>
const & x, unexpected_type<E>
const & u )
1689 return (!x) ? ( x.get_unexpected() < u ) :
false;
1692 #if nsel_P0323R <= 2 1694 template<
typename T,
typename E >
1695 constexpr
bool operator<( unexpected_type<E>
const & u, expected<T,E>
const & x )
1697 return (!x) ? ( u < x.get_unexpected() ) :
true ;
1700 template<
typename T,
typename E >
1701 constexpr
bool operator>( expected<T,E>
const & x, unexpected_type<E>
const & u )
1706 template<
typename T,
typename E >
1707 constexpr
bool operator>( unexpected_type<E>
const & u, expected<T,E>
const & x )
1712 template<
typename T,
typename E >
1713 constexpr
bool operator<=( expected<T,E>
const & x, unexpected_type<E>
const & u )
1718 template<
typename T,
typename E >
1719 constexpr
bool operator<=( unexpected_type<E>
const & u, expected<T,E>
const & x)
1724 template<
typename T,
typename E >
1725 constexpr
bool operator>=( expected<T,E>
const & x, unexpected_type<E>
const & u )
1730 template<
typename T,
typename E >
1731 constexpr
bool operator>=( unexpected_type<E>
const & u, expected<T,E>
const & x )
1736 #endif // nsel_P0323R 1740 template<
typename T,
typename E >
1741 constexpr
bool operator==( expected<T,E>
const & x, T
const & v )
1743 return bool(x) ? *x == v :
false;
1746 template<
typename T,
typename E >
1747 constexpr
bool operator==(T
const & v, expected<T,E>
const & x )
1749 return bool(x) ? v == *x :
false;
1752 template<
typename T,
typename E >
1753 constexpr
bool operator!=( expected<T,E>
const & x, T
const & v )
1755 return bool(x) ? *x != v :
true;
1758 template<
typename T,
typename E >
1759 constexpr
bool operator!=( T
const & v, expected<T,E>
const & x )
1761 return bool(x) ? v != *x :
true;
1764 template<
typename T,
typename E >
1765 constexpr
bool operator<( expected<T,E>
const & x, T
const & v )
1767 return bool(x) ? *x < v :
true;
1770 template<
typename T,
typename E >
1771 constexpr
bool operator<( T const & v, expected<T,E>
const & x )
1773 return bool(x) ? v < *x :
false;
1776 template<
typename T,
typename E >
1777 constexpr
bool operator>( T
const & v, expected<T,E>
const & x )
1779 return bool(x) ? *x < v :
false;
1782 template<
typename T,
typename E >
1783 constexpr
bool operator>( expected<T,E>
const & x, T
const & v )
1785 return bool(x) ? v < *x :
false;
1788 template<
typename T,
typename E >
1789 constexpr
bool operator<=( T const & v, expected<T,E>
const & x )
1791 return bool(x) ? ! ( *x < v ) :
false;
1794 template<
typename T,
typename E >
1795 constexpr
bool operator<=( expected<T,E>
const & x, T
const & v )
1797 return bool(x) ? ! ( v < *x ) :
true;
1800 template<
typename T,
typename E >
1801 constexpr
bool operator>=( expected<T,E>
const & x, T
const & v )
1803 return bool(x) ? ! ( *x < v ) :
false;
1806 template<
typename T,
typename E >
1807 constexpr
bool operator>=( T
const & v, expected<T,E>
const & x )
1809 return bool(x) ? ! ( v < *x ) :
true;
1814 template<
typename T,
typename E >
1815 void swap( expected<T,E> & x, expected<T,E> & y ) noexcept ( noexcept ( x.swap(y) ) )
1820 #if nsel_P0323R <= 3 1822 template<
typename T >
1823 constexpr
auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
1825 return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
1830 auto inline make_expected() -> expected<void>
1835 template<
typename T >
1836 constexpr
auto make_expected_from_current_exception() -> expected<T>
1838 return expected<T>( make_unexpected_from_current_exception() );
1841 template<
typename T >
1842 auto make_expected_from_exception( std::exception_ptr v ) -> expected<T>
1844 return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) );
1847 template<
typename T,
typename E >
1848 constexpr
auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
1850 return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
1853 template<
typename F >
1855 auto make_expected_from_call( F f,
1856 nsel_REQUIRES_A( ! std::is_same<
typename std::result_of<F()>::type,
void>::value )
1857 ) -> expected< typename std::result_of<F()>::type >
1861 return make_expected( f() );
1865 return make_unexpected_from_current_exception();
1869 template<
typename F >
1871 auto make_expected_from_call( F f,
1872 nsel_REQUIRES_A( std::is_same<
typename std::result_of<F()>::type,
void>::value )
1878 return make_expected();
1882 return make_unexpected_from_current_exception();
1886 #endif // nsel_P0323R 1890 using namespace expected_lite;
1901 template<
typename T,
typename E >
1909 return arg ? std::hash<T>{}(*arg) :
result_type{};
1914 template<
typename T,
typename E >
1922 return arg ? std::hash<T>{}(*arg) :
result_type{};
1931 template<
typename E >
1942 #if nsel_CPP17_OR_GREATER && nsel_COMPILER_MSVC_VERSION > 141 1943 template<
typename E >
1944 using unexpected = unexpected_type<E>;
1949 #undef nsel_REQUIRES 1950 #undef nsel_REQUIRES_0 1951 #undef nsel_REQUIRES_T 1955 #endif // nsel_USES_STD_EXPECTED 1957 #endif // NONSTD_EXPECTED_LITE_HPP
nonstd::expected< T &, E > argument_type
nonstd::expected< T, E > argument_type
void swap(linb::any &lhs, linb::any &rhs) noexcept
in_place_t in_place(detail::in_place_index_tag< K >=detail::in_place_index_tag< K >())
#define nsel_REQUIRES_0(...)
#define nsel_DISABLE_MSVC_WARNINGS(codes)
#define nonstd_lite_in_place(T)
in_place_t in_place_index(detail::in_place_index_tag< K >=detail::in_place_index_tag< K >())
typename hash< T >::result_type result_type
#define nsel_REQUIRES_T(...)
#define nsel_RESTORE_WARNINGS()
constexpr result_type operator()(argument_type const &arg) const
in_place_t in_place_type(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())
#define nsel_CPP17_OR_GREATER
constexpr result_type operator()(argument_type const &arg) const
#define nonstd_lite_in_place_t(T)
#define nsel_REQUIRES_A(...)
typename hash< T >::result_type result_type
in_place_t in_place(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())