1 // This version targets C++11 and later.
3 // Copyright (C) 2016-2020 Martin Moene.
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 // expected lite is based on:
9 // A proposal to add a utility class to represent expected monad
10 // by Vicente J. Botet Escriba and Pierre Talbot. http:://wg21.link/p0323
12 #ifndef NONSTD_EXPECTED_LITE_HPP
13 #define NONSTD_EXPECTED_LITE_HPP
15 #define expected_lite_MAJOR 0
16 #define expected_lite_MINOR 8
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
24 // expected-lite configuration:
26 #define nsel_EXPECTED_DEFAULT 0
27 #define nsel_EXPECTED_NONSTD 1
28 #define nsel_EXPECTED_STD 2
30 // tweak header support:
33 # if __has_include(<nonstd/expected.tweak.hpp>)
34 # include <nonstd/expected.tweak.hpp>
36 #define expected_HAVE_TWEAK_HEADER 1
38 #define expected_HAVE_TWEAK_HEADER 0
39 //# pragma message("expected.hpp: Note: Tweak header not supported.")
42 // expected selection and configuration:
44 #if !defined( nsel_CONFIG_SELECT_EXPECTED )
45 # define nsel_CONFIG_SELECT_EXPECTED ( nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD )
48 // Proposal revisions:
51 // N4015 : -2 (2014-05-26)
52 // N4109 : -1 (2014-06-29)
53 // P0323R0: 0 (2016-05-28)
54 // P0323R1: 1 (2016-10-12)
56 // P0323R2: 2 (2017-06-15)
57 // P0323R3: 3 (2017-10-15)
58 // P0323R4: 4 (2017-11-26)
59 // P0323R5: 5 (2018-02-08)
60 // P0323R6: 6 (2018-04-02)
61 // P0323R7: 7 (2018-06-22) *
63 // expected-lite uses 2 and higher
66 # define nsel_P0323R 7
69 // Monadic operations proposal revisions:
71 // P2505R0: 0 (2021-12-12)
72 // P2505R1: 1 (2022-02-10)
73 // P2505R2: 2 (2022-04-15)
74 // P2505R3: 3 (2022-06-05)
75 // P2505R4: 4 (2022-06-15)
76 // P2505R5: 5 (2022-09-20) *
78 // expected-lite uses 5
81 # define nsel_P2505R 5
84 // Control presence of C++ exception handling (try and auto discover):
86 #ifndef nsel_CONFIG_NO_EXCEPTIONS
87 # if defined(_MSC_VER)
88 # include <cstddef> // for _HAS_EXCEPTIONS
90 # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
91 # define nsel_CONFIG_NO_EXCEPTIONS 0
93 # define nsel_CONFIG_NO_EXCEPTIONS 1
97 // at default use SEH with MSVC for no C++ exceptions
99 #ifndef nsel_CONFIG_NO_EXCEPTIONS_SEH
100 # define nsel_CONFIG_NO_EXCEPTIONS_SEH ( nsel_CONFIG_NO_EXCEPTIONS && _MSC_VER )
103 // C++ language version detection (C++23 is speculative):
104 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
106 #ifndef nsel_CPLUSPLUS
107 # if defined(_MSVC_LANG ) && !defined(__clang__)
108 # define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
110 # define nsel_CPLUSPLUS __cplusplus
114 #define nsel_CPP98_OR_GREATER ( nsel_CPLUSPLUS >= 199711L )
115 #define nsel_CPP11_OR_GREATER ( nsel_CPLUSPLUS >= 201103L )
116 #define nsel_CPP14_OR_GREATER ( nsel_CPLUSPLUS >= 201402L )
117 #define nsel_CPP17_OR_GREATER ( nsel_CPLUSPLUS >= 201703L )
118 #define nsel_CPP20_OR_GREATER ( nsel_CPLUSPLUS >= 202002L )
119 #define nsel_CPP23_OR_GREATER ( nsel_CPLUSPLUS >= 202300L )
121 // Use C++23 std::expected if available and requested:
123 #if nsel_CPP23_OR_GREATER && defined(__has_include )
124 # if __has_include( <expected> )
125 # define nsel_HAVE_STD_EXPECTED 1
127 # define nsel_HAVE_STD_EXPECTED 0
130 # define nsel_HAVE_STD_EXPECTED 0
133 #define nsel_USES_STD_EXPECTED ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) )
136 // in_place: code duplicated in any-lite, expected-lite, expected-lite, value-ptr-lite, variant-lite:
139 #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
140 #define nonstd_lite_HAVE_IN_PLACE_TYPES 1
142 // C++17 std::in_place in <utility>:
144 #if nsel_CPP17_OR_GREATER
151 using std::in_place_type
;
152 using std::in_place_index
;
153 using std::in_place_t
;
154 using std::in_place_type_t
;
155 using std::in_place_index_t
;
157 #define nonstd_lite_in_place_t( T) std::in_place_t
158 #define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
159 #define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
161 #define nonstd_lite_in_place( T) std::in_place_t{}
162 #define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
163 #define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
165 } // namespace nonstd
167 #else // nsel_CPP17_OR_GREATER
175 struct in_place_type_tag
{};
177 template< std::size_t K
>
178 struct in_place_index_tag
{};
180 } // namespace detail
182 struct in_place_t
{};
185 inline in_place_t
in_place( detail::in_place_type_tag
<T
> = detail::in_place_type_tag
<T
>() )
190 template< std::size_t K
>
191 inline in_place_t
in_place( detail::in_place_index_tag
<K
> = detail::in_place_index_tag
<K
>() )
197 inline in_place_t
in_place_type( detail::in_place_type_tag
<T
> = detail::in_place_type_tag
<T
>() )
202 template< std::size_t K
>
203 inline in_place_t
in_place_index( detail::in_place_index_tag
<K
> = detail::in_place_index_tag
<K
>() )
208 // mimic templated typedef:
210 #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
211 #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
212 #define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
214 #define nonstd_lite_in_place( T) nonstd::in_place_type<T>
215 #define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
216 #define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
218 } // namespace nonstd
220 #endif // nsel_CPP17_OR_GREATER
221 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
224 // Using std::expected:
227 #if nsel_USES_STD_EXPECTED
234 using std::unexpected
;
235 using std::bad_expected_access
;
236 using std::unexpect_t
;
239 //[[deprecated("replace unexpected_type with unexpected")]]
241 template< typename E
>
242 using unexpected_type
= unexpected
<E
>;
244 // Unconditionally provide make_unexpected():
246 template< typename E
>
247 constexpr auto make_unexpected( E
&& value
) -> unexpected
< typename
std::decay
<E
>::type
>
249 return unexpected
< typename
std::decay
<E
>::type
>( std::forward
<E
>(value
) );
251 } // namespace nonstd
253 #else // nsel_USES_STD_EXPECTED
257 #include <functional>
258 #include <initializer_list>
261 #include <system_error>
262 #include <type_traits>
265 // additional includes:
267 #if nsel_CONFIG_NO_EXCEPTIONS
268 # if nsel_CONFIG_NO_EXCEPTIONS_SEH
269 # include <windows.h> // for ExceptionCodes
271 // already included: <cassert>
274 # include <stdexcept>
277 // C++ feature usage:
279 #if nsel_CPP11_OR_GREATER
280 # define nsel_constexpr constexpr
282 # define nsel_constexpr /*constexpr*/
285 #if nsel_CPP14_OR_GREATER
286 # define nsel_constexpr14 constexpr
288 # define nsel_constexpr14 /*constexpr*/
291 #if nsel_CPP17_OR_GREATER
292 # define nsel_inline17 inline
294 # define nsel_inline17 /*inline*/
297 // Compiler versions:
299 // MSVC++ 6.0 _MSC_VER == 1200 nsel_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
300 // MSVC++ 7.0 _MSC_VER == 1300 nsel_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
301 // MSVC++ 7.1 _MSC_VER == 1310 nsel_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
302 // MSVC++ 8.0 _MSC_VER == 1400 nsel_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
303 // MSVC++ 9.0 _MSC_VER == 1500 nsel_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
304 // MSVC++ 10.0 _MSC_VER == 1600 nsel_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
305 // MSVC++ 11.0 _MSC_VER == 1700 nsel_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
306 // MSVC++ 12.0 _MSC_VER == 1800 nsel_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
307 // MSVC++ 14.0 _MSC_VER == 1900 nsel_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
308 // MSVC++ 14.1 _MSC_VER >= 1910 nsel_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
309 // MSVC++ 14.2 _MSC_VER >= 1920 nsel_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
311 #if defined(_MSC_VER) && !defined(__clang__)
312 # define nsel_COMPILER_MSVC_VER (_MSC_VER )
313 # define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) )
315 # define nsel_COMPILER_MSVC_VER 0
316 # define nsel_COMPILER_MSVC_VERSION 0
319 #define nsel_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
321 #if defined(__clang__)
322 # define nsel_COMPILER_CLANG_VERSION nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
324 # define nsel_COMPILER_CLANG_VERSION 0
327 #if defined(__GNUC__) && !defined(__clang__)
328 # define nsel_COMPILER_GNUC_VERSION nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
330 # define nsel_COMPILER_GNUC_VERSION 0
333 // half-open range [lo..hi):
334 //#define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
338 #define nsel_REQUIRES_0(...) \
339 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
341 #define nsel_REQUIRES_T(...) \
342 , typename std::enable_if< (__VA_ARGS__), int >::type = 0
344 #define nsel_REQUIRES_R(R, ...) \
345 typename std::enable_if< (__VA_ARGS__), R>::type
347 #define nsel_REQUIRES_A(...) \
348 , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
350 // Clang, GNUC, MSVC warning suppression macros:
353 # pragma clang diagnostic push
354 #elif defined __GNUC__
355 # pragma GCC diagnostic push
358 #if nsel_COMPILER_MSVC_VERSION >= 140
359 # define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(push) ) __pragma( warning(disable: codes) )
361 # define nsel_DISABLE_MSVC_WARNINGS(codes)
365 # define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
366 # define nsel_RESTORE_MSVC_WARNINGS()
367 #elif defined __GNUC__
368 # define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
369 # define nsel_RESTORE_MSVC_WARNINGS()
370 #elif nsel_COMPILER_MSVC_VERSION >= 140
371 # define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) )
372 # define nsel_RESTORE_MSVC_WARNINGS() nsel_RESTORE_WARNINGS()
374 # define nsel_RESTORE_WARNINGS()
375 # define nsel_RESTORE_MSVC_WARNINGS()
378 // Suppress the following MSVC (GSL) warnings:
379 // - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11)
381 nsel_DISABLE_MSVC_WARNINGS( 26409 )
383 // Presence of language and library features:
386 # define nsel_HAS_CPP0X _HAS_CPP0X
388 # define nsel_HAS_CPP0X 0
391 // Presence of language and library features:
393 #define nsel_CPP17_000 (nsel_CPP17_OR_GREATER)
395 // Presence of C++17 language features:
397 #define nsel_HAVE_DEPRECATED nsel_CPP17_000
399 // C++ feature usage:
401 #if nsel_HAVE_DEPRECATED
402 # define nsel_deprecated(msg) [[deprecated(msg)]]
404 # define nsel_deprecated(msg) /*[[deprecated]]*/
411 namespace nonstd
{ namespace expected_lite
{
413 // type traits C++17:
417 #if nsel_CPP17_OR_GREATER
419 using std::conjunction
;
420 using std::is_swappable
;
421 using std::is_nothrow_swappable
;
423 #else // nsel_CPP17_OR_GREATER
431 template< typename T
, typename
= decltype( swap( std::declval
<T
&>(), std::declval
<T
&>() ) ) >
432 static std::true_type
test( int /* unused */);
435 static std::false_type
test(...);
438 struct is_nothrow_swappable
440 // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
442 template< typename T
>
443 static constexpr bool satisfies()
445 return noexcept( swap( std::declval
<T
&>(), std::declval
<T
&>() ) );
448 template< typename T
>
449 static auto test( int ) -> std::integral_constant
<bool, satisfies
<T
>()>{}
452 static auto test(...) -> std::false_type
;
454 } // namespace detail
456 // is [nothrow] swappable:
458 template< typename T
>
459 struct is_swappable
: decltype( detail::is_swappable::test
<T
>(0) ){};
461 template< typename T
>
462 struct is_nothrow_swappable
: decltype( detail::is_nothrow_swappable::test
<T
>(0) ){};
466 template< typename
... > struct conjunction
: std::true_type
{};
467 template< typename B1
> struct conjunction
<B1
> : B1
{};
469 template< typename B1
, typename
... Bn
>
470 struct conjunction
<B1
, Bn
...> : std::conditional
<bool(B1::value
), conjunction
<Bn
...>, B1
>::type
{};
472 #endif // nsel_CPP17_OR_GREATER
476 // type traits C++20:
480 #if defined(__cpp_lib_remove_cvref)
482 using std::remove_cvref
;
486 template< typename T
>
489 typedef typename
std::remove_cv
< typename
std::remove_reference
<T
>::type
>::type type
;
496 // forward declaration:
498 template< typename T
, typename E
>
504 template< typename T
>
505 struct is_expected
: std::false_type
{};
507 template< typename T
, typename E
>
508 struct is_expected
< expected
< T
, E
> > : std::true_type
{};
509 #endif // nsel_P2505R >= 3
511 /// discriminated union to hold value or 'error'.
513 template< typename T
, typename E
>
514 class storage_t_noncopy_nonmove_impl
516 template< typename
, typename
> friend class nonstd::expected_lite::expected
;
519 using value_type
= T
;
520 using error_type
= E
;
522 // no-op construction
523 storage_t_noncopy_nonmove_impl() {}
524 ~storage_t_noncopy_nonmove_impl() {}
526 explicit storage_t_noncopy_nonmove_impl( bool has_value
)
527 : m_has_value( has_value
)
530 void construct_value()
532 new( &m_value
) value_type();
535 // void construct_value( value_type const & e )
537 // new( &m_value ) value_type( e );
540 // void construct_value( value_type && e )
542 // new( &m_value ) value_type( std::move( e ) );
545 template< class... Args
>
546 void emplace_value( Args
&&... args
)
548 new( &m_value
) value_type( std::forward
<Args
>(args
)...);
551 template< class U
, class... Args
>
552 void emplace_value( std::initializer_list
<U
> il
, Args
&&... args
)
554 new( &m_value
) value_type( il
, std::forward
<Args
>(args
)... );
557 void destruct_value()
559 m_value
.~value_type();
562 // void construct_error( error_type const & e )
564 // // new( &m_error ) error_type( e );
567 // void construct_error( error_type && e )
569 // // new( &m_error ) error_type( std::move( e ) );
572 template< class... Args
>
573 void emplace_error( Args
&&... args
)
575 new( &m_error
) error_type( std::forward
<Args
>(args
)...);
578 template< class U
, class... Args
>
579 void emplace_error( std::initializer_list
<U
> il
, Args
&&... args
)
581 new( &m_error
) error_type( il
, std::forward
<Args
>(args
)... );
584 void destruct_error()
586 m_error
.~error_type();
589 constexpr value_type
const & value() const &
594 value_type
& value() &
599 constexpr value_type
const && value() const &&
601 return std::move( m_value
);
604 nsel_constexpr14 value_type
&& value() &&
606 return std::move( m_value
);
609 value_type
const * value_ptr() const
614 value_type
* value_ptr()
619 error_type
const & error() const &
624 error_type
& error() &
629 constexpr error_type
const && error() const &&
631 return std::move( m_error
);
634 nsel_constexpr14 error_type
&& error() &&
636 return std::move( m_error
);
639 bool has_value() const
644 void set_has_value( bool v
)
656 bool m_has_value
= false;
659 template< typename T
, typename E
>
662 template< typename
, typename
> friend class nonstd::expected_lite::expected
;
665 using value_type
= T
;
666 using error_type
= E
;
668 // no-op construction
672 explicit storage_t_impl( bool has_value
)
673 : m_has_value( has_value
)
676 void construct_value()
678 new( &m_value
) value_type();
681 void construct_value( value_type
const & e
)
683 new( &m_value
) value_type( e
);
686 void construct_value( value_type
&& e
)
688 new( &m_value
) value_type( std::move( e
) );
691 template< class... Args
>
692 void emplace_value( Args
&&... args
)
694 new( &m_value
) value_type( std::forward
<Args
>(args
)...);
697 template< class U
, class... Args
>
698 void emplace_value( std::initializer_list
<U
> il
, Args
&&... args
)
700 new( &m_value
) value_type( il
, std::forward
<Args
>(args
)... );
703 void destruct_value()
705 m_value
.~value_type();
708 void construct_error( error_type
const & e
)
710 new( &m_error
) error_type( e
);
713 void construct_error( error_type
&& e
)
715 new( &m_error
) error_type( std::move( e
) );
718 template< class... Args
>
719 void emplace_error( Args
&&... args
)
721 new( &m_error
) error_type( std::forward
<Args
>(args
)...);
724 template< class U
, class... Args
>
725 void emplace_error( std::initializer_list
<U
> il
, Args
&&... args
)
727 new( &m_error
) error_type( il
, std::forward
<Args
>(args
)... );
730 void destruct_error()
732 m_error
.~error_type();
735 constexpr value_type
const & value() const &
740 value_type
& value() &
745 constexpr value_type
const && value() const &&
747 return std::move( m_value
);
750 nsel_constexpr14 value_type
&& value() &&
752 return std::move( m_value
);
755 value_type
const * value_ptr() const
760 value_type
* value_ptr()
765 error_type
const & error() const &
770 error_type
& error() &
775 constexpr error_type
const && error() const &&
777 return std::move( m_error
);
780 nsel_constexpr14 error_type
&& error() &&
782 return std::move( m_error
);
785 bool has_value() const
790 void set_has_value( bool v
)
802 bool m_has_value
= false;
805 /// discriminated union to hold only 'error'.
807 template< typename E
>
808 struct storage_t_impl
<void, E
>
810 template< typename
, typename
> friend class nonstd::expected_lite::expected
;
813 using value_type
= void;
814 using error_type
= E
;
816 // no-op construction
820 explicit storage_t_impl( bool has_value
)
821 : m_has_value( has_value
)
824 void construct_error( error_type
const & e
)
826 new( &m_error
) error_type( e
);
829 void construct_error( error_type
&& e
)
831 new( &m_error
) error_type( std::move( e
) );
834 template< class... Args
>
835 void emplace_error( Args
&&... args
)
837 new( &m_error
) error_type( std::forward
<Args
>(args
)...);
840 template< class U
, class... Args
>
841 void emplace_error( std::initializer_list
<U
> il
, Args
&&... args
)
843 new( &m_error
) error_type( il
, std::forward
<Args
>(args
)... );
846 void destruct_error()
848 m_error
.~error_type();
851 error_type
const & error() const &
856 error_type
& error() &
861 constexpr error_type
const && error() const &&
863 return std::move( m_error
);
866 nsel_constexpr14 error_type
&& error() &&
868 return std::move( m_error
);
871 bool has_value() const
876 void set_has_value( bool v
)
888 bool m_has_value
= false;
891 template< typename T
, typename E
, bool isConstructable
, bool isMoveable
>
897 template< typename T
, typename E
>
898 class storage_t
<T
, E
, false, false> : public storage_t_noncopy_nonmove_impl
<T
, E
>
901 storage_t() = default;
902 ~storage_t() = default;
904 explicit storage_t( bool has_value
)
905 : storage_t_noncopy_nonmove_impl
<T
, E
>( has_value
)
908 storage_t( storage_t
const & other
) = delete;
909 storage_t( storage_t
&& other
) = delete;
913 template< typename T
, typename E
>
914 class storage_t
<T
, E
, true, true> : public storage_t_impl
<T
, E
>
917 storage_t() = default;
918 ~storage_t() = default;
920 explicit storage_t( bool has_value
)
921 : storage_t_impl
<T
, E
>( has_value
)
924 storage_t( storage_t
const & other
)
925 : storage_t_impl
<T
, E
>( other
.has_value() )
927 if ( this->has_value() ) this->construct_value( other
.value() );
928 else this->construct_error( other
.error() );
931 storage_t(storage_t
&& other
)
932 : storage_t_impl
<T
, E
>( other
.has_value() )
934 if ( this->has_value() ) this->construct_value( std::move( other
.value() ) );
935 else this->construct_error( std::move( other
.error() ) );
939 template< typename E
>
940 class storage_t
<void, E
, true, true> : public storage_t_impl
<void, E
>
943 storage_t() = default;
944 ~storage_t() = default;
946 explicit storage_t( bool has_value
)
947 : storage_t_impl
<void, E
>( has_value
)
950 storage_t( storage_t
const & other
)
951 : storage_t_impl
<void, E
>( other
.has_value() )
953 if ( this->has_value() ) ;
954 else this->construct_error( other
.error() );
957 storage_t(storage_t
&& other
)
958 : storage_t_impl
<void, E
>( other
.has_value() )
960 if ( this->has_value() ) ;
961 else this->construct_error( std::move( other
.error() ) );
965 template< typename T
, typename E
>
966 class storage_t
<T
, E
, true, false> : public storage_t_impl
<T
, E
>
969 storage_t() = default;
970 ~storage_t() = default;
972 explicit storage_t( bool has_value
)
973 : storage_t_impl
<T
, E
>( has_value
)
976 storage_t( storage_t
const & other
)
977 : storage_t_impl
<T
, E
>(other
.has_value())
979 if ( this->has_value() ) this->construct_value( other
.value() );
980 else this->construct_error( other
.error() );
983 storage_t( storage_t
&& other
) = delete;
986 template< typename E
>
987 class storage_t
<void, E
, true, false> : public storage_t_impl
<void, E
>
990 storage_t() = default;
991 ~storage_t() = default;
993 explicit storage_t( bool has_value
)
994 : storage_t_impl
<void, E
>( has_value
)
997 storage_t( storage_t
const & other
)
998 : storage_t_impl
<void, E
>(other
.has_value())
1000 if ( this->has_value() ) ;
1001 else this->construct_error( other
.error() );
1004 storage_t( storage_t
&& other
) = delete;
1007 template< typename T
, typename E
>
1008 class storage_t
<T
, E
, false, true> : public storage_t_impl
<T
, E
>
1011 storage_t() = default;
1012 ~storage_t() = default;
1014 explicit storage_t( bool has_value
)
1015 : storage_t_impl
<T
, E
>( has_value
)
1018 storage_t( storage_t
const & other
) = delete;
1020 storage_t( storage_t
&& other
)
1021 : storage_t_impl
<T
, E
>( other
.has_value() )
1023 if ( this->has_value() ) this->construct_value( std::move( other
.value() ) );
1024 else this->construct_error( std::move( other
.error() ) );
1028 template< typename E
>
1029 class storage_t
<void, E
, false, true> : public storage_t_impl
<void, E
>
1032 storage_t() = default;
1033 ~storage_t() = default;
1035 explicit storage_t( bool has_value
)
1036 : storage_t_impl
<void, E
>( has_value
)
1039 storage_t( storage_t
const & other
) = delete;
1041 storage_t( storage_t
&& other
)
1042 : storage_t_impl
<void, E
>( other
.has_value() )
1044 if ( this->has_value() ) ;
1045 else this->construct_error( std::move( other
.error() ) );
1049 #if nsel_P2505R >= 3
1050 // C++11 invoke implementation
1051 template< typename
>
1052 struct is_reference_wrapper
: std::false_type
{};
1053 template< typename T
>
1054 struct is_reference_wrapper
< std::reference_wrapper
< T
> > : std::true_type
{};
1056 template< typename FnT
, typename ClassT
, typename ObjectT
, typename
... Args
1058 std::is_function
<FnT
>::value
1059 && ( std::is_same
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
1060 || std::is_base_of
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
)
1063 nsel_constexpr
auto invoke_member_function_impl( FnT
ClassT::* memfnptr
, ObjectT
&& obj
, Args
&& ... args
)
1064 noexcept( noexcept( (std::forward
< ObjectT
>( obj
).*memfnptr
)( std::forward
< Args
>( args
)... ) ) )
1065 -> decltype( (std::forward
< ObjectT
>( obj
).*memfnptr
)( std::forward
< Args
>( args
)...) )
1067 return (std::forward
< ObjectT
>( obj
).*memfnptr
)( std::forward
< Args
>( args
)... );
1070 template< typename FnT
, typename ClassT
, typename ObjectT
, typename
... Args
1072 std::is_function
<FnT
>::value
1073 && is_reference_wrapper
< typename
std20::remove_cvref
< ObjectT
>::type
>::value
1076 nsel_constexpr
auto invoke_member_function_impl( FnT
ClassT::* memfnptr
, ObjectT
&& obj
, Args
&& ... args
)
1077 noexcept( noexcept( (obj
.get().*memfnptr
)( std::forward
< Args
>( args
) ... ) ) )
1078 -> decltype( (obj
.get().*memfnptr
)( std::forward
< Args
>( args
) ... ) )
1080 return (obj
.get().*memfnptr
)( std::forward
< Args
>( args
) ... );
1083 template< typename FnT
, typename ClassT
, typename ObjectT
, typename
... Args
1085 std::is_function
<FnT
>::value
1086 && !std::is_same
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
1087 && !std::is_base_of
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
1088 && !is_reference_wrapper
< typename
std20::remove_cvref
< ObjectT
>::type
>::value
1091 nsel_constexpr
auto invoke_member_function_impl( FnT
ClassT::* memfnptr
, ObjectT
&& obj
, Args
&& ... args
)
1092 noexcept( noexcept( ((*std::forward
< ObjectT
>( obj
)).*memfnptr
)( std::forward
< Args
>( args
) ... ) ) )
1093 -> decltype( ((*std::forward
< ObjectT
>( obj
)).*memfnptr
)( std::forward
< Args
>( args
) ... ) )
1095 return ((*std::forward
<ObjectT
>(obj
)).*memfnptr
)( std::forward
< Args
>( args
) ... );
1098 template< typename MemberT
, typename ClassT
, typename ObjectT
1100 std::is_same
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
1101 || std::is_base_of
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
1104 nsel_constexpr
auto invoke_member_object_impl( MemberT
ClassT::* memobjptr
, ObjectT
&& obj
)
1105 noexcept( noexcept( std::forward
< ObjectT
>( obj
).*memobjptr
) )
1106 -> decltype( std::forward
< ObjectT
>( obj
).*memobjptr
)
1108 return std::forward
< ObjectT
>( obj
).*memobjptr
;
1111 template< typename MemberT
, typename ClassT
, typename ObjectT
1113 is_reference_wrapper
< typename
std20::remove_cvref
< ObjectT
>::type
>::value
1116 nsel_constexpr
auto invoke_member_object_impl( MemberT
ClassT::* memobjptr
, ObjectT
&& obj
)
1117 noexcept( noexcept( obj
.get().*memobjptr
) )
1118 -> decltype( obj
.get().*memobjptr
)
1120 return obj
.get().*memobjptr
;
1123 template< typename MemberT
, typename ClassT
, typename ObjectT
1125 !std::is_same
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
1126 && !std::is_base_of
< ClassT
, typename
std20::remove_cvref
< ObjectT
>::type
>::value
1127 && !is_reference_wrapper
< typename
std20::remove_cvref
< ObjectT
>::type
>::value
1130 nsel_constexpr
auto invoke_member_object_impl( MemberT
ClassT::* memobjptr
, ObjectT
&& obj
)
1131 noexcept( noexcept( (*std::forward
< ObjectT
>( obj
)).*memobjptr
) )
1132 -> decltype( (*std::forward
< ObjectT
>( obj
)).*memobjptr
)
1134 return (*std::forward
< ObjectT
>( obj
)).*memobjptr
;
1137 template< typename F
, typename
... Args
1139 std::is_member_function_pointer
< typename
std20::remove_cvref
< F
>::type
>::value
1142 nsel_constexpr
auto invoke( F
&& f
, Args
&& ... args
)
1143 noexcept( noexcept( invoke_member_function_impl( std::forward
< F
>( f
), std::forward
< Args
>( args
) ... ) ) )
1144 -> decltype( invoke_member_function_impl( std::forward
< F
>( f
), std::forward
< Args
>( args
) ... ) )
1146 return invoke_member_function_impl( std::forward
< F
>( f
), std::forward
< Args
>( args
) ... );
1149 template< typename F
, typename
... Args
1151 std::is_member_object_pointer
< typename
std20::remove_cvref
< F
>::type
>::value
1154 nsel_constexpr
auto invoke( F
&& f
, Args
&& ... args
)
1155 noexcept( noexcept( invoke_member_object_impl( std::forward
< F
>( f
), std::forward
< Args
>( args
) ... ) ) )
1156 -> decltype( invoke_member_object_impl( std::forward
< F
>( f
), std::forward
< Args
>( args
) ... ) )
1158 return invoke_member_object_impl( std::forward
< F
>( f
), std::forward
< Args
>( args
) ... );
1161 template< typename F
, typename
... Args
1163 !std::is_member_function_pointer
< typename
std20::remove_cvref
< F
>::type
>::value
1164 && !std::is_member_object_pointer
< typename
std20::remove_cvref
< F
>::type
>::value
1167 nsel_constexpr
auto invoke( F
&& f
, Args
&& ... args
)
1168 noexcept( noexcept( std::forward
< F
>( f
)( std::forward
< Args
>( args
) ... ) ) )
1169 -> decltype( std::forward
< F
>( f
)( std::forward
< Args
>( args
) ... ) )
1171 return std::forward
< F
>( f
)( std::forward
< Args
>( args
) ... );
1174 template< typename F
, typename
... Args
>
1175 using invoke_result_nocvref_t
= typename
std20::remove_cvref
< decltype( invoke( std::declval
< F
>(), std::declval
< Args
>()... ) ) >::type
;
1177 #if nsel_P2505R >= 5
1178 template< typename F
, typename
... Args
>
1179 using transform_invoke_result_t
= typename
std::remove_cv
< decltype( invoke( std::declval
< F
>(), std::declval
< Args
>()... ) ) >::type
;
1181 template< typename F
, typename
... Args
>
1182 using transform_invoke_result_t
= invoke_result_nocvref_t
1183 #endif // nsel_P2505R >= 5
1185 template< typename T
>
1186 struct valid_expected_value_type
: std::integral_constant
< bool, std::is_destructible
< T
>::value
&& !std::is_reference
< T
>::value
&& !std::is_array
< T
>::value
> {};
1188 #endif // nsel_P2505R >= 3
1189 } // namespace detail
1191 /// x.x.5 Unexpected object type; unexpected_type; C++17 and later can also use aliased type unexpected.
1193 #if nsel_P0323R <= 2
1194 template< typename E
= std::exception_ptr
>
1195 class unexpected_type
1197 template< typename E
>
1198 class unexpected_type
1199 #endif // nsel_P0323R
1202 using error_type
= E
;
1204 // x.x.5.2.1 Constructors
1206 // unexpected_type() = delete;
1208 constexpr unexpected_type( unexpected_type
const & ) = default;
1209 constexpr unexpected_type( unexpected_type
&& ) = default;
1211 template< typename
... Args
1213 std::is_constructible
<E
, Args
&&...>::value
1216 constexpr explicit unexpected_type( nonstd_lite_in_place_t(E
), Args
&&... args
)
1217 : m_error( std::forward
<Args
>( args
)...)
1220 template< typename U
, typename
... Args
1222 std::is_constructible
<E
, std::initializer_list
<U
>, Args
&&...>::value
1225 constexpr explicit unexpected_type( nonstd_lite_in_place_t(E
), std::initializer_list
<U
> il
, Args
&&... args
)
1226 : m_error( il
, std::forward
<Args
>( args
)...)
1229 template< typename E2
1231 std::is_constructible
<E
,E2
>::value
1232 && !std::is_same
< typename
std20::remove_cvref
<E2
>::type
, nonstd_lite_in_place_t(E2
) >::value
1233 && !std::is_same
< typename
std20::remove_cvref
<E2
>::type
, unexpected_type
>::value
1236 constexpr explicit unexpected_type( E2
&& error
)
1237 : m_error( std::forward
<E2
>( error
) )
1240 template< typename E2
1242 std::is_constructible
< E
, E2
>::value
1243 && !std::is_constructible
<E
, unexpected_type
<E2
> & >::value
1244 && !std::is_constructible
<E
, unexpected_type
<E2
> >::value
1245 && !std::is_constructible
<E
, unexpected_type
<E2
> const & >::value
1246 && !std::is_constructible
<E
, unexpected_type
<E2
> const >::value
1247 && !std::is_convertible
< unexpected_type
<E2
> &, E
>::value
1248 && !std::is_convertible
< unexpected_type
<E2
> , E
>::value
1249 && !std::is_convertible
< unexpected_type
<E2
> const &, E
>::value
1250 && !std::is_convertible
< unexpected_type
<E2
> const , E
>::value
1251 && !std::is_convertible
< E2
const &, E
>::value
/*=> explicit */
1254 constexpr explicit unexpected_type( unexpected_type
<E2
> const & error
)
1255 : m_error( E
{ error
.error() } )
1258 template< typename E2
1260 std::is_constructible
< E
, E2
>::value
1261 && !std::is_constructible
<E
, unexpected_type
<E2
> & >::value
1262 && !std::is_constructible
<E
, unexpected_type
<E2
> >::value
1263 && !std::is_constructible
<E
, unexpected_type
<E2
> const & >::value
1264 && !std::is_constructible
<E
, unexpected_type
<E2
> const >::value
1265 && !std::is_convertible
< unexpected_type
<E2
> &, E
>::value
1266 && !std::is_convertible
< unexpected_type
<E2
> , E
>::value
1267 && !std::is_convertible
< unexpected_type
<E2
> const &, E
>::value
1268 && !std::is_convertible
< unexpected_type
<E2
> const , E
>::value
1269 && std::is_convertible
< E2
const &, E
>::value
/*=> explicit */
1272 constexpr /*non-explicit*/ unexpected_type( unexpected_type
<E2
> const & error
)
1273 : m_error( error
.error() )
1276 template< typename E2
1278 std::is_constructible
< E
, E2
>::value
1279 && !std::is_constructible
<E
, unexpected_type
<E2
> & >::value
1280 && !std::is_constructible
<E
, unexpected_type
<E2
> >::value
1281 && !std::is_constructible
<E
, unexpected_type
<E2
> const & >::value
1282 && !std::is_constructible
<E
, unexpected_type
<E2
> const >::value
1283 && !std::is_convertible
< unexpected_type
<E2
> &, E
>::value
1284 && !std::is_convertible
< unexpected_type
<E2
> , E
>::value
1285 && !std::is_convertible
< unexpected_type
<E2
> const &, E
>::value
1286 && !std::is_convertible
< unexpected_type
<E2
> const , E
>::value
1287 && !std::is_convertible
< E2
const &, E
>::value
/*=> explicit */
1290 constexpr explicit unexpected_type( unexpected_type
<E2
> && error
)
1291 : m_error( E
{ std::move( error
.error() ) } )
1294 template< typename E2
1296 std::is_constructible
< E
, E2
>::value
1297 && !std::is_constructible
<E
, unexpected_type
<E2
> & >::value
1298 && !std::is_constructible
<E
, unexpected_type
<E2
> >::value
1299 && !std::is_constructible
<E
, unexpected_type
<E2
> const & >::value
1300 && !std::is_constructible
<E
, unexpected_type
<E2
> const >::value
1301 && !std::is_convertible
< unexpected_type
<E2
> &, E
>::value
1302 && !std::is_convertible
< unexpected_type
<E2
> , E
>::value
1303 && !std::is_convertible
< unexpected_type
<E2
> const &, E
>::value
1304 && !std::is_convertible
< unexpected_type
<E2
> const , E
>::value
1305 && std::is_convertible
< E2
const &, E
>::value
/*=> non-explicit */
1308 constexpr /*non-explicit*/ unexpected_type( unexpected_type
<E2
> && error
)
1309 : m_error( std::move( error
.error() ) )
1312 // x.x.5.2.2 Assignment
1314 nsel_constexpr14 unexpected_type
& operator=( unexpected_type
const & ) = default;
1315 nsel_constexpr14 unexpected_type
& operator=( unexpected_type
&& ) = default;
1317 template< typename E2
= E
>
1318 nsel_constexpr14 unexpected_type
& operator=( unexpected_type
<E2
> const & other
)
1320 unexpected_type
{ other
.error() }.swap( *this );
1324 template< typename E2
= E
>
1325 nsel_constexpr14 unexpected_type
& operator=( unexpected_type
<E2
> && other
)
1327 unexpected_type
{ std::move( other
.error() ) }.swap( *this );
1331 // x.x.5.2.3 Observers
1333 nsel_constexpr14 E
& error() & noexcept
1338 constexpr E
const & error() const & noexcept
1343 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1345 nsel_constexpr14 E
&& error() && noexcept
1347 return std::move( m_error
);
1350 constexpr E
const && error() const && noexcept
1352 return std::move( m_error
);
1357 // x.x.5.2.3 Observers - deprecated
1359 nsel_deprecated("replace value() with error()")
1361 nsel_constexpr14 E
& value() & noexcept
1366 nsel_deprecated("replace value() with error()")
1368 constexpr E
const & value() const & noexcept
1373 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1375 nsel_deprecated("replace value() with error()")
1377 nsel_constexpr14 E
&& value() && noexcept
1379 return std::move( m_error
);
1382 nsel_deprecated("replace value() with error()")
1384 constexpr E
const && value() const && noexcept
1386 return std::move( m_error
);
1393 template< typename U
=E
>
1394 nsel_REQUIRES_R( void,
1395 std17::is_swappable
<U
>::value
1397 swap( unexpected_type
& other
) noexcept (
1398 std17::is_nothrow_swappable
<U
>::value
1402 swap( m_error
, other
.m_error
);
1405 // TODO: ??? unexpected_type: in-class friend operator==, !=
1411 #if nsel_CPP17_OR_GREATER
1413 /// template deduction guide:
1415 template< typename E
>
1416 unexpected_type( E
) -> unexpected_type
< E
>;
1420 /// class unexpected_type, std::exception_ptr specialization (P0323R2)
1422 #if !nsel_CONFIG_NO_EXCEPTIONS
1423 #if nsel_P0323R <= 2
1425 // TODO: Should expected be specialized for particular E types such as exception_ptr and how?
1426 // See p0323r7 2.1. Ergonomics, http://wg21.link/p0323
1428 class unexpected_type
< std::exception_ptr
>
1431 using error_type
= std::exception_ptr
;
1433 unexpected_type() = delete;
1435 ~unexpected_type(){}
1437 explicit unexpected_type( std::exception_ptr
const & error
)
1441 explicit unexpected_type(std::exception_ptr
&& error
)
1442 : m_error( std::move( error
) )
1445 template< typename E
>
1446 explicit unexpected_type( E error
)
1447 : m_error( std::make_exception_ptr( error
) )
1450 std::exception_ptr
const & value() const
1455 std::exception_ptr
& value()
1461 std::exception_ptr m_error
;
1464 #endif // nsel_P0323R
1465 #endif // !nsel_CONFIG_NO_EXCEPTIONS
1467 /// x.x.4, Unexpected equality operators
1469 template< typename E1
, typename E2
>
1470 constexpr bool operator==( unexpected_type
<E1
> const & x
, unexpected_type
<E2
> const & y
)
1472 return x
.error() == y
.error();
1475 template< typename E1
, typename E2
>
1476 constexpr bool operator!=( unexpected_type
<E1
> const & x
, unexpected_type
<E2
> const & y
)
1478 return ! ( x
== y
);
1481 #if nsel_P0323R <= 2
1483 template< typename E
>
1484 constexpr bool operator<( unexpected_type
<E
> const & x
, unexpected_type
<E
> const & y
)
1486 return x
.error() < y
.error();
1489 template< typename E
>
1490 constexpr bool operator>( unexpected_type
<E
> const & x
, unexpected_type
<E
> const & y
)
1495 template< typename E
>
1496 constexpr bool operator<=( unexpected_type
<E
> const & x
, unexpected_type
<E
> const & y
)
1501 template< typename E
>
1502 constexpr bool operator>=( unexpected_type
<E
> const & x
, unexpected_type
<E
> const & y
)
1507 #endif // nsel_P0323R
1509 /// x.x.5 Specialized algorithms
1511 template< typename E
1513 std17::is_swappable
<E
>::value
1516 void swap( unexpected_type
<E
> & x
, unexpected_type
<E
> & y
) noexcept ( noexcept ( x
.swap(y
) ) )
1521 #if nsel_P0323R <= 2
1523 // unexpected: relational operators for std::exception_ptr:
1525 inline constexpr bool operator<( unexpected_type
<std::exception_ptr
> const & /*x*/, unexpected_type
<std::exception_ptr
> const & /*y*/ )
1530 inline constexpr bool operator>( unexpected_type
<std::exception_ptr
> const & /*x*/, unexpected_type
<std::exception_ptr
> const & /*y*/ )
1535 inline constexpr bool operator<=( unexpected_type
<std::exception_ptr
> const & x
, unexpected_type
<std::exception_ptr
> const & y
)
1540 inline constexpr bool operator>=( unexpected_type
<std::exception_ptr
> const & x
, unexpected_type
<std::exception_ptr
> const & y
)
1545 #endif // nsel_P0323R
1547 // unexpected: traits
1549 #if nsel_P0323R <= 3
1551 template< typename E
>
1552 struct is_unexpected
: std::false_type
{};
1554 template< typename E
>
1555 struct is_unexpected
< unexpected_type
<E
> > : std::true_type
{};
1557 #endif // nsel_P0323R
1559 // unexpected: factory
1561 // keep make_unexpected() removed in p0323r2 for pre-C++17:
1563 template< typename E
>
1564 nsel_constexpr14
auto
1565 make_unexpected( E
&& value
) -> unexpected_type
< typename
std::decay
<E
>::type
>
1567 return unexpected_type
< typename
std::decay
<E
>::type
>( std::forward
<E
>(value
) );
1570 #if nsel_P0323R <= 3
1572 /*nsel_constexpr14*/ auto inline
1573 make_unexpected_from_current_exception() -> unexpected_type
< std::exception_ptr
>
1575 return unexpected_type
< std::exception_ptr
>( std::current_exception() );
1578 #endif // nsel_P0323R
1580 /// x.x.6, x.x.7 expected access error
1582 template< typename E
>
1583 class bad_expected_access
;
1585 /// x.x.7 bad_expected_access<void>: expected access error
1588 class bad_expected_access
< void > : public std::exception
1591 explicit bad_expected_access()
1596 /// x.x.6 bad_expected_access: expected access error
1598 #if !nsel_CONFIG_NO_EXCEPTIONS
1600 template< typename E
>
1601 class bad_expected_access
: public bad_expected_access
< void >
1604 using error_type
= E
;
1606 explicit bad_expected_access( error_type error
)
1610 virtual char const * what() const noexcept override
1612 return "bad_expected_access";
1615 nsel_constexpr14 error_type
& error() &
1620 constexpr error_type
const & error() const &
1625 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1627 nsel_constexpr14 error_type
&& error() &&
1629 return std::move( m_error
);
1632 constexpr error_type
const && error() const &&
1634 return std::move( m_error
);
1643 #endif // nsel_CONFIG_NO_EXCEPTIONS
1645 /// x.x.8 unexpect tag, in_place_unexpected tag: construct an error
1647 struct unexpect_t
{};
1648 using in_place_unexpected_t
= unexpect_t
;
1650 nsel_inline17
constexpr unexpect_t unexpect
{};
1651 nsel_inline17
constexpr unexpect_t in_place_unexpected
{};
1653 /// class error_traits
1655 #if nsel_CONFIG_NO_EXCEPTIONS
1658 inline bool text( char const * /*text*/ ) { return true; }
1661 template< typename Error
>
1664 static void rethrow( Error
const & /*e*/ )
1666 #if nsel_CONFIG_NO_EXCEPTIONS_SEH
1667 RaiseException( EXCEPTION_ACCESS_VIOLATION
, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
1669 assert( false && detail::text("throw bad_expected_access<Error>{ e };") );
1675 struct error_traits
< std::exception_ptr
>
1677 static void rethrow( std::exception_ptr
const & /*e*/ )
1679 #if nsel_CONFIG_NO_EXCEPTIONS_SEH
1680 RaiseException( EXCEPTION_ACCESS_VIOLATION
, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
1682 assert( false && detail::text("throw bad_expected_access<std::exception_ptr>{ e };") );
1688 struct error_traits
< std::error_code
>
1690 static void rethrow( std::error_code
const & /*e*/ )
1692 #if nsel_CONFIG_NO_EXCEPTIONS_SEH
1693 RaiseException( EXCEPTION_ACCESS_VIOLATION
, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
1695 assert( false && detail::text("throw std::system_error( e );") );
1700 #else // nsel_CONFIG_NO_EXCEPTIONS
1702 template< typename Error
>
1705 static void rethrow( Error
const & e
)
1707 throw bad_expected_access
<Error
>{ e
};
1712 struct error_traits
< std::exception_ptr
>
1714 static void rethrow( std::exception_ptr
const & e
)
1716 std::rethrow_exception( e
);
1721 struct error_traits
< std::error_code
>
1723 static void rethrow( std::error_code
const & e
)
1725 throw std::system_error( e
);
1729 #endif // nsel_CONFIG_NO_EXCEPTIONS
1731 #if nsel_P2505R >= 3
1734 // from https://en.cppreference.com/w/cpp/utility/expected/unexpected:
1735 // "the type of the unexpected value. The type must not be an array type, a non-object type, a specialization of std::unexpected, or a cv-qualified type."
1736 template< typename T
>
1737 struct valid_unexpected_type
: std::integral_constant
< bool,
1738 std::is_same
< T
, typename
std20::remove_cvref
< T
>::type
>::value
1739 && std::is_object
< T
>::value
1740 && !std::is_array
< T
>::value
1743 template< typename T
>
1744 struct valid_unexpected_type
< unexpected_type
< T
> > : std::false_type
{};
1746 } // namespace detail
1747 #endif // nsel_P2505R >= 3
1749 } // namespace expected_lite
1751 // provide nonstd::unexpected_type:
1753 using expected_lite::unexpected_type
;
1755 namespace expected_lite
{
1759 #if nsel_P0323R <= 2
1760 template< typename T
, typename E
= std::exception_ptr
>
1763 template< typename T
, typename E
>
1765 #endif // nsel_P0323R
1768 template< typename
, typename
> friend class expected
;
1771 using value_type
= T
;
1772 using error_type
= E
;
1773 using unexpected_type
= nonstd::unexpected_type
<E
>;
1775 template< typename U
>
1778 using type
= expected
<U
, error_type
>;
1781 // x.x.4.1 constructors
1784 std::is_default_constructible
<T
>::value
1786 nsel_constexpr14
expected()
1789 contained
.construct_value();
1792 nsel_constexpr14
expected( expected
const & ) = default;
1793 nsel_constexpr14
expected( expected
&& ) = default;
1795 template< typename U
, typename G
1797 std::is_constructible
< T
, U
const &>::value
1798 && std::is_constructible
<E
, G
const &>::value
1799 && !std::is_constructible
<T
, expected
<U
, G
> & >::value
1800 && !std::is_constructible
<T
, expected
<U
, G
> && >::value
1801 && !std::is_constructible
<T
, expected
<U
, G
> const & >::value
1802 && !std::is_constructible
<T
, expected
<U
, G
> const && >::value
1803 && !std::is_convertible
< expected
<U
, G
> & , T
>::value
1804 && !std::is_convertible
< expected
<U
, G
> &&, T
>::value
1805 && !std::is_convertible
< expected
<U
, G
> const & , T
>::value
1806 && !std::is_convertible
< expected
<U
, G
> const &&, T
>::value
1807 && (!std::is_convertible
<U
const &, T
>::value
|| !std::is_convertible
<G
const &, E
>::value
) /*=> explicit */
1810 nsel_constexpr14
explicit expected( expected
<U
, G
> const & other
)
1811 : contained( other
.has_value() )
1813 if ( has_value() ) contained
.construct_value( T
{ other
.contained
.value() } );
1814 else contained
.construct_error( E
{ other
.contained
.error() } );
1817 template< typename U
, typename G
1819 std::is_constructible
< T
, U
const &>::value
1820 && std::is_constructible
<E
, G
const &>::value
1821 && !std::is_constructible
<T
, expected
<U
, G
> & >::value
1822 && !std::is_constructible
<T
, expected
<U
, G
> && >::value
1823 && !std::is_constructible
<T
, expected
<U
, G
> const & >::value
1824 && !std::is_constructible
<T
, expected
<U
, G
> const && >::value
1825 && !std::is_convertible
< expected
<U
, G
> & , T
>::value
1826 && !std::is_convertible
< expected
<U
, G
> &&, T
>::value
1827 && !std::is_convertible
< expected
<U
, G
> const &, T
>::value
1828 && !std::is_convertible
< expected
<U
, G
> const &&, T
>::value
1829 && !(!std::is_convertible
<U
const &, T
>::value
|| !std::is_convertible
<G
const &, E
>::value
) /*=> non-explicit */
1832 nsel_constexpr14
/*non-explicit*/ expected( expected
<U
, G
> const & other
)
1833 : contained( other
.has_value() )
1835 if ( has_value() ) contained
.construct_value( other
.contained
.value() );
1836 else contained
.construct_error( other
.contained
.error() );
1839 template< typename U
, typename G
1841 std::is_constructible
< T
, U
>::value
1842 && std::is_constructible
<E
, G
>::value
1843 && !std::is_constructible
<T
, expected
<U
, G
> & >::value
1844 && !std::is_constructible
<T
, expected
<U
, G
> && >::value
1845 && !std::is_constructible
<T
, expected
<U
, G
> const & >::value
1846 && !std::is_constructible
<T
, expected
<U
, G
> const && >::value
1847 && !std::is_convertible
< expected
<U
, G
> & , T
>::value
1848 && !std::is_convertible
< expected
<U
, G
> &&, T
>::value
1849 && !std::is_convertible
< expected
<U
, G
> const & , T
>::value
1850 && !std::is_convertible
< expected
<U
, G
> const &&, T
>::value
1851 && (!std::is_convertible
<U
, T
>::value
|| !std::is_convertible
<G
, E
>::value
) /*=> explicit */
1854 nsel_constexpr14
explicit expected( expected
<U
, G
> && other
)
1855 : contained( other
.has_value() )
1857 if ( has_value() ) contained
.construct_value( T
{ std::move( other
.contained
.value() ) } );
1858 else contained
.construct_error( E
{ std::move( other
.contained
.error() ) } );
1861 template< typename U
, typename G
1863 std::is_constructible
< T
, U
>::value
1864 && std::is_constructible
<E
, G
>::value
1865 && !std::is_constructible
<T
, expected
<U
, G
> & >::value
1866 && !std::is_constructible
<T
, expected
<U
, G
> && >::value
1867 && !std::is_constructible
<T
, expected
<U
, G
> const & >::value
1868 && !std::is_constructible
<T
, expected
<U
, G
> const && >::value
1869 && !std::is_convertible
< expected
<U
, G
> & , T
>::value
1870 && !std::is_convertible
< expected
<U
, G
> &&, T
>::value
1871 && !std::is_convertible
< expected
<U
, G
> const & , T
>::value
1872 && !std::is_convertible
< expected
<U
, G
> const &&, T
>::value
1873 && !(!std::is_convertible
<U
, T
>::value
|| !std::is_convertible
<G
, E
>::value
) /*=> non-explicit */
1876 nsel_constexpr14
/*non-explicit*/ expected( expected
<U
, G
> && other
)
1877 : contained( other
.has_value() )
1879 if ( has_value() ) contained
.construct_value( std::move( other
.contained
.value() ) );
1880 else contained
.construct_error( std::move( other
.contained
.error() ) );
1883 template< typename U
= T
1885 std::is_copy_constructible
<U
>::value
1888 nsel_constexpr14
expected( value_type
const & value
)
1891 contained
.construct_value( value
);
1894 template< typename U
= T
1896 std::is_constructible
<T
,U
&&>::value
1897 && !std::is_same
<typename
std20::remove_cvref
<U
>::type
, nonstd_lite_in_place_t(U
)>::value
1898 && !std::is_same
< expected
<T
,E
> , typename
std20::remove_cvref
<U
>::type
>::value
1899 && !std::is_same
<nonstd::unexpected_type
<E
>, typename
std20::remove_cvref
<U
>::type
>::value
1900 && !std::is_convertible
<U
&&,T
>::value
/*=> explicit */
1903 nsel_constexpr14
explicit expected( U
&& value
) noexcept
1905 std::is_nothrow_move_constructible
<U
>::value
&&
1906 std::is_nothrow_move_constructible
<E
>::value
1910 contained
.construct_value( T
{ std::forward
<U
>( value
) } );
1913 template< typename U
= T
1915 std::is_constructible
<T
,U
&&>::value
1916 && !std::is_same
<typename
std20::remove_cvref
<U
>::type
, nonstd_lite_in_place_t(U
)>::value
1917 && !std::is_same
< expected
<T
,E
> , typename
std20::remove_cvref
<U
>::type
>::value
1918 && !std::is_same
<nonstd::unexpected_type
<E
>, typename
std20::remove_cvref
<U
>::type
>::value
1919 && std::is_convertible
<U
&&,T
>::value
/*=> non-explicit */
1922 nsel_constexpr14
/*non-explicit*/ expected( U
&& value
) noexcept
1924 std::is_nothrow_move_constructible
<U
>::value
&&
1925 std::is_nothrow_move_constructible
<E
>::value
1929 contained
.construct_value( std::forward
<U
>( value
) );
1934 template< typename G
= E
1936 std::is_constructible
<E
, G
const & >::value
1937 && !std::is_convertible
< G
const &, E
>::value
/*=> explicit */
1940 nsel_constexpr14
explicit expected( nonstd::unexpected_type
<G
> const & error
)
1941 : contained( false )
1943 contained
.construct_error( E
{ error
.error() } );
1946 template< typename G
= E
1948 std::is_constructible
<E
, G
const & >::value
1949 && std::is_convertible
< G
const &, E
>::value
/*=> non-explicit */
1952 nsel_constexpr14
/*non-explicit*/ expected( nonstd::unexpected_type
<G
> const & error
)
1953 : contained( false )
1955 contained
.construct_error( error
.error() );
1958 template< typename G
= E
1960 std::is_constructible
<E
, G
&& >::value
1961 && !std::is_convertible
< G
&&, E
>::value
/*=> explicit */
1964 nsel_constexpr14
explicit expected( nonstd::unexpected_type
<G
> && error
)
1965 : contained( false )
1967 contained
.construct_error( E
{ std::move( error
.error() ) } );
1970 template< typename G
= E
1972 std::is_constructible
<E
, G
&& >::value
1973 && std::is_convertible
< G
&&, E
>::value
/*=> non-explicit */
1976 nsel_constexpr14
/*non-explicit*/ expected( nonstd::unexpected_type
<G
> && error
)
1977 : contained( false )
1979 contained
.construct_error( std::move( error
.error() ) );
1982 // in-place construction, value
1984 template< typename
... Args
1986 std::is_constructible
<T
, Args
&&...>::value
1989 nsel_constexpr14
explicit expected( nonstd_lite_in_place_t(T
), Args
&&... args
)
1992 contained
.emplace_value( std::forward
<Args
>( args
)... );
1995 template< typename U
, typename
... Args
1997 std::is_constructible
<T
, std::initializer_list
<U
>, Args
&&...>::value
2000 nsel_constexpr14
explicit expected( nonstd_lite_in_place_t(T
), std::initializer_list
<U
> il
, Args
&&... args
)
2003 contained
.emplace_value( il
, std::forward
<Args
>( args
)... );
2006 // in-place construction, error
2008 template< typename
... Args
2010 std::is_constructible
<E
, Args
&&...>::value
2013 nsel_constexpr14
explicit expected( unexpect_t
, Args
&&... args
)
2014 : contained( false )
2016 contained
.emplace_error( std::forward
<Args
>( args
)... );
2019 template< typename U
, typename
... Args
2021 std::is_constructible
<E
, std::initializer_list
<U
>, Args
&&...>::value
2024 nsel_constexpr14
explicit expected( unexpect_t
, std::initializer_list
<U
> il
, Args
&&... args
)
2025 : contained( false )
2027 contained
.emplace_error( il
, std::forward
<Args
>( args
)... );
2030 // x.x.4.2 destructor
2032 // TODO: ~expected: triviality
2033 // Effects: If T is not cv void and is_trivially_destructible_v<T> is false and bool(*this), calls val.~T(). If is_trivially_destructible_v<E> is false and !bool(*this), calls unexpect.~unexpected<E>().
2034 // Remarks: If either T is cv void or is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> is true, then this destructor shall be a trivial destructor.
2038 if ( has_value() ) contained
.destruct_value();
2039 else contained
.destruct_error();
2042 // x.x.4.3 assignment
2044 expected
& operator=( expected
const & other
)
2046 expected( other
).swap( *this );
2050 expected
& operator=( expected
&& other
) noexcept
2052 std::is_nothrow_move_constructible
< T
>::value
2053 && std::is_nothrow_move_assignable
< T
>::value
2054 && std::is_nothrow_move_constructible
<E
>::value
// added for missing
2055 && std::is_nothrow_move_assignable
< E
>::value
) // nothrow above
2057 expected( std::move( other
) ).swap( *this );
2061 template< typename U
2063 !std::is_same
<expected
<T
,E
>, typename
std20::remove_cvref
<U
>::type
>::value
2064 && std17::conjunction
<std::is_scalar
<T
>, std::is_same
<T
, std::decay
<U
>> >::value
2065 && std::is_constructible
<T
,U
>::value
2066 && std::is_assignable
< T
&,U
>::value
2067 && std::is_nothrow_move_constructible
<E
>::value
)
2069 expected
& operator=( U
&& value
)
2071 expected( std::forward
<U
>( value
) ).swap( *this );
2075 template< typename G
= E
2077 std::is_constructible
<E
, G
const&>::value
&&
2078 std::is_copy_constructible
<G
>::value
// TODO: std::is_nothrow_copy_constructible<G>
2079 && std::is_copy_assignable
<G
>::value
2082 expected
& operator=( nonstd::unexpected_type
<G
> const & error
)
2084 expected( unexpect
, error
.error() ).swap( *this );
2088 template< typename G
= E
2090 std::is_constructible
<E
, G
&&>::value
&&
2091 std::is_move_constructible
<G
>::value
// TODO: std::is_nothrow_move_constructible<G>
2092 && std::is_move_assignable
<G
>::value
2095 expected
& operator=( nonstd::unexpected_type
<G
> && error
)
2097 expected( unexpect
, std::move( error
.error() ) ).swap( *this );
2101 template< typename
... Args
2103 std::is_nothrow_constructible
<T
, Args
&&...>::value
2106 value_type
& emplace( Args
&&... args
)
2108 expected( nonstd_lite_in_place(T
), std::forward
<Args
>(args
)... ).swap( *this );
2112 template< typename U
, typename
... Args
2114 std::is_nothrow_constructible
<T
, std::initializer_list
<U
>&, Args
&&...>::value
2117 value_type
& emplace( std::initializer_list
<U
> il
, Args
&&... args
)
2119 expected( nonstd_lite_in_place(T
), il
, std::forward
<Args
>(args
)... ).swap( *this );
2125 template< typename U
=T
, typename G
=E
>
2126 nsel_REQUIRES_R( void,
2127 std17::is_swappable
< U
>::value
2128 && std17::is_swappable
<G
>::value
2129 && ( std::is_move_constructible
<U
>::value
|| std::is_move_constructible
<G
>::value
)
2131 swap( expected
& other
) noexcept
2133 std::is_nothrow_move_constructible
<T
>::value
&& std17::is_nothrow_swappable
<T
&>::value
&&
2134 std::is_nothrow_move_constructible
<E
>::value
&& std17::is_nothrow_swappable
<E
&>::value
2139 if ( bool(*this) && bool(other
) ) { swap( contained
.value(), other
.contained
.value() ); }
2140 else if ( ! bool(*this) && ! bool(other
) ) { swap( contained
.error(), other
.contained
.error() ); }
2141 else if ( bool(*this) && ! bool(other
) ) { error_type
t( std::move( other
.error() ) );
2142 other
.contained
.destruct_error();
2143 other
.contained
.construct_value( std::move( contained
.value() ) );
2144 contained
.destruct_value();
2145 contained
.construct_error( std::move( t
) );
2146 bool has_value
= contained
.has_value();
2147 bool other_has_value
= other
.has_value();
2148 other
.contained
.set_has_value(has_value
);
2149 contained
.set_has_value(other_has_value
);
2151 else if ( ! bool(*this) && bool(other
) ) { other
.swap( *this ); }
2154 // x.x.4.5 observers
2156 constexpr value_type
const * operator ->() const
2158 return assert( has_value() ), contained
.value_ptr();
2161 value_type
* operator ->()
2163 return assert( has_value() ), contained
.value_ptr();
2166 constexpr value_type
const & operator *() const &
2168 return assert( has_value() ), contained
.value();
2171 value_type
& operator *() &
2173 return assert( has_value() ), contained
.value();
2176 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2178 constexpr value_type
const && operator *() const &&
2180 return std::move( ( assert( has_value() ), contained
.value() ) );
2183 nsel_constexpr14 value_type
&& operator *() &&
2185 return std::move( ( assert( has_value() ), contained
.value() ) );
2190 constexpr explicit operator bool() const noexcept
2195 constexpr bool has_value() const noexcept
2197 return contained
.has_value();
2200 nsel_DISABLE_MSVC_WARNINGS( 4702 ) // warning C4702: unreachable code, see issue 65.
2202 constexpr value_type
const & value() const &
2205 ? ( contained
.value() )
2206 : ( error_traits
<error_type
>::rethrow( contained
.error() ), contained
.value() );
2209 value_type
& value() &
2212 ? ( contained
.value() )
2213 : ( error_traits
<error_type
>::rethrow( contained
.error() ), contained
.value() );
2215 nsel_RESTORE_MSVC_WARNINGS()
2217 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2219 constexpr value_type
const && value() const &&
2221 return std::move( has_value()
2222 ? ( contained
.value() )
2223 : ( error_traits
<error_type
>::rethrow( contained
.error() ), contained
.value() ) );
2226 nsel_constexpr14 value_type
&& value() &&
2228 return std::move( has_value()
2229 ? ( contained
.value() )
2230 : ( error_traits
<error_type
>::rethrow( contained
.error() ), contained
.value() ) );
2235 constexpr error_type
const & error() const &
2237 return assert( ! has_value() ), contained
.error();
2240 error_type
& error() &
2242 return assert( ! has_value() ), contained
.error();
2245 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2247 constexpr error_type
const && error() const &&
2249 return std::move( ( assert( ! has_value() ), contained
.error() ) );
2252 error_type
&& error() &&
2254 return std::move( ( assert( ! has_value() ), contained
.error() ) );
2259 constexpr unexpected_type
get_unexpected() const
2261 return make_unexpected( contained
.error() );
2264 template< typename Ex
>
2265 bool has_exception() const
2267 using ContainedEx
= typename
std::remove_reference
< decltype( get_unexpected().value() ) >::type
;
2268 return ! has_value() && std::is_base_of
< Ex
, ContainedEx
>::value
;
2271 template< typename U
2273 std::is_copy_constructible
< T
>::value
2274 && std::is_convertible
<U
&&, T
>::value
2277 value_type
value_or( U
&& v
) const &
2281 : static_cast<T
>( std::forward
<U
>( v
) );
2284 template< typename U
2286 std::is_move_constructible
< T
>::value
2287 && std::is_convertible
<U
&&, T
>::value
2290 value_type
value_or( U
&& v
) &&
2293 ? std::move( contained
.value() )
2294 : static_cast<T
>( std::forward
<U
>( v
) );
2297 #if nsel_P2505R >= 4
2298 template< typename G
= E
2300 std::is_copy_constructible
< E
>::value
2301 && std::is_convertible
< G
, E
>::value
2304 nsel_constexpr error_type
error_or( G
&& e
) const &
2307 ? static_cast< E
>( std::forward
< G
>( e
) )
2308 : contained
.error();
2311 template< typename G
= E
2313 std::is_move_constructible
< E
>::value
2314 && std::is_convertible
< G
, E
>::value
2317 nsel_constexpr14 error_type
error_or( G
&& e
) &&
2320 ? static_cast< E
>( std::forward
< G
>( e
) )
2321 : std::move( contained
.error() );
2323 #endif // nsel_P2505R >= 4
2325 #if nsel_P2505R >= 3
2326 // Monadic operations (P2505)
2327 template< typename F
2329 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, value_type
& > > ::value
2330 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, value_type
& >::error_type
, error_type
>::value
2331 && std::is_constructible
< error_type
, error_type
& >::value
2334 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
, value_type
& > and_then( F
&& f
) &
2337 ? detail::invoke_result_nocvref_t
< F
, value_type
& >( detail::invoke( std::forward
< F
>( f
), value() ) )
2338 : detail::invoke_result_nocvref_t
< F
, value_type
& >( unexpect
, error() );
2343 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, const value_type
& > >::value
2344 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, const value_type
& >::error_type
, error_type
>::value
2345 && std::is_constructible
< error_type
, const error_type
& >::value
2348 nsel_constexpr
detail::invoke_result_nocvref_t
< F
, const value_type
& > and_then( F
&& f
) const &
2351 ? detail::invoke_result_nocvref_t
< F
, const value_type
& >( detail::invoke( std::forward
< F
>( f
), value() ) )
2352 : detail::invoke_result_nocvref_t
< F
, const value_type
& >( unexpect
, error() );
2355 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2358 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, value_type
&& > >::value
2359 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, value_type
&& >::error_type
, error_type
>::value
2360 && std::is_constructible
< error_type
, error_type
&& >::value
2363 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
, value_type
&& > and_then( F
&& f
) &&
2366 ? detail::invoke_result_nocvref_t
< F
, value_type
&& >( detail::invoke( std::forward
< F
>( f
), std::move( value() ) ) )
2367 : detail::invoke_result_nocvref_t
< F
, value_type
&& >( unexpect
, std::move( error() ) );
2372 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, const value_type
&& > >::value
2373 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, const value_type
& >::error_type
, error_type
>::value
2374 && std::is_constructible
< error_type
, const error_type
&& >::value
2377 nsel_constexpr
detail::invoke_result_nocvref_t
< F
, const value_type
&& > and_then( F
&& f
) const &&
2380 ? detail::invoke_result_nocvref_t
< F
, const value_type
&& >( detail::invoke( std::forward
< F
>( f
), std::move( value() ) ) )
2381 : detail::invoke_result_nocvref_t
< F
, const value_type
&& >( unexpect
, std::move( error() ) );
2387 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, error_type
& > >::value
2388 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, error_type
& >::value_type
, value_type
>::value
2389 && std::is_constructible
< value_type
, value_type
& >::value
2392 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
, error_type
& > or_else( F
&& f
) &
2395 ? detail::invoke_result_nocvref_t
< F
, error_type
& >( value() )
2396 : detail::invoke_result_nocvref_t
< F
, error_type
& >( detail::invoke( std::forward
< F
>( f
), error() ) );
2401 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, const error_type
& > >::value
2402 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, const error_type
& >::value_type
, value_type
>::value
2403 && std::is_constructible
< value_type
, const value_type
& >::value
2406 nsel_constexpr
detail::invoke_result_nocvref_t
< F
, const error_type
& > or_else( F
&& f
) const &
2409 ? detail::invoke_result_nocvref_t
< F
, const error_type
& >( value() )
2410 : detail::invoke_result_nocvref_t
< F
, const error_type
& >( detail::invoke( std::forward
< F
>( f
), error() ) );
2413 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2416 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, error_type
&& > >::value
2417 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, error_type
&& >::value_type
, value_type
>::value
2418 && std::is_constructible
< value_type
, value_type
&& >::value
2421 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
, error_type
&& > or_else( F
&& f
) &&
2424 ? detail::invoke_result_nocvref_t
< F
, error_type
&& >( std::move( value() ) )
2425 : detail::invoke_result_nocvref_t
< F
, error_type
&& >( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
2430 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, const error_type
&& > >::value
2431 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
, const error_type
&& >::value_type
, value_type
>::value
2432 && std::is_constructible
< value_type
, const value_type
&& >::value
2435 nsel_constexpr
detail::invoke_result_nocvref_t
< F
, const error_type
&& > or_else( F
&& f
) const &&
2438 ? detail::invoke_result_nocvref_t
< F
, const error_type
&& >( std::move( value() ) )
2439 : detail::invoke_result_nocvref_t
< F
, const error_type
&& >( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
2445 std::is_constructible
< error_type
, error_type
& >::value
2446 && !std::is_void
< detail::transform_invoke_result_t
< F
, value_type
& > >::value
2447 && detail::valid_expected_value_type
< detail::transform_invoke_result_t
< F
, value_type
& > >::value
2450 nsel_constexpr14 expected
< detail::transform_invoke_result_t
< F
, value_type
& >, error_type
> transform( F
&& f
) &
2453 ? expected
< detail::transform_invoke_result_t
< F
, value_type
& >, error_type
>( detail::invoke( std::forward
< F
>( f
), **this ) )
2454 : make_unexpected( error() );
2459 std::is_constructible
< error_type
, error_type
& >::value
2460 && std::is_void
< detail::transform_invoke_result_t
< F
, value_type
& > >::value
2463 nsel_constexpr14 expected
< void, error_type
> transform( F
&& f
) &
2466 ? ( detail::invoke( std::forward
< F
>( f
), **this ), expected
< void, error_type
>() )
2467 : make_unexpected( error() );
2472 std::is_constructible
< error_type
, const error_type
& >::value
2473 && !std::is_void
< detail::transform_invoke_result_t
< F
, const value_type
& > >::value
2474 && detail::valid_expected_value_type
< detail::transform_invoke_result_t
< F
, const value_type
& > >::value
2477 nsel_constexpr expected
< detail::transform_invoke_result_t
< F
, const value_type
& >, error_type
> transform( F
&& f
) const &
2480 ? expected
< detail::transform_invoke_result_t
< F
, const value_type
& >, error_type
>( detail::invoke( std::forward
< F
>( f
), **this ) )
2481 : make_unexpected( error() );
2486 std::is_constructible
< error_type
, const error_type
& >::value
2487 && std::is_void
< detail::transform_invoke_result_t
< F
, const value_type
& > >::value
2490 nsel_constexpr expected
< void, error_type
> transform( F
&& f
) const &
2493 ? ( detail::invoke( std::forward
< F
>( f
), **this ), expected
< void, error_type
>() )
2494 : make_unexpected( error() );
2497 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2500 std::is_constructible
< error_type
, error_type
&& >::value
2501 && !std::is_void
< detail::transform_invoke_result_t
< F
, value_type
&& > >::value
2502 && detail::valid_expected_value_type
< detail::transform_invoke_result_t
< F
, value_type
&& > >::value
2505 nsel_constexpr14 expected
< detail::transform_invoke_result_t
< F
, value_type
&& >, error_type
> transform( F
&& f
) &&
2508 ? expected
< detail::transform_invoke_result_t
< F
, value_type
&& >, error_type
>( detail::invoke( std::forward
< F
>( f
), std::move( **this ) ) )
2509 : make_unexpected( std::move( error() ) );
2514 std::is_constructible
< error_type
, error_type
&& >::value
2515 && std::is_void
< detail::transform_invoke_result_t
< F
, value_type
&& > >::value
2518 nsel_constexpr14 expected
< void, error_type
> transform( F
&& f
) &&
2521 ? ( detail::invoke( std::forward
< F
>( f
), **this ), expected
< void, error_type
>() )
2522 : make_unexpected( std::move( error() ) );
2527 std::is_constructible
< error_type
, const error_type
&& >::value
2528 && !std::is_void
< detail::transform_invoke_result_t
< F
, const value_type
&& > >::value
2529 && detail::valid_expected_value_type
< detail::transform_invoke_result_t
< F
, const value_type
&& > >::value
2532 nsel_constexpr expected
< detail::transform_invoke_result_t
< F
, const value_type
&& >, error_type
> transform( F
&& f
) const &&
2535 ? expected
< detail::transform_invoke_result_t
< F
, const value_type
&& >, error_type
>( detail::invoke( std::forward
< F
>( f
), std::move( **this ) ) )
2536 : make_unexpected( std::move( error() ) );
2541 std::is_constructible
< error_type
, const error_type
&& >::value
2542 && std::is_void
< detail::transform_invoke_result_t
< F
, const value_type
&& > >::value
2545 nsel_constexpr expected
< void, error_type
> transform( F
&& f
) const &&
2548 ? ( detail::invoke( std::forward
< F
>( f
), **this ), expected
< void, error_type
>() )
2549 : make_unexpected( std::move( error() ) );
2555 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, error_type
& > >::value
2556 && std::is_constructible
< value_type
, value_type
& >::value
2559 nsel_constexpr14 expected
< value_type
, detail::transform_invoke_result_t
< F
, error_type
& > > transform_error( F
&& f
) &
2562 ? expected
< value_type
, detail::transform_invoke_result_t
< F
, error_type
& > >( in_place
, **this )
2563 : make_unexpected( detail::invoke( std::forward
< F
>( f
), error() ) );
2568 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, const error_type
& > >::value
2569 && std::is_constructible
< value_type
, const value_type
& >::value
2572 nsel_constexpr expected
< value_type
, detail::transform_invoke_result_t
< F
, const error_type
& > > transform_error( F
&& f
) const &
2575 ? expected
< value_type
, detail::transform_invoke_result_t
< F
, const error_type
& > >( in_place
, **this )
2576 : make_unexpected( detail::invoke( std::forward
< F
>( f
), error() ) );
2579 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2582 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, error_type
&& > >::value
2583 && std::is_constructible
< value_type
, value_type
&& >::value
2586 nsel_constexpr14 expected
< value_type
, detail::transform_invoke_result_t
< F
, error_type
&& > > transform_error( F
&& f
) &&
2589 ? expected
< value_type
, detail::transform_invoke_result_t
< F
, error_type
&& > >( in_place
, std::move( **this ) )
2590 : make_unexpected( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
2595 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, const error_type
&& > >::value
2596 && std::is_constructible
< value_type
, const value_type
&& >::value
2599 nsel_constexpr expected
< value_type
, detail::transform_invoke_result_t
< F
, const error_type
&& > > transform_error( F
&& f
) const &&
2602 ? expected
< value_type
, detail::transform_invoke_result_t
< F
, const error_type
&& > >( in_place
, std::move( **this ) )
2603 : make_unexpected( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
2606 #endif // nsel_P2505R >= 3
2609 // template <class U, class E>
2610 // constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
2612 // template <class T, class E>
2613 // constexpr expected<T,E> expected<T,E>::unwrap() const&;
2615 // template <class U, class E>
2616 // expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
2618 // template <class T, class E>
2619 // template expected<T,E> expected<T,E>::unwrap() &&;
2623 // template< typename Ex, typename F>
2624 // expected<T,E> catch_exception(F&& f);
2626 // template< typename F>
2627 // expected<decltype(func(declval<T>())),E> map(F&& func) ;
2629 // template< typename F>
2630 // 'see below' bind(F&& func);
2632 // template< typename F>
2633 // expected<T,E> catch_error(F&& f);
2635 // template< typename F>
2636 // 'see below' then(F&& func);
2643 , std::is_copy_constructible
<T
>::value
&& std::is_copy_constructible
<E
>::value
2644 , std::is_move_constructible
<T
>::value
&& std::is_move_constructible
<E
>::value
2649 /// class expected, void specialization
2651 template< typename E
>
2652 class expected
<void, E
>
2655 template< typename
, typename
> friend class expected
;
2658 using value_type
= void;
2659 using error_type
= E
;
2660 using unexpected_type
= nonstd::unexpected_type
<E
>;
2662 // x.x.4.1 constructors
2664 constexpr expected() noexcept
2668 nsel_constexpr14
expected( expected
const & other
) = default;
2669 nsel_constexpr14
expected( expected
&& other
) = default;
2671 constexpr explicit expected( nonstd_lite_in_place_t(void) )
2675 template< typename G
= E
2677 !std::is_convertible
<G
const &, E
>::value
/*=> explicit */
2680 nsel_constexpr14
explicit expected( nonstd::unexpected_type
<G
> const & error
)
2681 : contained( false )
2683 contained
.construct_error( E
{ error
.error() } );
2686 template< typename G
= E
2688 std::is_convertible
<G
const &, E
>::value
/*=> non-explicit */
2691 nsel_constexpr14
/*non-explicit*/ expected( nonstd::unexpected_type
<G
> const & error
)
2692 : contained( false )
2694 contained
.construct_error( error
.error() );
2697 template< typename G
= E
2699 !std::is_convertible
<G
&&, E
>::value
/*=> explicit */
2702 nsel_constexpr14
explicit expected( nonstd::unexpected_type
<G
> && error
)
2703 : contained( false )
2705 contained
.construct_error( E
{ std::move( error
.error() ) } );
2708 template< typename G
= E
2710 std::is_convertible
<G
&&, E
>::value
/*=> non-explicit */
2713 nsel_constexpr14
/*non-explicit*/ expected( nonstd::unexpected_type
<G
> && error
)
2714 : contained( false )
2716 contained
.construct_error( std::move( error
.error() ) );
2719 template< typename
... Args
2721 std::is_constructible
<E
, Args
&&...>::value
2724 nsel_constexpr14
explicit expected( unexpect_t
, Args
&&... args
)
2725 : contained( false )
2727 contained
.emplace_error( std::forward
<Args
>( args
)... );
2730 template< typename U
, typename
... Args
2732 std::is_constructible
<E
, std::initializer_list
<U
>, Args
&&...>::value
2735 nsel_constexpr14
explicit expected( unexpect_t
, std::initializer_list
<U
> il
, Args
&&... args
)
2736 : contained( false )
2738 contained
.emplace_error( il
, std::forward
<Args
>( args
)... );
2745 if ( ! has_value() )
2747 contained
.destruct_error();
2751 // x.x.4.3 assignment
2753 expected
& operator=( expected
const & other
)
2755 expected( other
).swap( *this );
2759 expected
& operator=( expected
&& other
) noexcept
2761 std::is_nothrow_move_assignable
<E
>::value
&&
2762 std::is_nothrow_move_constructible
<E
>::value
)
2764 expected( std::move( other
) ).swap( *this );
2770 expected().swap( *this );
2775 template< typename G
= E
>
2776 nsel_REQUIRES_R( void,
2777 std17::is_swappable
<G
>::value
2778 && std::is_move_constructible
<G
>::value
2780 swap( expected
& other
) noexcept
2782 std::is_nothrow_move_constructible
<E
>::value
&& std17::is_nothrow_swappable
<E
&>::value
2787 if ( ! bool(*this) && ! bool(other
) ) { swap( contained
.error(), other
.contained
.error() ); }
2788 else if ( bool(*this) && ! bool(other
) ) { contained
.construct_error( std::move( other
.error() ) );
2789 bool has_value
= contained
.has_value();
2790 bool other_has_value
= other
.has_value();
2791 other
.contained
.set_has_value(has_value
);
2792 contained
.set_has_value(other_has_value
);
2794 else if ( ! bool(*this) && bool(other
) ) { other
.swap( *this ); }
2797 // x.x.4.5 observers
2799 constexpr explicit operator bool() const noexcept
2804 constexpr bool has_value() const noexcept
2806 return contained
.has_value();
2811 if ( ! has_value() )
2813 error_traits
<error_type
>::rethrow( contained
.error() );
2817 constexpr error_type
const & error() const &
2819 return assert( ! has_value() ), contained
.error();
2822 error_type
& error() &
2824 return assert( ! has_value() ), contained
.error();
2827 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2829 constexpr error_type
const && error() const &&
2831 return std::move( ( assert( ! has_value() ), contained
.error() ) );
2834 error_type
&& error() &&
2836 return std::move( ( assert( ! has_value() ), contained
.error() ) );
2841 constexpr unexpected_type
get_unexpected() const
2843 return make_unexpected( contained
.error() );
2846 template< typename Ex
>
2847 bool has_exception() const
2849 using ContainedEx
= typename
std::remove_reference
< decltype( get_unexpected().value() ) >::type
;
2850 return ! has_value() && std::is_base_of
< Ex
, ContainedEx
>::value
;
2853 #if nsel_P2505R >= 4
2854 template< typename G
= E
2856 std::is_copy_constructible
< E
>::value
2857 && std::is_convertible
< G
, E
>::value
2860 nsel_constexpr error_type
error_or( G
&& e
) const &
2863 ? static_cast< E
>( std::forward
< G
>( e
) )
2864 : contained
.error();
2867 template< typename G
= E
2869 std::is_move_constructible
< E
>::value
2870 && std::is_convertible
< G
, E
>::value
2873 nsel_constexpr14 error_type
error_or( G
&& e
) &&
2876 ? static_cast< E
>( std::forward
< G
>( e
) )
2877 : std::move( contained
.error() );
2879 #endif // nsel_P2505R >= 4
2881 #if nsel_P2505R >= 3
2882 // Monadic operations (P2505)
2885 detail::is_expected
< detail::invoke_result_nocvref_t
< F
> >::value
2886 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
>::error_type
, error_type
>::value
2887 && std::is_constructible
< error_type
, error_type
& >::value
2890 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
> and_then( F
&& f
) &
2893 ? detail::invoke_result_nocvref_t
< F
>( detail::invoke( std::forward
< F
>( f
) ) )
2894 : detail::invoke_result_nocvref_t
< F
>( unexpect
, error() );
2899 detail::is_expected
< detail::invoke_result_nocvref_t
< F
> >::value
2900 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
>::error_type
, error_type
>::value
2901 && std::is_constructible
< error_type
, const error_type
& >::value
2904 nsel_constexpr
detail::invoke_result_nocvref_t
< F
> and_then( F
&& f
) const &
2907 ? detail::invoke_result_nocvref_t
< F
>( detail::invoke( std::forward
< F
>( f
) ) )
2908 : detail::invoke_result_nocvref_t
< F
>( unexpect
, error() );
2911 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2914 detail::is_expected
< detail::invoke_result_nocvref_t
< F
> >::value
2915 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
>::error_type
, error_type
>::value
2916 && std::is_constructible
< error_type
, error_type
&& >::value
2919 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
> and_then( F
&& f
) &&
2922 ? detail::invoke_result_nocvref_t
< F
>( detail::invoke( std::forward
< F
>( f
) ) )
2923 : detail::invoke_result_nocvref_t
< F
>( unexpect
, std::move( error() ) );
2928 detail::is_expected
< detail::invoke_result_nocvref_t
< F
> >::value
2929 && std::is_same
< typename
detail::invoke_result_nocvref_t
< F
>::error_type
, error_type
>::value
2930 && std::is_constructible
< error_type
, const error_type
&& >::value
2933 nsel_constexpr
detail::invoke_result_nocvref_t
< F
> and_then( F
&& f
) const &&
2936 ? detail::invoke_result_nocvref_t
< F
>( detail::invoke( std::forward
< F
>( f
) ) )
2937 : detail::invoke_result_nocvref_t
< F
>( unexpect
, std::move( error() ) );
2943 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, error_type
& > >::value
2944 && std::is_void
< typename
detail::invoke_result_nocvref_t
< F
, error_type
& >::value_type
>::value
2947 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
, error_type
& > or_else( F
&& f
) &
2950 ? detail::invoke_result_nocvref_t
< F
, error_type
& >()
2951 : detail::invoke_result_nocvref_t
< F
, error_type
& >( detail::invoke( std::forward
< F
>( f
), error() ) );
2956 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, const error_type
& > >::value
2957 && std::is_void
< typename
detail::invoke_result_nocvref_t
< F
, const error_type
& >::value_type
>::value
2960 nsel_constexpr
detail::invoke_result_nocvref_t
< F
, const error_type
& > or_else( F
&& f
) const &
2963 ? detail::invoke_result_nocvref_t
< F
, const error_type
& >()
2964 : detail::invoke_result_nocvref_t
< F
, const error_type
& >( detail::invoke( std::forward
< F
>( f
), error() ) );
2967 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2970 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, error_type
&& > >::value
2971 && std::is_void
< typename
detail::invoke_result_nocvref_t
< F
, error_type
&& >::value_type
>::value
2974 nsel_constexpr14
detail::invoke_result_nocvref_t
< F
, error_type
&& > or_else( F
&& f
) &&
2977 ? detail::invoke_result_nocvref_t
< F
, error_type
&& >()
2978 : detail::invoke_result_nocvref_t
< F
, error_type
&& >( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
2983 detail::is_expected
< detail::invoke_result_nocvref_t
< F
, const error_type
&& > >::value
2984 && std::is_void
< typename
detail::invoke_result_nocvref_t
< F
, const error_type
&& >::value_type
>::value
2987 nsel_constexpr
detail::invoke_result_nocvref_t
< F
, const error_type
&& > or_else( F
&& f
) const &&
2990 ? detail::invoke_result_nocvref_t
< F
, const error_type
&& >()
2991 : detail::invoke_result_nocvref_t
< F
, const error_type
&& >( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
2997 std::is_constructible
< error_type
, error_type
& >::value
2998 && !std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3001 nsel_constexpr14 expected
< detail::transform_invoke_result_t
< F
>, error_type
> transform( F
&& f
) &
3004 ? expected
< detail::transform_invoke_result_t
< F
>, error_type
>( detail::invoke( std::forward
< F
>( f
) ) )
3005 : make_unexpected( error() );
3010 std::is_constructible
< error_type
, error_type
& >::value
3011 && std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3014 nsel_constexpr14 expected
< void, error_type
> transform( F
&& f
) &
3017 ? ( detail::invoke( std::forward
< F
>( f
) ), expected
< void, error_type
>() )
3018 : make_unexpected( error() );
3023 std::is_constructible
< error_type
, const error_type
& >::value
3024 && !std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3027 nsel_constexpr expected
< detail::transform_invoke_result_t
< F
>, error_type
> transform( F
&& f
) const &
3030 ? expected
< detail::transform_invoke_result_t
< F
>, error_type
>( detail::invoke( std::forward
< F
>( f
) ) )
3031 : make_unexpected( error() );
3036 std::is_constructible
< error_type
, const error_type
& >::value
3037 && std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3040 nsel_constexpr expected
< void, error_type
> transform( F
&& f
) const &
3043 ? ( detail::invoke( std::forward
< F
>( f
) ), expected
< void, error_type
>() )
3044 : make_unexpected( error() );
3047 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
3050 std::is_constructible
< error_type
, error_type
&& >::value
3051 && !std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3054 nsel_constexpr14 expected
< detail::transform_invoke_result_t
< F
>, error_type
> transform( F
&& f
) &&
3057 ? expected
< detail::transform_invoke_result_t
< F
>, error_type
>( detail::invoke( std::forward
< F
>( f
) ) )
3058 : make_unexpected( error() );
3063 std::is_constructible
< error_type
, error_type
&& >::value
3064 && std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3067 nsel_constexpr14 expected
< void, error_type
> transform( F
&& f
) &&
3070 ? ( detail::invoke( std::forward
< F
>( f
) ), expected
< void, error_type
>() )
3071 : make_unexpected( error() );
3076 std::is_constructible
< error_type
, const error_type
&& >::value
3077 && !std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3080 nsel_constexpr expected
< detail::transform_invoke_result_t
< F
>, error_type
> transform( F
&& f
) const &&
3083 ? expected
< detail::transform_invoke_result_t
< F
>, error_type
>( detail::invoke( std::forward
< F
>( f
) ) )
3084 : make_unexpected( error() );
3089 std::is_constructible
< error_type
, const error_type
&& >::value
3090 && std::is_void
< detail::transform_invoke_result_t
< F
> >::value
3093 nsel_constexpr expected
< void, error_type
> transform( F
&& f
) const &&
3096 ? ( detail::invoke( std::forward
< F
>( f
) ), expected
< void, error_type
>() )
3097 : make_unexpected( error() );
3103 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, error_type
& > >::value
3106 nsel_constexpr14 expected
< void, detail::transform_invoke_result_t
< F
, error_type
& > > transform_error( F
&& f
) &
3109 ? expected
< void, detail::transform_invoke_result_t
< F
, error_type
& > >()
3110 : make_unexpected( detail::invoke( std::forward
< F
>( f
), error() ) );
3115 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, const error_type
& > >::value
3118 nsel_constexpr expected
< void, detail::transform_invoke_result_t
< F
, const error_type
& > > transform_error( F
&& f
) const &
3121 ? expected
< void, detail::transform_invoke_result_t
< F
, const error_type
& > >()
3122 : make_unexpected( detail::invoke( std::forward
< F
>( f
), error() ) );
3125 #if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
3128 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, error_type
&& > >::value
3131 nsel_constexpr14 expected
< void, detail::transform_invoke_result_t
< F
, error_type
&& > > transform_error( F
&& f
) &&
3134 ? expected
< void, detail::transform_invoke_result_t
< F
, error_type
&& > >()
3135 : make_unexpected( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
3140 detail::valid_unexpected_type
< detail::transform_invoke_result_t
< F
, const error_type
&& > >::value
3143 nsel_constexpr expected
< void, detail::transform_invoke_result_t
< F
, const error_type
&& > > transform_error( F
&& f
) const &&
3146 ? expected
< void, detail::transform_invoke_result_t
< F
, const error_type
&& > >()
3147 : make_unexpected( detail::invoke( std::forward
< F
>( f
), std::move( error() ) ) );
3150 #endif // nsel_P2505R >= 3
3152 // template constexpr 'see below' unwrap() const&;
3154 // template 'see below' unwrap() &&;
3158 // template< typename Ex, typename F>
3159 // expected<void,E> catch_exception(F&& f);
3161 // template< typename F>
3162 // expected<decltype(func()), E> map(F&& func) ;
3164 // template< typename F>
3165 // 'see below' bind(F&& func) ;
3167 // template< typename F>
3168 // expected<void,E> catch_error(F&& f);
3170 // template< typename F>
3171 // 'see below' then(F&& func);
3178 , std::is_copy_constructible
<E
>::value
3179 , std::is_move_constructible
<E
>::value
3184 // x.x.4.6 expected<>: comparison operators
3186 template< typename T1
, typename E1
, typename T2
, typename E2
3188 !std::is_void
<T1
>::value
&& !std::is_void
<T2
>::value
3191 constexpr bool operator==( expected
<T1
,E1
> const & x
, expected
<T2
,E2
> const & y
)
3193 return bool(x
) != bool(y
) ? false : bool(x
) ? *x
== *y
: x
.error() == y
.error();
3196 template< typename T1
, typename E1
, typename T2
, typename E2
3198 std::is_void
<T1
>::value
&& std::is_void
<T2
>::value
3201 constexpr bool operator==( expected
<T1
,E1
> const & x
, expected
<T2
,E2
> const & y
)
3203 return bool(x
) != bool(y
) ? false : bool(x
) || static_cast<bool>( x
.error() == y
.error() );
3206 template< typename T1
, typename E1
, typename T2
, typename E2
>
3207 constexpr bool operator!=( expected
<T1
,E1
> const & x
, expected
<T2
,E2
> const & y
)
3212 #if nsel_P0323R <= 2
3214 template< typename T
, typename E
>
3215 constexpr bool operator<( expected
<T
,E
> const & x
, expected
<T
,E
> const & y
)
3217 return (!y
) ? false : (!x
) ? true : *x
< *y
;
3220 template< typename T
, typename E
>
3221 constexpr bool operator>( expected
<T
,E
> const & x
, expected
<T
,E
> const & y
)
3226 template< typename T
, typename E
>
3227 constexpr bool operator<=( expected
<T
,E
> const & x
, expected
<T
,E
> const & y
)
3232 template< typename T
, typename E
>
3233 constexpr bool operator>=( expected
<T
,E
> const & x
, expected
<T
,E
> const & y
)
3240 // x.x.4.7 expected: comparison with T
3242 template< typename T1
, typename E1
, typename T2
3244 !std::is_void
<T1
>::value
3247 constexpr bool operator==( expected
<T1
,E1
> const & x
, T2
const & v
)
3249 return bool(x
) ? *x
== v
: false;
3252 template< typename T1
, typename E1
, typename T2
3254 !std::is_void
<T1
>::value
3257 constexpr bool operator==(T2
const & v
, expected
<T1
,E1
> const & x
)
3259 return bool(x
) ? v
== *x
: false;
3262 template< typename T1
, typename E1
, typename T2
>
3263 constexpr bool operator!=( expected
<T1
,E1
> const & x
, T2
const & v
)
3265 return bool(x
) ? *x
!= v
: true;
3268 template< typename T1
, typename E1
, typename T2
>
3269 constexpr bool operator!=( T2
const & v
, expected
<T1
,E1
> const & x
)
3271 return bool(x
) ? v
!= *x
: true;
3274 #if nsel_P0323R <= 2
3276 template< typename T
, typename E
>
3277 constexpr bool operator<( expected
<T
,E
> const & x
, T
const & v
)
3279 return bool(x
) ? *x
< v
: true;
3282 template< typename T
, typename E
>
3283 constexpr bool operator<( T
const & v
, expected
<T
,E
> const & x
)
3285 return bool(x
) ? v
< *x
: false;
3288 template< typename T
, typename E
>
3289 constexpr bool operator>( T
const & v
, expected
<T
,E
> const & x
)
3291 return bool(x
) ? *x
< v
: false;
3294 template< typename T
, typename E
>
3295 constexpr bool operator>( expected
<T
,E
> const & x
, T
const & v
)
3297 return bool(x
) ? v
< *x
: false;
3300 template< typename T
, typename E
>
3301 constexpr bool operator<=( T
const & v
, expected
<T
,E
> const & x
)
3303 return bool(x
) ? ! ( *x
< v
) : false;
3306 template< typename T
, typename E
>
3307 constexpr bool operator<=( expected
<T
,E
> const & x
, T
const & v
)
3309 return bool(x
) ? ! ( v
< *x
) : true;
3312 template< typename T
, typename E
>
3313 constexpr bool operator>=( expected
<T
,E
> const & x
, T
const & v
)
3315 return bool(x
) ? ! ( *x
< v
) : false;
3318 template< typename T
, typename E
>
3319 constexpr bool operator>=( T
const & v
, expected
<T
,E
> const & x
)
3321 return bool(x
) ? ! ( v
< *x
) : true;
3324 #endif // nsel_P0323R
3326 // x.x.4.8 expected: comparison with unexpected_type
3328 template< typename T1
, typename E1
, typename E2
>
3329 constexpr bool operator==( expected
<T1
,E1
> const & x
, unexpected_type
<E2
> const & u
)
3331 return (!x
) ? x
.get_unexpected() == u
: false;
3334 template< typename T1
, typename E1
, typename E2
>
3335 constexpr bool operator==( unexpected_type
<E2
> const & u
, expected
<T1
,E1
> const & x
)
3340 template< typename T1
, typename E1
, typename E2
>
3341 constexpr bool operator!=( expected
<T1
,E1
> const & x
, unexpected_type
<E2
> const & u
)
3343 return ! ( x
== u
);
3346 template< typename T1
, typename E1
, typename E2
>
3347 constexpr bool operator!=( unexpected_type
<E2
> const & u
, expected
<T1
,E1
> const & x
)
3349 return ! ( x
== u
);
3352 #if nsel_P0323R <= 2
3354 template< typename T
, typename E
>
3355 constexpr bool operator<( expected
<T
,E
> const & x
, unexpected_type
<E
> const & u
)
3357 return (!x
) ? ( x
.get_unexpected() < u
) : false;
3360 template< typename T
, typename E
>
3361 constexpr bool operator<( unexpected_type
<E
> const & u
, expected
<T
,E
> const & x
)
3363 return (!x
) ? ( u
< x
.get_unexpected() ) : true ;
3366 template< typename T
, typename E
>
3367 constexpr bool operator>( expected
<T
,E
> const & x
, unexpected_type
<E
> const & u
)
3372 template< typename T
, typename E
>
3373 constexpr bool operator>( unexpected_type
<E
> const & u
, expected
<T
,E
> const & x
)
3378 template< typename T
, typename E
>
3379 constexpr bool operator<=( expected
<T
,E
> const & x
, unexpected_type
<E
> const & u
)
3384 template< typename T
, typename E
>
3385 constexpr bool operator<=( unexpected_type
<E
> const & u
, expected
<T
,E
> const & x
)
3390 template< typename T
, typename E
>
3391 constexpr bool operator>=( expected
<T
,E
> const & x
, unexpected_type
<E
> const & u
)
3396 template< typename T
, typename E
>
3397 constexpr bool operator>=( unexpected_type
<E
> const & u
, expected
<T
,E
> const & x
)
3402 #endif // nsel_P0323R
3404 /// x.x.x Specialized algorithms
3406 template< typename T
, typename E
3408 ( std::is_void
<T
>::value
|| std::is_move_constructible
<T
>::value
)
3409 && std::is_move_constructible
<E
>::value
3410 && std17::is_swappable
<T
>::value
3411 && std17::is_swappable
<E
>::value
)
3413 void swap( expected
<T
,E
> & x
, expected
<T
,E
> & y
) noexcept ( noexcept ( x
.swap(y
) ) )
3418 #if nsel_P0323R <= 3
3420 template< typename T
>
3421 constexpr auto make_expected( T
&& v
) -> expected
< typename
std::decay
<T
>::type
>
3423 return expected
< typename
std::decay
<T
>::type
>( std::forward
<T
>( v
) );
3426 // expected<void> specialization:
3428 auto inline make_expected() -> expected
<void>
3430 return expected
<void>( in_place
);
3433 template< typename T
>
3434 constexpr auto make_expected_from_current_exception() -> expected
<T
>
3436 return expected
<T
>( make_unexpected_from_current_exception() );
3439 template< typename T
>
3440 auto make_expected_from_exception( std::exception_ptr v
) -> expected
<T
>
3442 return expected
<T
>( unexpected_type
<std::exception_ptr
>( std::forward
<std::exception_ptr
>( v
) ) );
3445 template< typename T
, typename E
>
3446 constexpr auto make_expected_from_error( E e
) -> expected
<T
, typename
std::decay
<E
>::type
>
3448 return expected
<T
, typename
std::decay
<E
>::type
>( make_unexpected( e
) );
3451 template< typename F
3452 nsel_REQUIRES_T( ! std::is_same
<typename
std::result_of
<F()>::type
, void>::value
)
3454 /*nsel_constexpr14*/
3455 auto make_expected_from_call( F f
) -> expected
< typename
std::result_of
<F()>::type
>
3459 return make_expected( f() );
3463 return make_unexpected_from_current_exception();
3467 template< typename F
3468 nsel_REQUIRES_T( std::is_same
<typename
std::result_of
<F()>::type
, void>::value
)
3470 /*nsel_constexpr14*/
3471 auto make_expected_from_call( F f
) -> expected
<void>
3476 return make_expected();
3480 return make_unexpected_from_current_exception();
3484 #endif // nsel_P0323R
3486 } // namespace expected_lite
3488 using namespace expected_lite
;
3490 // using expected_lite::expected;
3493 } // namespace nonstd
3497 // expected: hash support
3499 template< typename T
, typename E
>
3500 struct hash
< nonstd::expected
<T
,E
> >
3502 using result_type
= std::size_t;
3503 using argument_type
= nonstd::expected
<T
,E
>;
3505 constexpr result_type
operator()(argument_type
const & arg
) const
3507 return arg
? std::hash
<T
>{}(*arg
) : result_type
{};
3511 // TBD - ?? remove? see spec.
3512 template< typename T
, typename E
>
3513 struct hash
< nonstd::expected
<T
&,E
> >
3515 using result_type
= std::size_t;
3516 using argument_type
= nonstd::expected
<T
&,E
>;
3518 constexpr result_type
operator()(argument_type
const & arg
) const
3520 return arg
? std::hash
<T
>{}(*arg
) : result_type
{};
3525 // bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true;
3526 // otherwise it evaluates to an unspecified value if E is exception_ptr or
3527 // a combination of hashing false and hash<E>()(e.error()).
3529 template< typename E
>
3530 struct hash
< nonstd::expected
<void,E
> >
3538 // void unexpected() is deprecated && removed in C++17
3540 #if nsel_CPP17_OR_GREATER || nsel_COMPILER_MSVC_VERSION > 141
3541 template< typename E
>
3542 using unexpected
= unexpected_type
<E
>;
3545 } // namespace nonstd
3547 #undef nsel_REQUIRES
3548 #undef nsel_REQUIRES_0
3549 #undef nsel_REQUIRES_T
3551 nsel_RESTORE_WARNINGS()
3553 #endif // nsel_USES_STD_EXPECTED
3555 #endif // NONSTD_EXPECTED_LITE_HPP