NGen
Loading...
Searching...
No Matches
expected.hpp
1// Vendored from https://github.com/martinmoene/expected-lite/commit/a7510b213a668306fb038c934e27e53cc01141d4
2// This version targets C++11 and later.
3//
4// Copyright (C) 2016-2025 Martin Moene.
5//
6// Distributed under the Boost Software License, Version 1.0.
7// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8//
9// expected lite is based on:
10// A proposal to add a utility class to represent expected monad
11// by Vicente J. Botet Escriba and Pierre Talbot. http:://wg21.link/p0323
12
13#ifndef NONSTD_EXPECTED_LITE_HPP
14#define NONSTD_EXPECTED_LITE_HPP
15
16#define expected_lite_MAJOR 0
17#define expected_lite_MINOR 9
18#define expected_lite_PATCH 0
19
20#define expected_lite_VERSION expected_STRINGIFY(expected_lite_MAJOR) "." expected_STRINGIFY(expected_lite_MINOR) "." expected_STRINGIFY(expected_lite_PATCH)
21
22#define expected_STRINGIFY( x ) expected_STRINGIFY_( x )
23#define expected_STRINGIFY_( x ) #x
24
25// expected-lite configuration:
26
27#define nsel_EXPECTED_DEFAULT 0
28#define nsel_EXPECTED_NONSTD 1
29#define nsel_EXPECTED_STD 2
30
31// tweak header support:
32
33#ifdef __has_include
34# if __has_include(<nonstd/expected.tweak.hpp>)
35# include <nonstd/expected.tweak.hpp>
36# endif
37#define expected_HAVE_TWEAK_HEADER 1
38#else
39#define expected_HAVE_TWEAK_HEADER 0
40//# pragma message("expected.hpp: Note: Tweak header not supported.")
41#endif
42
43// expected selection and configuration:
44
45#if !defined( nsel_CONFIG_SELECT_EXPECTED )
46# define nsel_CONFIG_SELECT_EXPECTED ( nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD )
47#endif
48
49// Proposal revisions:
50//
51// DXXXXR0: --
52// N4015 : -2 (2014-05-26)
53// N4109 : -1 (2014-06-29)
54// P0323R0: 0 (2016-05-28)
55// P0323R1: 1 (2016-10-12)
56// -------:
57// P0323R2: 2 (2017-06-15)
58// P0323R3: 3 (2017-10-15)
59// P0323R4: 4 (2017-11-26)
60// P0323R5: 5 (2018-02-08)
61// P0323R6: 6 (2018-04-02)
62// P0323R7: 7 (2018-06-22) *
63//
64// expected-lite uses 2 and higher
65
66#ifndef nsel_P0323R
67# define nsel_P0323R 7
68#endif
69
70// Monadic operations proposal revisions:
71//
72// P2505R0: 0 (2021-12-12)
73// P2505R1: 1 (2022-02-10)
74// P2505R2: 2 (2022-04-15)
75// P2505R3: 3 (2022-06-05)
76// P2505R4: 4 (2022-06-15)
77// P2505R5: 5 (2022-09-20) *
78//
79// expected-lite uses 5
80
81#ifndef nsel_P2505R
82# define nsel_P2505R 5
83#endif
84
85// Lean and mean inclusion of Windows.h, if applicable; default on for MSVC:
86
87#if !defined(nsel_CONFIG_WIN32_LEAN_AND_MEAN) && defined(_MSC_VER)
88# define nsel_CONFIG_WIN32_LEAN_AND_MEAN 1
89#else
90# define nsel_CONFIG_WIN32_LEAN_AND_MEAN 0
91#endif
92
93// Control marking class expected with [[nodiscard]]]:
94
95#if !defined(nsel_CONFIG_NO_NODISCARD)
96# define nsel_CONFIG_NO_NODISCARD 0
97#else
98# define nsel_CONFIG_NO_NODISCARD 1
99#endif
100
101// Control presence of C++ exception handling (try and auto discover):
102
103#ifndef nsel_CONFIG_NO_EXCEPTIONS
104# if defined(_MSC_VER)
105# include <cstddef> // for _HAS_EXCEPTIONS
106# endif
107# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
108# define nsel_CONFIG_NO_EXCEPTIONS 0
109# else
110# define nsel_CONFIG_NO_EXCEPTIONS 1
111# endif
112#endif
113
114// at default use SEH with MSVC for no C++ exceptions
115
116#if !defined(nsel_CONFIG_NO_EXCEPTIONS_SEH) && defined(_MSC_VER)
117# define nsel_CONFIG_NO_EXCEPTIONS_SEH nsel_CONFIG_NO_EXCEPTIONS
118#else
119# define nsel_CONFIG_NO_EXCEPTIONS_SEH 0
120#endif
121
122// C++ language version detection (C++23 is speculative):
123// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
124
125#ifndef nsel_CPLUSPLUS
126# if defined(_MSVC_LANG ) && !defined(__clang__)
127# define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
128# else
129# define nsel_CPLUSPLUS __cplusplus
130# endif
131#endif
132
133#define nsel_CPP98_OR_GREATER ( nsel_CPLUSPLUS >= 199711L )
134#define nsel_CPP11_OR_GREATER ( nsel_CPLUSPLUS >= 201103L )
135#define nsel_CPP14_OR_GREATER ( nsel_CPLUSPLUS >= 201402L )
136#define nsel_CPP17_OR_GREATER ( nsel_CPLUSPLUS >= 201703L )
137#define nsel_CPP20_OR_GREATER ( nsel_CPLUSPLUS >= 202002L )
138#define nsel_CPP23_OR_GREATER ( nsel_CPLUSPLUS >= 202300L )
139
140// Use C++23 std::expected if available and requested:
141
142#if nsel_CPP23_OR_GREATER && defined(__has_include )
143# if __has_include( <expected> )
144# define nsel_HAVE_STD_EXPECTED 1
145# else
146# define nsel_HAVE_STD_EXPECTED 0
147# endif
148#else
149# define nsel_HAVE_STD_EXPECTED 0
150#endif
151
152#define nsel_USES_STD_EXPECTED ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) )
153
154//
155// in_place: code duplicated in any-lite, expected-lite, expected-lite, value-ptr-lite, variant-lite:
156//
157
158#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
159#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
160
161// C++17 std::in_place in <utility>:
162
163#if nsel_CPP17_OR_GREATER
164
165#include <utility>
166
167namespace nonstd {
168
169using std::in_place;
170using std::in_place_type;
171using std::in_place_index;
172using std::in_place_t;
173using std::in_place_type_t;
174using std::in_place_index_t;
175
176#define nonstd_lite_in_place_t( T) std::in_place_t
177#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
178#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
179
180#define nonstd_lite_in_place( T) std::in_place_t{}
181#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
182#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
183
184} // namespace nonstd
185
186#else // nsel_CPP17_OR_GREATER
187
188#include <cstddef>
189
190namespace nonstd {
191namespace detail {
192
193template< class T >
195
196template< std::size_t K >
198
199} // namespace detail
200
201struct in_place_t {};
202
203template< class T >
208
209template< std::size_t K >
214
215template< class T >
220
221template< std::size_t K >
226
227// mimic templated typedef:
228
229#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
230#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
231#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
232
233#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
234#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
235#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
236
237} // namespace nonstd
238
239#endif // nsel_CPP17_OR_GREATER
240#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
241
242//
243// Using std::expected:
244//
245
246#if nsel_USES_STD_EXPECTED
247
248#include <expected>
249
250namespace nonstd {
251
252 using std::expected;
253 using std::unexpected;
254 using std::bad_expected_access;
255 using std::unexpect_t;
256 using std::unexpect;
257
258 //[[deprecated("replace unexpected_type with unexpected")]]
259
260 template< typename E >
261 using unexpected_type = unexpected<E>;
262
263 // Unconditionally provide make_unexpected():
264
265 template< typename E >
266 constexpr auto make_unexpected( E && value ) -> unexpected< typename std::decay<E>::type >
267 {
268 return unexpected< typename std::decay<E>::type >( std::forward<E>(value) );
269 }
270
271 template
272 <
273 typename E, typename... Args,
274 typename = std::enable_if<
275 std::is_constructible<E, Args...>::value
276 >
277 >
278 constexpr auto
279 make_unexpected( std::in_place_t inplace, Args &&... args ) -> unexpected_type< typename std::decay<E>::type >
280 {
281 return unexpected_type< typename std::decay<E>::type >( inplace, std::forward<Args>(args)...);
282 }
283} // namespace nonstd
284
285#else // nsel_USES_STD_EXPECTED
286
287#include <cassert>
288#include <exception>
289#include <functional>
290#include <initializer_list>
291#include <memory>
292#include <new>
293#include <system_error>
294#include <type_traits>
295#include <utility>
296
297// additional includes:
298
299#if nsel_CONFIG_WIN32_LEAN_AND_MEAN
300# ifndef WIN32_LEAN_AND_MEAN
301# define WIN32_LEAN_AND_MEAN
302# endif
303#endif
304
305#if nsel_CONFIG_NO_EXCEPTIONS
306# if nsel_CONFIG_NO_EXCEPTIONS_SEH
307# include <windows.h> // for ExceptionCodes
308# else
309// already included: <cassert>
310# endif
311#else
312# include <stdexcept>
313#endif
314
315// C++ feature usage:
316
317#if nsel_CPP11_OR_GREATER
318# define nsel_constexpr constexpr
319#else
320# define nsel_constexpr /*constexpr*/
321#endif
322
323#if nsel_CPP14_OR_GREATER
324# define nsel_constexpr14 constexpr
325#else
326# define nsel_constexpr14 /*constexpr*/
327#endif
328
329#if nsel_CPP17_OR_GREATER
330# define nsel_inline17 inline
331#else
332# define nsel_inline17 /*inline*/
333#endif
334
335// Compiler versions:
336//
337// MSVC++ 6.0 _MSC_VER == 1200 nsel_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
338// MSVC++ 7.0 _MSC_VER == 1300 nsel_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
339// MSVC++ 7.1 _MSC_VER == 1310 nsel_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
340// MSVC++ 8.0 _MSC_VER == 1400 nsel_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
341// MSVC++ 9.0 _MSC_VER == 1500 nsel_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
342// MSVC++ 10.0 _MSC_VER == 1600 nsel_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
343// MSVC++ 11.0 _MSC_VER == 1700 nsel_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
344// MSVC++ 12.0 _MSC_VER == 1800 nsel_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
345// MSVC++ 14.0 _MSC_VER == 1900 nsel_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
346// MSVC++ 14.1 _MSC_VER >= 1910 nsel_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
347// MSVC++ 14.2 _MSC_VER >= 1920 nsel_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
348
349#if defined(_MSC_VER) && !defined(__clang__)
350# define nsel_COMPILER_MSVC_VER (_MSC_VER )
351# define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) )
352#else
353# define nsel_COMPILER_MSVC_VER 0
354# define nsel_COMPILER_MSVC_VERSION 0
355#endif
356
357#define nsel_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
358
359#if defined(__clang__)
360# define nsel_COMPILER_CLANG_VERSION nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
361#else
362# define nsel_COMPILER_CLANG_VERSION 0
363#endif
364
365#if defined(__GNUC__) && !defined(__clang__)
366# define nsel_COMPILER_GNUC_VERSION nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
367#else
368# define nsel_COMPILER_GNUC_VERSION 0
369#endif
370
371// half-open range [lo..hi):
372//#define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
373
374// Method enabling
375
376#define nsel_REQUIRES_0(...) \
377 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
378
379#define nsel_REQUIRES_T(...) \
380 , typename std::enable_if< (__VA_ARGS__), int >::type = 0
381
382#define nsel_REQUIRES_R(R, ...) \
383 typename std::enable_if< (__VA_ARGS__), R>::type
384
385#define nsel_REQUIRES_A(...) \
386 , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
387
388// Clang, GNUC, MSVC warning suppression macros:
389
390#ifdef __clang__
391# pragma clang diagnostic push
392#elif defined __GNUC__
393# pragma GCC diagnostic push
394#endif // __clang__
395
396#if nsel_COMPILER_MSVC_VERSION >= 140
397# define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(push) ) __pragma( warning(disable: codes) )
398#else
399# define nsel_DISABLE_MSVC_WARNINGS(codes)
400#endif
401
402#ifdef __clang__
403# define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
404# define nsel_RESTORE_MSVC_WARNINGS()
405#elif defined __GNUC__
406# define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
407# define nsel_RESTORE_MSVC_WARNINGS()
408#elif nsel_COMPILER_MSVC_VERSION >= 140
409# define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) )
410# define nsel_RESTORE_MSVC_WARNINGS() nsel_RESTORE_WARNINGS()
411#else
412# define nsel_RESTORE_WARNINGS()
413# define nsel_RESTORE_MSVC_WARNINGS()
414#endif
415
416// Suppress the following MSVC (GSL) warnings:
417// - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11)
418
419nsel_DISABLE_MSVC_WARNINGS( 26409 )
420
421// Presence of language and library features:
422
423#ifdef _HAS_CPP0X
424# define nsel_HAS_CPP0X _HAS_CPP0X
425#else
426# define nsel_HAS_CPP0X 0
427#endif
428
429// Presence of language and library features:
430
431#define nsel_CPP11_000 (nsel_CPP11_OR_GREATER)
432#define nsel_CPP17_000 (nsel_CPP17_OR_GREATER)
433
434// Presence of C++11 library features:
435
436#define nsel_HAVE_ADDRESSOF nsel_CPP11_000
437
438// Presence of C++17 language features:
439
440#define nsel_HAVE_DEPRECATED nsel_CPP17_000
441#define nsel_HAVE_NODISCARD nsel_CPP17_000
442
443// C++ feature usage:
444
445#if nsel_HAVE_DEPRECATED
446# define nsel_deprecated(msg) [[deprecated(msg)]]
447#else
448# define nsel_deprecated(msg) /*[[deprecated]]*/
449#endif
450
451#if nsel_HAVE_NODISCARD && !nsel_CONFIG_NO_NODISCARD
452# define nsel_NODISCARD [[nodiscard]]
453#else
454# define nsel_NODISCARD /*[[nodiscard]]*/
455#endif
456
457//
458// expected:
459//
460
461namespace nonstd { namespace expected_lite {
462
463// library features C++11:
464
465namespace std11 {
466
467// #if 0 && nsel_HAVE_ADDRESSOF
468#if nsel_HAVE_ADDRESSOF
469 using std::addressof;
470#else
471 template< class T >
472 T * addressof( T & arg ) noexcept
473 {
474 return &arg;
475 }
476
477 template< class T >
478 const T * addressof( const T && ) = delete;
479#endif
480} // namespace std11
481
482// type traits C++17:
483
484namespace std17 {
485
486#if nsel_CPP17_OR_GREATER
487
488using std::conjunction;
489using std::is_swappable;
490using std::is_nothrow_swappable;
491
492#else // nsel_CPP17_OR_GREATER
493
494namespace detail {
495
496using std::swap;
497
498struct is_swappable
499{
500 template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
501 static std::true_type test( int /* unused */);
502
503 template< typename >
504 static std::false_type test(...);
505};
506
507struct is_nothrow_swappable
508{
509 // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
510
511 template< typename T >
512 static constexpr bool satisfies()
513 {
514 return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
515 }
516
517 template< typename T >
518 static auto test( int ) -> std::integral_constant<bool, satisfies<T>()>{}
519
520 template< typename >
521 static auto test(...) -> std::false_type;
522};
523} // namespace detail
524
525// is [nothrow] swappable:
526
527template< typename T >
528struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
529
530template< typename T >
531struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
532
533// conjunction:
534
535template< typename... > struct conjunction : std::true_type{};
536template< typename B1 > struct conjunction<B1> : B1{};
537
538template< typename B1, typename... Bn >
539struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type{};
540
541#endif // nsel_CPP17_OR_GREATER
542
543} // namespace std17
544
545// type traits C++20:
546
547namespace std20 {
548
549#if defined(__cpp_lib_remove_cvref)
550
551using std::remove_cvref;
552
553#else
554
555template< typename T >
556struct remove_cvref
557{
558 typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
559};
560
561#endif
562
563} // namespace std20
564
565// forward declaration:
566
567template< typename T, typename E >
568class expected;
569
570namespace detail {
571
572#if nsel_P2505R >= 3
573template< typename T >
574struct is_expected : std::false_type {};
575
576template< typename T, typename E >
577struct is_expected< expected< T, E > > : std::true_type {};
578#endif // nsel_P2505R >= 3
579
581
582template< typename T, typename E >
583class storage_t_noncopy_nonmove_impl
584{
585 template< typename, typename > friend class nonstd::expected_lite::expected;
586
587public:
588 using value_type = T;
589 using error_type = E;
590
591 // no-op construction
592 storage_t_noncopy_nonmove_impl() {}
593 ~storage_t_noncopy_nonmove_impl() {}
594
595 explicit storage_t_noncopy_nonmove_impl( bool has_value )
596 : m_has_value( has_value )
597 {}
598
599 void construct_value()
600 {
601 new( std11::addressof(m_value) ) value_type();
602 }
603
604 // void construct_value( value_type const & e )
605 // {
606 // new( std11::addressof(m_value) ) value_type( e );
607 // }
608
609 // void construct_value( value_type && e )
610 // {
611 // new( std11::addressof(m_value) ) value_type( std::move( e ) );
612 // }
613
614 template< class... Args >
615 void emplace_value( Args&&... args )
616 {
617 new( std11::addressof(m_value) ) value_type( std::forward<Args>(args)...);
618 }
619
620 template< class U, class... Args >
621 void emplace_value( std::initializer_list<U> il, Args&&... args )
622 {
623 new( std11::addressof(m_value) ) value_type( il, std::forward<Args>(args)... );
624 }
625
626 void destruct_value()
627 {
628 m_value.~value_type();
629 }
630
631 // void construct_error( error_type const & e )
632 // {
633 // // new( std11::addressof(m_error) ) error_type( e );
634 // }
635
636 // void construct_error( error_type && e )
637 // {
638 // // new( std11::addressof(m_error) ) error_type( std::move( e ) );
639 // }
640
641 template< class... Args >
642 void emplace_error( Args&&... args )
643 {
644 new( std11::addressof(m_error) ) error_type( std::forward<Args>(args)...);
645 }
646
647 template< class U, class... Args >
648 void emplace_error( std::initializer_list<U> il, Args&&... args )
649 {
650 new( std11::addressof(m_error) ) error_type( il, std::forward<Args>(args)... );
651 }
652
653 void destruct_error()
654 {
655 m_error.~error_type();
656 }
657
658 constexpr value_type const & value() const &
659 {
660 return m_value;
661 }
662
663 value_type & value() &
664 {
665 return m_value;
666 }
667
668 constexpr value_type const && value() const &&
669 {
670 return std::move( m_value );
671 }
672
673 nsel_constexpr14 value_type && value() &&
674 {
675 return std::move( m_value );
676 }
677
678 value_type const * value_ptr() const
679 {
680 return std11::addressof(m_value);
681 }
682
683 value_type * value_ptr()
684 {
685 return std11::addressof(m_value);
686 }
687
688 error_type const & error() const &
689 {
690 return m_error;
691 }
692
693 error_type & error() &
694 {
695 return m_error;
696 }
697
698 constexpr error_type const && error() const &&
699 {
700 return std::move( m_error );
701 }
702
703 nsel_constexpr14 error_type && error() &&
704 {
705 return std::move( m_error );
706 }
707
708 bool has_value() const
709 {
710 return m_has_value;
711 }
712
713 void set_has_value( bool v )
714 {
715 m_has_value = v;
716 }
717
718private:
719 union
720 {
721 value_type m_value;
722 error_type m_error;
723 };
724
725 bool m_has_value = false;
726};
727
728template< typename T, typename E >
729class storage_t_impl
730{
731 template< typename, typename > friend class nonstd::expected_lite::expected;
732
733public:
734 using value_type = T;
735 using error_type = E;
736
737 // no-op construction
738 storage_t_impl() {}
739 ~storage_t_impl() {}
740
741 explicit storage_t_impl( bool has_value )
742 : m_has_value( has_value )
743 {}
744
745 void construct_value()
746 {
747 new( std11::addressof(m_value) ) value_type();
748 }
749
750 void construct_value( value_type const & e )
751 {
752 new( std11::addressof(m_value) ) value_type( e );
753 }
754
755 void construct_value( value_type && e )
756 {
757 new( std11::addressof(m_value) ) value_type( std::move( e ) );
758 }
759
760 template< class... Args >
761 void emplace_value( Args&&... args )
762 {
763 new( std11::addressof(m_value) ) value_type( std::forward<Args>(args)...);
764 }
765
766 template< class U, class... Args >
767 void emplace_value( std::initializer_list<U> il, Args&&... args )
768 {
769 new( std11::addressof(m_value) ) value_type( il, std::forward<Args>(args)... );
770 }
771
772 void destruct_value()
773 {
774 m_value.~value_type();
775 }
776
777 void construct_error( error_type const & e )
778 {
779 new( std11::addressof(m_error) ) error_type( e );
780 }
781
782 void construct_error( error_type && e )
783 {
784 new( std11::addressof(m_error) ) error_type( std::move( e ) );
785 }
786
787 template< class... Args >
788 void emplace_error( Args&&... args )
789 {
790 new( std11::addressof(m_error) ) error_type( std::forward<Args>(args)...);
791 }
792
793 template< class U, class... Args >
794 void emplace_error( std::initializer_list<U> il, Args&&... args )
795 {
796 new( std11::addressof(m_error) ) error_type( il, std::forward<Args>(args)... );
797 }
798
799 void destruct_error()
800 {
801 m_error.~error_type();
802 }
803
804 constexpr value_type const & value() const &
805 {
806 return m_value;
807 }
808
809 value_type & value() &
810 {
811 return m_value;
812 }
813
814 constexpr value_type const && value() const &&
815 {
816 return std::move( m_value );
817 }
818
819 nsel_constexpr14 value_type && value() &&
820 {
821 return std::move( m_value );
822 }
823
824 value_type const * value_ptr() const
825 {
826 return std11::addressof(m_value);
827 }
828
829 value_type * value_ptr()
830 {
831 return std11::addressof(m_value);
832 }
833
834 error_type const & error() const &
835 {
836 return m_error;
837 }
838
839 error_type & error() &
840 {
841 return m_error;
842 }
843
844 constexpr error_type const && error() const &&
845 {
846 return std::move( m_error );
847 }
848
849 nsel_constexpr14 error_type && error() &&
850 {
851 return std::move( m_error );
852 }
853
854 bool has_value() const
855 {
856 return m_has_value;
857 }
858
859 void set_has_value( bool v )
860 {
861 m_has_value = v;
862 }
863
864private:
865 union
866 {
867 value_type m_value;
868 error_type m_error;
869 };
870
871 bool m_has_value = false;
872};
873
875
876template< typename E >
877struct storage_t_impl< void, E >
878{
879 template< typename, typename > friend class nonstd::expected_lite::expected;
880
881public:
882 using value_type = void;
883 using error_type = E;
884
885 // no-op construction
886 storage_t_impl() {}
887 ~storage_t_impl() {}
888
889 explicit storage_t_impl( bool has_value )
890 : m_has_value( has_value )
891 {}
892
893 void construct_error( error_type const & e )
894 {
895 new( std11::addressof(m_error) ) error_type( e );
896 }
897
898 void construct_error( error_type && e )
899 {
900 new( std11::addressof(m_error) ) error_type( std::move( e ) );
901 }
902
903 template< class... Args >
904 void emplace_error( Args&&... args )
905 {
906 new( std11::addressof(m_error) ) error_type( std::forward<Args>(args)...);
907 }
908
909 template< class U, class... Args >
910 void emplace_error( std::initializer_list<U> il, Args&&... args )
911 {
912 new( std11::addressof(m_error) ) error_type( il, std::forward<Args>(args)... );
913 }
914
915 void destruct_error()
916 {
917 m_error.~error_type();
918 }
919
920 error_type const & error() const &
921 {
922 return m_error;
923 }
924
925 error_type & error() &
926 {
927 return m_error;
928 }
929
930 constexpr error_type const && error() const &&
931 {
932 return std::move( m_error );
933 }
934
935 nsel_constexpr14 error_type && error() &&
936 {
937 return std::move( m_error );
938 }
939
940 bool has_value() const
941 {
942 return m_has_value;
943 }
944
945 void set_has_value( bool v )
946 {
947 m_has_value = v;
948 }
949
950private:
951 union
952 {
953 char m_dummy;
954 error_type m_error;
955 };
956
957 bool m_has_value = false;
958};
959
960template< typename T, typename E, bool isConstructable, bool isMoveable >
961class storage_t
962{
963public:
964};
965
966template< typename T, typename E >
967class storage_t<T, E, false, false> : public storage_t_noncopy_nonmove_impl<T, E>
968{
969public:
970 storage_t() = default;
971 ~storage_t() = default;
972
973 explicit storage_t( bool has_value )
974 : storage_t_noncopy_nonmove_impl<T, E>( has_value )
975 {}
976
977 storage_t( storage_t const & other ) = delete;
978 storage_t( storage_t && other ) = delete;
979
980};
981
982template< typename T, typename E >
983class storage_t<T, E, true, true> : public storage_t_impl<T, E>
984{
985public:
986 storage_t() = default;
987 ~storage_t() = default;
988
989 explicit storage_t( bool has_value )
990 : storage_t_impl<T, E>( has_value )
991 {}
992
993 storage_t( storage_t const & other )
994 : storage_t_impl<T, E>( other.has_value() )
995 {
996 if ( this->has_value() ) this->construct_value( other.value() );
997 else this->construct_error( other.error() );
998 }
999
1000 storage_t(storage_t && other )
1001 : storage_t_impl<T, E>( other.has_value() )
1002 {
1003 if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
1004 else this->construct_error( std::move( other.error() ) );
1005 }
1006};
1007
1008template< typename E >
1009class storage_t<void, E, true, true> : public storage_t_impl<void, E>
1010{
1011public:
1012 storage_t() = default;
1013 ~storage_t() = default;
1014
1015 explicit storage_t( bool has_value )
1016 : storage_t_impl<void, E>( has_value )
1017 {}
1018
1019 storage_t( storage_t const & other )
1020 : storage_t_impl<void, E>( other.has_value() )
1021 {
1022 if ( this->has_value() ) ;
1023 else this->construct_error( other.error() );
1024 }
1025
1026 storage_t(storage_t && other )
1027 : storage_t_impl<void, E>( other.has_value() )
1028 {
1029 if ( this->has_value() ) ;
1030 else this->construct_error( std::move( other.error() ) );
1031 }
1032};
1033
1034template< typename T, typename E >
1035class storage_t<T, E, true, false> : public storage_t_impl<T, E>
1036{
1037public:
1038 storage_t() = default;
1039 ~storage_t() = default;
1040
1041 explicit storage_t( bool has_value )
1042 : storage_t_impl<T, E>( has_value )
1043 {}
1044
1045 storage_t( storage_t const & other )
1046 : storage_t_impl<T, E>(other.has_value())
1047 {
1048 if ( this->has_value() ) this->construct_value( other.value() );
1049 else this->construct_error( other.error() );
1050 }
1051
1052 storage_t( storage_t && other ) = delete;
1053};
1054
1055template< typename E >
1056class storage_t<void, E, true, false> : public storage_t_impl<void, E>
1057{
1058public:
1059 storage_t() = default;
1060 ~storage_t() = default;
1061
1062 explicit storage_t( bool has_value )
1063 : storage_t_impl<void, E>( has_value )
1064 {}
1065
1066 storage_t( storage_t const & other )
1067 : storage_t_impl<void, E>(other.has_value())
1068 {
1069 if ( this->has_value() ) ;
1070 else this->construct_error( other.error() );
1071 }
1072
1073 storage_t( storage_t && other ) = delete;
1074};
1075
1076template< typename T, typename E >
1077class storage_t<T, E, false, true> : public storage_t_impl<T, E>
1078{
1079public:
1080 storage_t() = default;
1081 ~storage_t() = default;
1082
1083 explicit storage_t( bool has_value )
1084 : storage_t_impl<T, E>( has_value )
1085 {}
1086
1087 storage_t( storage_t const & other ) = delete;
1088
1089 storage_t( storage_t && other )
1090 : storage_t_impl<T, E>( other.has_value() )
1091 {
1092 if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
1093 else this->construct_error( std::move( other.error() ) );
1094 }
1095};
1096
1097template< typename E >
1098class storage_t<void, E, false, true> : public storage_t_impl<void, E>
1099{
1100public:
1101 storage_t() = default;
1102 ~storage_t() = default;
1103
1104 explicit storage_t( bool has_value )
1105 : storage_t_impl<void, E>( has_value )
1106 {}
1107
1108 storage_t( storage_t const & other ) = delete;
1109
1110 storage_t( storage_t && other )
1111 : storage_t_impl<void, E>( other.has_value() )
1112 {
1113 if ( this->has_value() ) ;
1114 else this->construct_error( std::move( other.error() ) );
1115 }
1116};
1117
1118#if nsel_P2505R >= 3
1119// C++11 invoke implementation
1120template< typename >
1121struct is_reference_wrapper : std::false_type {};
1122template< typename T >
1123struct is_reference_wrapper< std::reference_wrapper< T > > : std::true_type {};
1124
1125template< typename FnT, typename ClassT, typename ObjectT, typename... Args
1126 nsel_REQUIRES_T(
1127 std::is_function<FnT>::value
1128 && ( std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
1129 || std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value )
1130 )
1131>
1132nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args )
1133 noexcept( noexcept( (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )... ) ) )
1134 -> decltype( (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )...) )
1135{
1136 return (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )... );
1137}
1138
1139template< typename FnT, typename ClassT, typename ObjectT, typename... Args
1140 nsel_REQUIRES_T(
1141 std::is_function<FnT>::value
1142 && is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
1143 )
1144>
1145nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args )
1146 noexcept( noexcept( (obj.get().*memfnptr)( std::forward< Args >( args ) ... ) ) )
1147 -> decltype( (obj.get().*memfnptr)( std::forward< Args >( args ) ... ) )
1148{
1149 return (obj.get().*memfnptr)( std::forward< Args >( args ) ... );
1150}
1151
1152template< typename FnT, typename ClassT, typename ObjectT, typename... Args
1153 nsel_REQUIRES_T(
1154 std::is_function<FnT>::value
1155 && !std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
1156 && !std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
1157 && !is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
1158 )
1159>
1160nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args )
1161 noexcept( noexcept( ((*std::forward< ObjectT >( obj )).*memfnptr)( std::forward< Args >( args ) ... ) ) )
1162 -> decltype( ((*std::forward< ObjectT >( obj )).*memfnptr)( std::forward< Args >( args ) ... ) )
1163{
1164 return ((*std::forward<ObjectT>(obj)).*memfnptr)( std::forward< Args >( args ) ... );
1165}
1166
1167template< typename MemberT, typename ClassT, typename ObjectT
1168 nsel_REQUIRES_T(
1169 std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
1170 || std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
1171 )
1172>
1173nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj )
1174 noexcept( noexcept( std::forward< ObjectT >( obj ).*memobjptr ) )
1175 -> decltype( std::forward< ObjectT >( obj ).*memobjptr )
1176{
1177 return std::forward< ObjectT >( obj ).*memobjptr;
1178}
1179
1180template< typename MemberT, typename ClassT, typename ObjectT
1181 nsel_REQUIRES_T(
1182 is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
1183 )
1184>
1185nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj )
1186 noexcept( noexcept( obj.get().*memobjptr ) )
1187 -> decltype( obj.get().*memobjptr )
1188{
1189 return obj.get().*memobjptr;
1190}
1191
1192template< typename MemberT, typename ClassT, typename ObjectT
1193 nsel_REQUIRES_T(
1194 !std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
1195 && !std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
1196 && !is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
1197 )
1198>
1199nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj )
1200 noexcept( noexcept( (*std::forward< ObjectT >( obj )).*memobjptr ) )
1201 -> decltype( (*std::forward< ObjectT >( obj )).*memobjptr )
1202{
1203 return (*std::forward< ObjectT >( obj )).*memobjptr;
1204}
1205
1206template< typename F, typename... Args
1207 nsel_REQUIRES_T(
1208 std::is_member_function_pointer< typename std20::remove_cvref< F >::type >::value
1209 )
1210>
1211nsel_constexpr auto invoke( F && f, Args && ... args )
1212 noexcept( noexcept( invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) )
1213 -> decltype( invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) )
1214{
1215 return invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... );
1216}
1217
1218template< typename F, typename... Args
1219 nsel_REQUIRES_T(
1220 std::is_member_object_pointer< typename std20::remove_cvref< F >::type >::value
1221 )
1222>
1223nsel_constexpr auto invoke( F && f, Args && ... args )
1224 noexcept( noexcept( invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) )
1225 -> decltype( invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) )
1226{
1227 return invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... );
1228}
1229
1230template< typename F, typename... Args
1231 nsel_REQUIRES_T(
1232 !std::is_member_function_pointer< typename std20::remove_cvref< F >::type >::value
1233 && !std::is_member_object_pointer< typename std20::remove_cvref< F >::type >::value
1234 )
1235>
1236nsel_constexpr auto invoke( F && f, Args && ... args )
1237 noexcept( noexcept( std::forward< F >( f )( std::forward< Args >( args ) ... ) ) )
1238 -> decltype( std::forward< F >( f )( std::forward< Args >( args ) ... ) )
1239{
1240 return std::forward< F >( f )( std::forward< Args >( args ) ... );
1241}
1242
1243template< typename F, typename ... Args >
1244using invoke_result_nocvref_t = typename std20::remove_cvref< decltype( ::nonstd::expected_lite::detail::invoke( std::declval< F >(), std::declval< Args >()... ) ) >::type;
1245
1246#if nsel_P2505R >= 5
1247template< typename F, typename ... Args >
1248using transform_invoke_result_t = typename std::remove_cv< decltype( ::nonstd::expected_lite::detail::invoke( std::declval< F >(), std::declval< Args >()... ) ) >::type;
1249#else
1250template< typename F, typename ... Args >
1251using transform_invoke_result_t = invoke_result_nocvref_t
1252#endif // nsel_P2505R >= 5
1253
1254template< typename T >
1255struct valid_expected_value_type : std::integral_constant< bool, std::is_destructible< T >::value && !std::is_reference< T >::value && !std::is_array< T >::value > {};
1256
1257#endif // nsel_P2505R >= 3
1258} // namespace detail
1259
1261
1262#if nsel_P0323R <= 2
1263template< typename E = std::exception_ptr >
1264class unexpected_type
1265#else
1266template< typename E >
1267class unexpected_type
1268#endif // nsel_P0323R
1269{
1270public:
1271 using error_type = E;
1272
1273 // x.x.5.2.1 Constructors
1274
1275// unexpected_type() = delete;
1276
1277 constexpr unexpected_type( unexpected_type const & ) = default;
1278 constexpr unexpected_type( unexpected_type && ) = default;
1279
1280 template< typename... Args
1281 nsel_REQUIRES_T(
1282 std::is_constructible<E, Args&&...>::value
1283 )
1284 >
1285 constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), Args &&... args )
1286 : m_error( std::forward<Args>( args )...)
1287 {}
1288
1289 template< typename U, typename... Args
1290 nsel_REQUIRES_T(
1291 std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
1292 )
1293 >
1294 constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), std::initializer_list<U> il, Args &&... args )
1295 : m_error( il, std::forward<Args>( args )...)
1296 {}
1297
1298 template< typename E2
1299 nsel_REQUIRES_T(
1300 std::is_constructible<E,E2>::value
1301 && !std::is_same< typename std20::remove_cvref<E2>::type, nonstd_lite_in_place_t(E2) >::value
1302 && !std::is_same< typename std20::remove_cvref<E2>::type, unexpected_type >::value
1303 )
1304 >
1305 constexpr explicit unexpected_type( E2 && error )
1306 : m_error( std::forward<E2>( error ) )
1307 {}
1308
1309 template< typename E2
1310 nsel_REQUIRES_T(
1311 std::is_constructible< E, E2>::value
1312 && !std::is_constructible<E, unexpected_type<E2> & >::value
1313 && !std::is_constructible<E, unexpected_type<E2> >::value
1314 && !std::is_constructible<E, unexpected_type<E2> const & >::value
1315 && !std::is_constructible<E, unexpected_type<E2> const >::value
1316 && !std::is_convertible< unexpected_type<E2> &, E>::value
1317 && !std::is_convertible< unexpected_type<E2> , E>::value
1318 && !std::is_convertible< unexpected_type<E2> const &, E>::value
1319 && !std::is_convertible< unexpected_type<E2> const , E>::value
1320 && !std::is_convertible< E2 const &, E>::value /*=> explicit */
1321 )
1322 >
1323 constexpr explicit unexpected_type( unexpected_type<E2> const & error )
1324 : m_error( E{ error.error() } )
1325 {}
1326
1327 template< typename E2
1328 nsel_REQUIRES_T(
1329 std::is_constructible< E, E2>::value
1330 && !std::is_constructible<E, unexpected_type<E2> & >::value
1331 && !std::is_constructible<E, unexpected_type<E2> >::value
1332 && !std::is_constructible<E, unexpected_type<E2> const & >::value
1333 && !std::is_constructible<E, unexpected_type<E2> const >::value
1334 && !std::is_convertible< unexpected_type<E2> &, E>::value
1335 && !std::is_convertible< unexpected_type<E2> , E>::value
1336 && !std::is_convertible< unexpected_type<E2> const &, E>::value
1337 && !std::is_convertible< unexpected_type<E2> const , E>::value
1338 && std::is_convertible< E2 const &, E>::value /*=> explicit */
1339 )
1340 >
1341 constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> const & error )
1342 : m_error( error.error() )
1343 {}
1344
1345 template< typename E2
1346 nsel_REQUIRES_T(
1347 std::is_constructible< E, E2>::value
1348 && !std::is_constructible<E, unexpected_type<E2> & >::value
1349 && !std::is_constructible<E, unexpected_type<E2> >::value
1350 && !std::is_constructible<E, unexpected_type<E2> const & >::value
1351 && !std::is_constructible<E, unexpected_type<E2> const >::value
1352 && !std::is_convertible< unexpected_type<E2> &, E>::value
1353 && !std::is_convertible< unexpected_type<E2> , E>::value
1354 && !std::is_convertible< unexpected_type<E2> const &, E>::value
1355 && !std::is_convertible< unexpected_type<E2> const , E>::value
1356 && !std::is_convertible< E2 const &, E>::value /*=> explicit */
1357 )
1358 >
1359 constexpr explicit unexpected_type( unexpected_type<E2> && error )
1360 : m_error( E{ std::move( error.error() ) } )
1361 {}
1362
1363 template< typename E2
1364 nsel_REQUIRES_T(
1365 std::is_constructible< E, E2>::value
1366 && !std::is_constructible<E, unexpected_type<E2> & >::value
1367 && !std::is_constructible<E, unexpected_type<E2> >::value
1368 && !std::is_constructible<E, unexpected_type<E2> const & >::value
1369 && !std::is_constructible<E, unexpected_type<E2> const >::value
1370 && !std::is_convertible< unexpected_type<E2> &, E>::value
1371 && !std::is_convertible< unexpected_type<E2> , E>::value
1372 && !std::is_convertible< unexpected_type<E2> const &, E>::value
1373 && !std::is_convertible< unexpected_type<E2> const , E>::value
1374 && std::is_convertible< E2 const &, E>::value /*=> non-explicit */
1375 )
1376 >
1377 constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> && error )
1378 : m_error( std::move( error.error() ) )
1379 {}
1380
1381 // x.x.5.2.2 Assignment
1382
1383 nsel_constexpr14 unexpected_type& operator=( unexpected_type const & ) = default;
1384 nsel_constexpr14 unexpected_type& operator=( unexpected_type && ) = default;
1385
1386 template< typename E2 = E >
1387 nsel_constexpr14 unexpected_type & operator=( unexpected_type<E2> const & other )
1388 {
1389 unexpected_type{ other.error() }.swap( *this );
1390 return *this;
1391 }
1392
1393 template< typename E2 = E >
1394 nsel_constexpr14 unexpected_type & operator=( unexpected_type<E2> && other )
1395 {
1396 unexpected_type{ std::move( other.error() ) }.swap( *this );
1397 return *this;
1398 }
1399
1400 // x.x.5.2.3 Observers
1401
1402 nsel_constexpr14 E & error() & noexcept
1403 {
1404 return m_error;
1405 }
1406
1407 constexpr E const & error() const & noexcept
1408 {
1409 return m_error;
1410 }
1411
1412#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1413
1414 nsel_constexpr14 E && error() && noexcept
1415 {
1416 return std::move( m_error );
1417 }
1418
1419 constexpr E const && error() const && noexcept
1420 {
1421 return std::move( m_error );
1422 }
1423
1424#endif
1425
1426 // x.x.5.2.3 Observers - deprecated
1427
1428 nsel_deprecated("replace value() with error()")
1429
1430 nsel_constexpr14 E & value() & noexcept
1431 {
1432 return m_error;
1433 }
1434
1435 nsel_deprecated("replace value() with error()")
1436
1437 constexpr E const & value() const & noexcept
1438 {
1439 return m_error;
1440 }
1441
1442#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1443
1444 nsel_deprecated("replace value() with error()")
1445
1446 nsel_constexpr14 E && value() && noexcept
1447 {
1448 return std::move( m_error );
1449 }
1450
1451 nsel_deprecated("replace value() with error()")
1452
1453 constexpr E const && value() const && noexcept
1454 {
1455 return std::move( m_error );
1456 }
1457
1458#endif
1459
1460 // x.x.5.2.4 Swap
1461
1462 template< typename U=E >
1463 nsel_REQUIRES_R( void,
1464 std17::is_swappable<U>::value
1465 )
1466 swap( unexpected_type & other ) noexcept (
1467 std17::is_nothrow_swappable<U>::value
1468 )
1469 {
1470 using std::swap;
1471 swap( m_error, other.m_error );
1472 }
1473
1474 // TODO: ??? unexpected_type: in-class friend operator==, !=
1475
1476private:
1477 error_type m_error;
1478};
1479
1480#if nsel_CPP17_OR_GREATER
1481
1483
1484template< typename E >
1485unexpected_type( E ) -> unexpected_type< E >;
1486
1487#endif
1488
1490
1491#if !nsel_CONFIG_NO_EXCEPTIONS
1492#if nsel_P0323R <= 2
1493
1494// TODO: Should expected be specialized for particular E types such as exception_ptr and how?
1495// See p0323r7 2.1. Ergonomics, http://wg21.link/p0323
1496template<>
1497class unexpected_type< std::exception_ptr >
1498{
1499public:
1500 using error_type = std::exception_ptr;
1501
1502 unexpected_type() = delete;
1503
1504 ~unexpected_type(){}
1505
1506 explicit unexpected_type( std::exception_ptr const & error )
1507 : m_error( error )
1508 {}
1509
1510 explicit unexpected_type(std::exception_ptr && error )
1511 : m_error( std::move( error ) )
1512 {}
1513
1514 template< typename E >
1515 explicit unexpected_type( E error )
1516 : m_error( std::make_exception_ptr( error ) )
1517 {}
1518
1519 std::exception_ptr const & value() const
1520 {
1521 return m_error;
1522 }
1523
1524 std::exception_ptr & value()
1525 {
1526 return m_error;
1527 }
1528
1529private:
1530 std::exception_ptr m_error;
1531};
1532
1533#endif // nsel_P0323R
1534#endif // !nsel_CONFIG_NO_EXCEPTIONS
1535
1537
1538template< typename E1, typename E2 >
1539constexpr bool operator==( unexpected_type<E1> const & x, unexpected_type<E2> const & y )
1540{
1541 return x.error() == y.error();
1542}
1543
1544template< typename E1, typename E2 >
1545constexpr bool operator!=( unexpected_type<E1> const & x, unexpected_type<E2> const & y )
1546{
1547 return ! ( x == y );
1548}
1549
1550#if nsel_P0323R <= 2
1551
1552template< typename E >
1553constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y )
1554{
1555 return x.error() < y.error();
1556}
1557
1558template< typename E >
1559constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y )
1560{
1561 return ( y < x );
1562}
1563
1564template< typename E >
1565constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y )
1566{
1567 return ! ( y < x );
1568}
1569
1570template< typename E >
1571constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y )
1572{
1573 return ! ( x < y );
1574}
1575
1576#endif // nsel_P0323R
1577
1579
1580template< typename E
1581 nsel_REQUIRES_T(
1582 std17::is_swappable<E>::value
1583 )
1584>
1585void swap( unexpected_type<E> & x, unexpected_type<E> & y) noexcept ( noexcept ( x.swap(y) ) )
1586{
1587 x.swap( y );
1588}
1589
1590#if nsel_P0323R <= 2
1591
1592// unexpected: relational operators for std::exception_ptr:
1593
1594inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
1595{
1596 return false;
1597}
1598
1599inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
1600{
1601 return false;
1602}
1603
1604inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
1605{
1606 return ( x == y );
1607}
1608
1609inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
1610{
1611 return ( x == y );
1612}
1613
1614#endif // nsel_P0323R
1615
1616// unexpected: traits
1617
1618#if nsel_P0323R <= 3
1619
1620template< typename E >
1621struct is_unexpected : std::false_type {};
1622
1623template< typename E >
1624struct is_unexpected< unexpected_type<E> > : std::true_type {};
1625
1626#endif // nsel_P0323R
1627
1628// unexpected: factory
1629
1630// keep make_unexpected() removed in p0323r2 for pre-C++17:
1631
1632template< typename E >
1633nsel_constexpr14 auto
1634make_unexpected( E && value ) -> unexpected_type< typename std::decay<E>::type >
1635{
1636 return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
1637}
1638
1639template
1640<
1641 typename E, typename... Args,
1642 typename = std::enable_if<
1643 std::is_constructible<E, Args...>::value
1644 >
1645>
1646nsel_constexpr14 auto
1647make_unexpected( nonstd_lite_in_place_t(E), Args &&... args ) -> unexpected_type< typename std::decay<E>::type >
1648{
1649 return std::move( unexpected_type< typename std::decay<E>::type >( nonstd_lite_in_place(E), std::forward<Args>(args)...) );
1650}
1651
1652#if nsel_P0323R <= 3
1653
1654/*nsel_constexpr14*/ auto inline
1655make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
1656{
1657 return unexpected_type< std::exception_ptr >( std::current_exception() );
1658}
1659
1660#endif // nsel_P0323R
1661
1663
1664template< typename E >
1665class nsel_NODISCARD bad_expected_access;
1666
1668
1669template <>
1670class nsel_NODISCARD bad_expected_access< void > : public std::exception
1671{
1672public:
1673 explicit bad_expected_access()
1674 : std::exception()
1675 {}
1676};
1677
1679
1680#if !nsel_CONFIG_NO_EXCEPTIONS
1681
1682template< typename E >
1683class nsel_NODISCARD bad_expected_access : public bad_expected_access< void >
1684{
1685public:
1686 using error_type = E;
1687
1688 explicit bad_expected_access( error_type error )
1689 : m_error( error )
1690 {}
1691
1692 virtual char const * what() const noexcept override
1693 {
1694 return "bad_expected_access";
1695 }
1696
1697 nsel_constexpr14 error_type & error() &
1698 {
1699 return m_error;
1700 }
1701
1702 constexpr error_type const & error() const &
1703 {
1704 return m_error;
1705 }
1706
1707#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1708
1709 nsel_constexpr14 error_type && error() &&
1710 {
1711 return std::move( m_error );
1712 }
1713
1714 constexpr error_type const && error() const &&
1715 {
1716 return std::move( m_error );
1717 }
1718
1719#endif
1720
1721private:
1722 error_type m_error;
1723};
1724
1725#endif // nsel_CONFIG_NO_EXCEPTIONS
1726
1728
1729struct unexpect_t{};
1730using in_place_unexpected_t = unexpect_t;
1731
1732nsel_inline17 constexpr unexpect_t unexpect{};
1733nsel_inline17 constexpr unexpect_t in_place_unexpected{};
1734
1736
1737#if nsel_CONFIG_NO_EXCEPTIONS
1738
1739namespace detail {
1740 inline bool text( char const * /*text*/ ) { return true; }
1741}
1742
1743template< typename Error >
1744struct error_traits
1745{
1746 static void rethrow( Error const & /*e*/ )
1747 {
1748#if nsel_CONFIG_NO_EXCEPTIONS_SEH
1749 RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL );
1750#else
1751 assert( false && detail::text("throw bad_expected_access<Error>{ e };") );
1752#endif
1753 }
1754};
1755
1756template<>
1757struct error_traits< std::exception_ptr >
1758{
1759 static void rethrow( std::exception_ptr const & /*e*/ )
1760 {
1761#if nsel_CONFIG_NO_EXCEPTIONS_SEH
1762 RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL );
1763#else
1764 assert( false && detail::text("throw bad_expected_access<std::exception_ptr>{ e };") );
1765#endif
1766 }
1767};
1768
1769template<>
1770struct error_traits< std::error_code >
1771{
1772 static void rethrow( std::error_code const & /*e*/ )
1773 {
1774#if nsel_CONFIG_NO_EXCEPTIONS_SEH
1775 RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL );
1776#else
1777 assert( false && detail::text("throw std::system_error( e );") );
1778#endif
1779 }
1780};
1781
1782#else // nsel_CONFIG_NO_EXCEPTIONS
1783
1784template< typename Error >
1785struct error_traits
1786{
1787 static void rethrow( Error const & e )
1788 {
1789 throw bad_expected_access<Error>{ e };
1790 }
1791};
1792
1793template<>
1794struct error_traits< std::exception_ptr >
1795{
1796 static void rethrow( std::exception_ptr const & e )
1797 {
1798 std::rethrow_exception( e );
1799 }
1800};
1801
1802template<>
1803struct error_traits< std::error_code >
1804{
1805 static void rethrow( std::error_code const & e )
1806 {
1807 throw std::system_error( e );
1808 }
1809};
1810
1811#endif // nsel_CONFIG_NO_EXCEPTIONS
1812
1813#if nsel_P2505R >= 3
1814namespace detail {
1815
1816// from https://en.cppreference.com/w/cpp/utility/expected/unexpected:
1817// "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."
1818template< typename T >
1819struct valid_unexpected_type : std::integral_constant< bool,
1820 std::is_same< T, typename std20::remove_cvref< T >::type >::value
1821 && std::is_object< T >::value
1822 && !std::is_array< T >::value
1823> {};
1824
1825template< typename T >
1826struct valid_unexpected_type< unexpected_type< T > > : std::false_type {};
1827
1828} // namespace detail
1829#endif // nsel_P2505R >= 3
1830
1831} // namespace expected_lite
1832
1833// provide nonstd::unexpected_type:
1834
1835using expected_lite::unexpected_type;
1836
1837namespace expected_lite {
1838
1840
1841#if nsel_P0323R <= 2
1842template< typename T, typename E = std::exception_ptr >
1843class nsel_NODISCARD expected
1844#else
1845template< typename T, typename E >
1846class nsel_NODISCARD expected
1847#endif // nsel_P0323R
1848{
1849private:
1850 template< typename, typename > friend class expected;
1851
1852public:
1853 using value_type = T;
1854 using error_type = E;
1855 using unexpected_type = nonstd::unexpected_type<E>;
1856
1857 template< typename U >
1858 struct rebind
1859 {
1860 using type = expected<U, error_type>;
1861 };
1862
1863 // x.x.4.1 constructors
1864
1865 nsel_REQUIRES_0(
1866 std::is_default_constructible<T>::value
1867 )
1868 nsel_constexpr14 expected()
1869 : contained( true )
1870 {
1871 contained.construct_value();
1872 }
1873
1874 nsel_constexpr14 expected( expected const & ) = default;
1875 nsel_constexpr14 expected( expected && ) = default;
1876
1877 template< typename U, typename G
1878 nsel_REQUIRES_T(
1879 std::is_constructible< T, U const &>::value
1880 && std::is_constructible<E, G const &>::value
1881 && !std::is_constructible<T, expected<U, G> & >::value
1882 && !std::is_constructible<T, expected<U, G> && >::value
1883 && !std::is_constructible<T, expected<U, G> const & >::value
1884 && !std::is_constructible<T, expected<U, G> const && >::value
1885 && !std::is_convertible< expected<U, G> & , T>::value
1886 && !std::is_convertible< expected<U, G> &&, T>::value
1887 && !std::is_convertible< expected<U, G> const & , T>::value
1888 && !std::is_convertible< expected<U, G> const &&, T>::value
1889 && (!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> explicit */
1890 )
1891 >
1892 nsel_constexpr14 explicit expected( expected<U, G> const & other )
1893 : contained( other.has_value() )
1894 {
1895 if ( has_value() ) contained.construct_value( T{ other.contained.value() } );
1896 else contained.construct_error( E{ other.contained.error() } );
1897 }
1898
1899 template< typename U, typename G
1900 nsel_REQUIRES_T(
1901 std::is_constructible< T, U const &>::value
1902 && std::is_constructible<E, G const &>::value
1903 && !std::is_constructible<T, expected<U, G> & >::value
1904 && !std::is_constructible<T, expected<U, G> && >::value
1905 && !std::is_constructible<T, expected<U, G> const & >::value
1906 && !std::is_constructible<T, expected<U, G> const && >::value
1907 && !std::is_convertible< expected<U, G> & , T>::value
1908 && !std::is_convertible< expected<U, G> &&, T>::value
1909 && !std::is_convertible< expected<U, G> const &, T>::value
1910 && !std::is_convertible< expected<U, G> const &&, T>::value
1911 && !(!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> non-explicit */
1912 )
1913 >
1914 nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> const & other )
1915 : contained( other.has_value() )
1916 {
1917 if ( has_value() ) contained.construct_value( other.contained.value() );
1918 else contained.construct_error( other.contained.error() );
1919 }
1920
1921 template< typename U, typename G
1922 nsel_REQUIRES_T(
1923 std::is_constructible< T, U>::value
1924 && std::is_constructible<E, G>::value
1925 && !std::is_constructible<T, expected<U, G> & >::value
1926 && !std::is_constructible<T, expected<U, G> && >::value
1927 && !std::is_constructible<T, expected<U, G> const & >::value
1928 && !std::is_constructible<T, expected<U, G> const && >::value
1929 && !std::is_convertible< expected<U, G> & , T>::value
1930 && !std::is_convertible< expected<U, G> &&, T>::value
1931 && !std::is_convertible< expected<U, G> const & , T>::value
1932 && !std::is_convertible< expected<U, G> const &&, T>::value
1933 && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> explicit */
1934 )
1935 >
1936 nsel_constexpr14 explicit expected( expected<U, G> && other )
1937 : contained( other.has_value() )
1938 {
1939 if ( has_value() ) contained.construct_value( T{ std::move( other.contained.value() ) } );
1940 else contained.construct_error( E{ std::move( other.contained.error() ) } );
1941 }
1942
1943 template< typename U, typename G
1944 nsel_REQUIRES_T(
1945 std::is_constructible< T, U>::value
1946 && std::is_constructible<E, G>::value
1947 && !std::is_constructible<T, expected<U, G> & >::value
1948 && !std::is_constructible<T, expected<U, G> && >::value
1949 && !std::is_constructible<T, expected<U, G> const & >::value
1950 && !std::is_constructible<T, expected<U, G> const && >::value
1951 && !std::is_convertible< expected<U, G> & , T>::value
1952 && !std::is_convertible< expected<U, G> &&, T>::value
1953 && !std::is_convertible< expected<U, G> const & , T>::value
1954 && !std::is_convertible< expected<U, G> const &&, T>::value
1955 && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> non-explicit */
1956 )
1957 >
1958 nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> && other )
1959 : contained( other.has_value() )
1960 {
1961 if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
1962 else contained.construct_error( std::move( other.contained.error() ) );
1963 }
1964
1965 template< typename U = T
1966 nsel_REQUIRES_T(
1967 std::is_copy_constructible<U>::value
1968 )
1969 >
1970 nsel_constexpr14 expected( value_type const & value )
1971 : contained( true )
1972 {
1973 contained.construct_value( value );
1974 }
1975
1976 template< typename U = T
1977 nsel_REQUIRES_T(
1978 std::is_constructible<T,U&&>::value
1979 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1980 && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value
1981 && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
1982 && !std::is_convertible<U&&,T>::value /*=> explicit */
1983 )
1984 >
1985 nsel_constexpr14 explicit expected( U && value ) noexcept
1986 (
1987 std::is_nothrow_move_constructible<U>::value &&
1988 std::is_nothrow_move_constructible<E>::value
1989 )
1990 : contained( true )
1991 {
1992 contained.construct_value( T{ std::forward<U>( value ) } );
1993 }
1994
1995 template< typename U = T
1996 nsel_REQUIRES_T(
1997 std::is_constructible<T,U&&>::value
1998 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1999 && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value
2000 && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
2001 && std::is_convertible<U&&,T>::value /*=> non-explicit */
2002 )
2003 >
2004 nsel_constexpr14 /*non-explicit*/ expected( U && value ) noexcept
2005 (
2006 std::is_nothrow_move_constructible<U>::value &&
2007 std::is_nothrow_move_constructible<E>::value
2008 )
2009 : contained( true )
2010 {
2011 contained.construct_value( std::forward<U>( value ) );
2012 }
2013
2014 // construct error:
2015
2016 template< typename G = E
2017 nsel_REQUIRES_T(
2018 std::is_constructible<E, G const & >::value
2019 && !std::is_convertible< G const &, E>::value /*=> explicit */
2020 )
2021 >
2022 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error )
2023 : contained( false )
2024 {
2025 contained.construct_error( E{ error.error() } );
2026 }
2027
2028 template< typename G = E
2029 nsel_REQUIRES_T(
2030 std::is_constructible<E, G const & >::value
2031 && std::is_convertible< G const &, E>::value /*=> non-explicit */
2032 )
2033 >
2034 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error )
2035 : contained( false )
2036 {
2037 contained.construct_error( error.error() );
2038 }
2039
2040 template< typename G = E
2041 nsel_REQUIRES_T(
2042 std::is_constructible<E, G&& >::value
2043 && !std::is_convertible< G&&, E>::value /*=> explicit */
2044 )
2045 >
2046 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error )
2047 : contained( false )
2048 {
2049 contained.construct_error( E{ std::move( error.error() ) } );
2050 }
2051
2052 template< typename G = E
2053 nsel_REQUIRES_T(
2054 std::is_constructible<E, G&& >::value
2055 && std::is_convertible< G&&, E>::value /*=> non-explicit */
2056 )
2057 >
2058 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error )
2059 : contained( false )
2060 {
2061 contained.construct_error( std::move( error.error() ) );
2062 }
2063
2064 // in-place construction, value
2065
2066 template< typename... Args
2067 nsel_REQUIRES_T(
2068 std::is_constructible<T, Args&&...>::value
2069 )
2070 >
2071 nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), Args&&... args )
2072 : contained( true )
2073 {
2074 contained.emplace_value( std::forward<Args>( args )... );
2075 }
2076
2077 template< typename U, typename... Args
2078 nsel_REQUIRES_T(
2079 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
2080 )
2081 >
2082 nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
2083 : contained( true )
2084 {
2085 contained.emplace_value( il, std::forward<Args>( args )... );
2086 }
2087
2088 // in-place construction, error
2089
2090 template< typename... Args
2091 nsel_REQUIRES_T(
2092 std::is_constructible<E, Args&&...>::value
2093 )
2094 >
2095 nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
2096 : contained( false )
2097 {
2098 contained.emplace_error( std::forward<Args>( args )... );
2099 }
2100
2101 template< typename U, typename... Args
2102 nsel_REQUIRES_T(
2103 std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
2104 )
2105 >
2106 nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
2107 : contained( false )
2108 {
2109 contained.emplace_error( il, std::forward<Args>( args )... );
2110 }
2111
2112 // x.x.4.2 destructor
2113
2114 // TODO: ~expected: triviality
2115 // 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>().
2116 // 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.
2117
2118 ~expected()
2119 {
2120 if ( has_value() ) contained.destruct_value();
2121 else contained.destruct_error();
2122 }
2123
2124 // x.x.4.3 assignment
2125
2126 expected & operator=( expected const & other )
2127 {
2128 expected( other ).swap( *this );
2129 return *this;
2130 }
2131
2132 expected & operator=( expected && other ) noexcept
2133 (
2134 std::is_nothrow_move_constructible< T>::value
2135 && std::is_nothrow_move_assignable< T>::value
2136 && std::is_nothrow_move_constructible<E>::value // added for missing
2137 && std::is_nothrow_move_assignable< E>::value ) // nothrow above
2138 {
2139 expected( std::move( other ) ).swap( *this );
2140 return *this;
2141 }
2142
2143 template< typename U
2144 nsel_REQUIRES_T(
2145 !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value
2146 && std17::conjunction<std::is_scalar<T>, std::is_same<T, std::decay<U>> >::value
2147 && std::is_constructible<T ,U>::value
2148 && std::is_assignable< T&,U>::value
2149 && std::is_nothrow_move_constructible<E>::value )
2150 >
2151 expected & operator=( U && value )
2152 {
2153 expected( std::forward<U>( value ) ).swap( *this );
2154 return *this;
2155 }
2156
2157 template< typename G = E
2158 nsel_REQUIRES_T(
2159 std::is_constructible<E, G const&>::value &&
2160 std::is_copy_constructible<G>::value // TODO: std::is_nothrow_copy_constructible<G>
2161 && std::is_copy_assignable<G>::value
2162 )
2163 >
2164 expected & operator=( nonstd::unexpected_type<G> const & error )
2165 {
2166 expected( unexpect, error.error() ).swap( *this );
2167 return *this;
2168 }
2169
2170 template< typename G = E
2171 nsel_REQUIRES_T(
2172 std::is_constructible<E, G&&>::value &&
2173 std::is_move_constructible<G>::value // TODO: std::is_nothrow_move_constructible<G>
2174 && std::is_move_assignable<G>::value
2175 )
2176 >
2177 expected & operator=( nonstd::unexpected_type<G> && error )
2178 {
2179 expected( unexpect, std::move( error.error() ) ).swap( *this );
2180 return *this;
2181 }
2182
2183 template< typename... Args
2184 nsel_REQUIRES_T(
2185 std::is_nothrow_constructible<T, Args&&...>::value
2186 )
2187 >
2188 value_type & emplace( Args &&... args )
2189 {
2190 expected( nonstd_lite_in_place(T), std::forward<Args>(args)... ).swap( *this );
2191 return value();
2192 }
2193
2194 template< typename U, typename... Args
2195 nsel_REQUIRES_T(
2196 std::is_nothrow_constructible<T, std::initializer_list<U>&, Args&&...>::value
2197 )
2198 >
2199 value_type & emplace( std::initializer_list<U> il, Args &&... args )
2200 {
2201 expected( nonstd_lite_in_place(T), il, std::forward<Args>(args)... ).swap( *this );
2202 return value();
2203 }
2204
2205 // x.x.4.4 swap
2206
2207 template< typename U=T, typename G=E >
2208 nsel_REQUIRES_R( void,
2209 std17::is_swappable< U>::value
2210 && std17::is_swappable<G>::value
2211 && ( std::is_move_constructible<U>::value || std::is_move_constructible<G>::value )
2212 )
2213 swap( expected & other ) noexcept
2214 (
2215 std::is_nothrow_move_constructible<T>::value && std17::is_nothrow_swappable<T&>::value &&
2216 std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::value
2217 )
2218 {
2219 using std::swap;
2220
2221 if ( bool(*this) && bool(other) ) { swap( contained.value(), other.contained.value() ); }
2222 else if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
2223 else if ( bool(*this) && ! bool(other) ) { error_type t( std::move( other.error() ) );
2224 other.contained.destruct_error();
2225 other.contained.construct_value( std::move( contained.value() ) );
2226 contained.destruct_value();
2227 contained.construct_error( std::move( t ) );
2228 bool has_value = contained.has_value();
2229 bool other_has_value = other.has_value();
2230 other.contained.set_has_value(has_value);
2231 contained.set_has_value(other_has_value);
2232 }
2233 else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
2234 }
2235
2236 // x.x.4.5 observers
2237
2238 constexpr value_type const * operator ->() const
2239 {
2240 return assert( has_value() ), contained.value_ptr();
2241 }
2242
2243 value_type * operator ->()
2244 {
2245 return assert( has_value() ), contained.value_ptr();
2246 }
2247
2248 constexpr value_type const & operator *() const &
2249 {
2250 return assert( has_value() ), contained.value();
2251 }
2252
2253 value_type & operator *() &
2254 {
2255 return assert( has_value() ), contained.value();
2256 }
2257
2258#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2259
2260 constexpr value_type const && operator *() const &&
2261 {
2262 return std::move( ( assert( has_value() ), contained.value() ) );
2263 }
2264
2265 nsel_constexpr14 value_type && operator *() &&
2266 {
2267 return std::move( ( assert( has_value() ), contained.value() ) );
2268 }
2269
2270#endif
2271
2272 constexpr explicit operator bool() const noexcept
2273 {
2274 return has_value();
2275 }
2276
2277 constexpr bool has_value() const noexcept
2278 {
2279 return contained.has_value();
2280 }
2281
2282 nsel_DISABLE_MSVC_WARNINGS( 4702 ) // warning C4702: unreachable code, see issue 65.
2283
2284 constexpr value_type const & value() const &
2285 {
2286 return has_value()
2287 ? ( contained.value() )
2288 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
2289 }
2290
2291 value_type & value() &
2292 {
2293 return has_value()
2294 ? ( contained.value() )
2295 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
2296 }
2297
2298#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2299
2300 constexpr value_type const && value() const &&
2301 {
2302 return std::move( has_value()
2303 ? ( contained.value() )
2304 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
2305 }
2306
2307 nsel_constexpr14 value_type && value() &&
2308 {
2309 return std::move( has_value()
2310 ? ( contained.value() )
2311 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
2312 }
2313
2314#endif
2315 nsel_RESTORE_MSVC_WARNINGS()
2316
2317 constexpr error_type const & error() const &
2318 {
2319 return assert( ! has_value() ), contained.error();
2320 }
2321
2322 error_type & error() &
2323 {
2324 return assert( ! has_value() ), contained.error();
2325 }
2326
2327#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2328
2329 constexpr error_type const && error() const &&
2330 {
2331 return std::move( ( assert( ! has_value() ), contained.error() ) );
2332 }
2333
2334 error_type && error() &&
2335 {
2336 return std::move( ( assert( ! has_value() ), contained.error() ) );
2337 }
2338
2339#endif
2340
2341 constexpr unexpected_type get_unexpected() const
2342 {
2343 return make_unexpected( contained.error() );
2344 }
2345
2346 template< typename Ex >
2347 bool has_exception() const
2348 {
2349 using ContainedEx = typename std::remove_reference< decltype( get_unexpected().error() ) >::type;
2350 return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
2351 }
2352
2353 template< typename U
2354 nsel_REQUIRES_T(
2355 std::is_copy_constructible< T>::value
2356 && std::is_convertible<U&&, T>::value
2357 )
2358 >
2359 value_type value_or( U && v ) const &
2360 {
2361 return has_value()
2362 ? contained.value()
2363 : static_cast<T>( std::forward<U>( v ) );
2364 }
2365
2366 template< typename U
2367 nsel_REQUIRES_T(
2368 std::is_move_constructible< T>::value
2369 && std::is_convertible<U&&, T>::value
2370 )
2371 >
2372 value_type value_or( U && v ) &&
2373 {
2374 return has_value()
2375 ? std::move( contained.value() )
2376 : static_cast<T>( std::forward<U>( v ) );
2377 }
2378
2379#if nsel_P2505R >= 4
2380 template< typename G = E
2381 nsel_REQUIRES_T(
2382 std::is_copy_constructible< E >::value
2383 && std::is_convertible< G, E >::value
2384 )
2385 >
2386 nsel_constexpr error_type error_or( G && e ) const &
2387 {
2388 return has_value()
2389 ? static_cast< E >( std::forward< G >( e ) )
2390 : contained.error();
2391 }
2392
2393 template< typename G = E
2394 nsel_REQUIRES_T(
2395 std::is_move_constructible< E >::value
2396 && std::is_convertible< G, E >::value
2397 )
2398 >
2399 nsel_constexpr14 error_type error_or( G && e ) &&
2400 {
2401 return has_value()
2402 ? static_cast< E >( std::forward< G >( e ) )
2403 : std::move( contained.error() );
2404 }
2405#endif // nsel_P2505R >= 4
2406
2407#if nsel_P2505R >= 3
2408 // Monadic operations (P2505)
2409 template< typename F
2410 nsel_REQUIRES_T(
2411 detail::is_expected < detail::invoke_result_nocvref_t< F, value_type & > > ::value
2412 && std::is_same< typename detail::invoke_result_nocvref_t< F, value_type & >::error_type, error_type >::value
2413 && std::is_constructible< error_type, error_type & >::value
2414 )
2415 >
2416 nsel_constexpr14 detail::invoke_result_nocvref_t< F, value_type & > and_then( F && f ) &
2417 {
2418 return has_value()
2419 ? detail::invoke_result_nocvref_t< F, value_type & >( detail::invoke( std::forward< F >( f ), value() ) )
2420 : detail::invoke_result_nocvref_t< F, value_type & >( unexpect, error() );
2421 }
2422
2423 template<typename F
2424 nsel_REQUIRES_T(
2425 detail::is_expected< detail::invoke_result_nocvref_t< F, const value_type & > >::value
2426 && std::is_same< typename detail::invoke_result_nocvref_t< F, const value_type & >::error_type, error_type >::value
2427 && std::is_constructible< error_type, const error_type & >::value
2428 )
2429 >
2430 nsel_constexpr detail::invoke_result_nocvref_t< F, const value_type & > and_then( F && f ) const &
2431 {
2432 return has_value()
2433 ? detail::invoke_result_nocvref_t< F, const value_type & >( detail::invoke( std::forward< F >( f ), value() ) )
2434 : detail::invoke_result_nocvref_t< F, const value_type & >( unexpect, error() );
2435 }
2436
2437#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2438 template<typename F
2439 nsel_REQUIRES_T(
2440 detail::is_expected< detail::invoke_result_nocvref_t< F, value_type && > >::value
2441 && std::is_same< typename detail::invoke_result_nocvref_t< F, value_type && >::error_type, error_type >::value
2442 && std::is_constructible< error_type, error_type && >::value
2443 )
2444 >
2445 nsel_constexpr14 detail::invoke_result_nocvref_t< F, value_type && > and_then( F && f ) &&
2446 {
2447 return has_value()
2448 ? detail::invoke_result_nocvref_t< F, value_type && >( detail::invoke( std::forward< F >( f ), std::move( value() ) ) )
2449 : detail::invoke_result_nocvref_t< F, value_type && >( unexpect, std::move( error() ) );
2450 }
2451
2452 template<typename F
2453 nsel_REQUIRES_T(
2454 detail::is_expected< detail::invoke_result_nocvref_t< F, const value_type && > >::value
2455 && std::is_same< typename detail::invoke_result_nocvref_t< F, const value_type & >::error_type, error_type >::value
2456 && std::is_constructible< error_type, const error_type && >::value
2457 )
2458 >
2459 nsel_constexpr detail::invoke_result_nocvref_t< F, const value_type && > and_then( F && f ) const &&
2460 {
2461 return has_value()
2462 ? detail::invoke_result_nocvref_t< F, const value_type && >( detail::invoke( std::forward< F >( f ), std::move( value() ) ) )
2463 : detail::invoke_result_nocvref_t< F, const value_type && >( unexpect, std::move( error() ) );
2464 }
2465#endif
2466
2467 template<typename F
2468 nsel_REQUIRES_T(
2469 detail::is_expected< detail::invoke_result_nocvref_t< F, error_type & > >::value
2470 && std::is_same< typename detail::invoke_result_nocvref_t< F, error_type & >::value_type, value_type >::value
2471 && std::is_constructible< value_type, value_type & >::value
2472 )
2473 >
2474 nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type & > or_else( F && f ) &
2475 {
2476 return has_value()
2477 ? detail::invoke_result_nocvref_t< F, error_type & >( value() )
2478 : detail::invoke_result_nocvref_t< F, error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
2479 }
2480
2481 template<typename F
2482 nsel_REQUIRES_T(
2483 detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type & > >::value
2484 && std::is_same< typename detail::invoke_result_nocvref_t< F, const error_type & >::value_type, value_type >::value
2485 && std::is_constructible< value_type, const value_type & >::value
2486 )
2487 >
2488 nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type & > or_else( F && f ) const &
2489 {
2490 return has_value()
2491 ? detail::invoke_result_nocvref_t< F, const error_type & >( value() )
2492 : detail::invoke_result_nocvref_t< F, const error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
2493 }
2494
2495#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2496 template<typename F
2497 nsel_REQUIRES_T(
2498 detail::is_expected< detail::invoke_result_nocvref_t< F, error_type && > >::value
2499 && std::is_same< typename detail::invoke_result_nocvref_t< F, error_type && >::value_type, value_type >::value
2500 && std::is_constructible< value_type, value_type && >::value
2501 )
2502 >
2503 nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type && > or_else( F && f ) &&
2504 {
2505 return has_value()
2506 ? detail::invoke_result_nocvref_t< F, error_type && >( std::move( value() ) )
2507 : detail::invoke_result_nocvref_t< F, error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
2508 }
2509
2510 template<typename F
2511 nsel_REQUIRES_T(
2512 detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type && > >::value
2513 && std::is_same< typename detail::invoke_result_nocvref_t< F, const error_type && >::value_type, value_type >::value
2514 && std::is_constructible< value_type, const value_type && >::value
2515 )
2516 >
2517 nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type && > or_else( F && f ) const &&
2518 {
2519 return has_value()
2520 ? detail::invoke_result_nocvref_t< F, const error_type && >( std::move( value() ) )
2521 : detail::invoke_result_nocvref_t< F, const error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
2522 }
2523#endif
2524
2525 template<typename F
2526 nsel_REQUIRES_T(
2527 std::is_constructible< error_type, error_type & >::value
2528 && !std::is_void< detail::transform_invoke_result_t< F, value_type & > >::value
2529 && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, value_type & > >::value
2530 )
2531 >
2532 nsel_constexpr14 expected< detail::transform_invoke_result_t< F, value_type & >, error_type > transform( F && f ) &
2533 {
2534 return has_value()
2535 ? expected< detail::transform_invoke_result_t< F, value_type & >, error_type >( detail::invoke( std::forward< F >( f ), **this ) )
2536 : make_unexpected( error() );
2537 }
2538
2539 template<typename F
2540 nsel_REQUIRES_T(
2541 std::is_constructible< error_type, error_type & >::value
2542 && std::is_void< detail::transform_invoke_result_t< F, value_type & > >::value
2543 )
2544 >
2545 nsel_constexpr14 expected< void, error_type > transform( F && f ) &
2546 {
2547 return has_value()
2548 ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
2549 : make_unexpected( error() );
2550 }
2551
2552 template<typename F
2553 nsel_REQUIRES_T(
2554 std::is_constructible< error_type, const error_type & >::value
2555 && !std::is_void< detail::transform_invoke_result_t< F, const value_type & > >::value
2556 && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, const value_type & > >::value
2557 )
2558 >
2559 nsel_constexpr expected< detail::transform_invoke_result_t< F, const value_type & >, error_type > transform( F && f ) const &
2560 {
2561 return has_value()
2562 ? expected< detail::transform_invoke_result_t< F, const value_type & >, error_type >( detail::invoke( std::forward< F >( f ), **this ) )
2563 : make_unexpected( error() );
2564 }
2565
2566 template<typename F
2567 nsel_REQUIRES_T(
2568 std::is_constructible< error_type, const error_type & >::value
2569 && std::is_void< detail::transform_invoke_result_t< F, const value_type & > >::value
2570 )
2571 >
2572 nsel_constexpr expected< void, error_type > transform( F && f ) const &
2573 {
2574 return has_value()
2575 ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
2576 : make_unexpected( error() );
2577 }
2578
2579#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2580 template<typename F
2581 nsel_REQUIRES_T(
2582 std::is_constructible< error_type, error_type && >::value
2583 && !std::is_void< detail::transform_invoke_result_t< F, value_type && > >::value
2584 && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, value_type && > >::value
2585 )
2586 >
2587 nsel_constexpr14 expected< detail::transform_invoke_result_t< F, value_type && >, error_type > transform( F && f ) &&
2588 {
2589 return has_value()
2590 ? expected< detail::transform_invoke_result_t< F, value_type && >, error_type >( detail::invoke( std::forward< F >( f ), std::move( **this ) ) )
2591 : make_unexpected( std::move( error() ) );
2592 }
2593
2594 template<typename F
2595 nsel_REQUIRES_T(
2596 std::is_constructible< error_type, error_type && >::value
2597 && std::is_void< detail::transform_invoke_result_t< F, value_type && > >::value
2598 )
2599 >
2600 nsel_constexpr14 expected< void, error_type > transform( F && f ) &&
2601 {
2602 return has_value()
2603 ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
2604 : make_unexpected( std::move( error() ) );
2605 }
2606
2607 template<typename F
2608 nsel_REQUIRES_T(
2609 std::is_constructible< error_type, const error_type && >::value
2610 && !std::is_void< detail::transform_invoke_result_t< F, const value_type && > >::value
2611 && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, const value_type && > >::value
2612 )
2613 >
2614 nsel_constexpr expected< detail::transform_invoke_result_t< F, const value_type && >, error_type > transform( F && f ) const &&
2615 {
2616 return has_value()
2617 ? expected< detail::transform_invoke_result_t< F, const value_type && >, error_type >( detail::invoke( std::forward< F >( f ), std::move( **this ) ) )
2618 : make_unexpected( std::move( error() ) );
2619 }
2620
2621 template<typename F
2622 nsel_REQUIRES_T(
2623 std::is_constructible< error_type, const error_type && >::value
2624 && std::is_void< detail::transform_invoke_result_t< F, const value_type && > >::value
2625 )
2626 >
2627 nsel_constexpr expected< void, error_type > transform( F && f ) const &&
2628 {
2629 return has_value()
2630 ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
2631 : make_unexpected( std::move( error() ) );
2632 }
2633#endif
2634
2635 template<typename F
2636 nsel_REQUIRES_T(
2637 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type & > >::value
2638 && std::is_constructible< value_type, value_type & >::value
2639 )
2640 >
2641 nsel_constexpr14 expected< value_type, detail::transform_invoke_result_t< F, error_type & > > transform_error( F && f ) &
2642 {
2643 return has_value()
2644 ? expected< value_type, detail::transform_invoke_result_t< F, error_type & > >( in_place, **this )
2645 : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
2646 }
2647
2648 template<typename F
2649 nsel_REQUIRES_T(
2650 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type & > >::value
2651 && std::is_constructible< value_type, const value_type & >::value
2652 )
2653 >
2654 nsel_constexpr expected< value_type, detail::transform_invoke_result_t< F, const error_type & > > transform_error( F && f ) const &
2655 {
2656 return has_value()
2657 ? expected< value_type, detail::transform_invoke_result_t< F, const error_type & > >( in_place, **this )
2658 : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
2659 }
2660
2661#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2662 template<typename F
2663 nsel_REQUIRES_T(
2664 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type && > >::value
2665 && std::is_constructible< value_type, value_type && >::value
2666 )
2667 >
2668 nsel_constexpr14 expected< value_type, detail::transform_invoke_result_t< F, error_type && > > transform_error( F && f ) &&
2669 {
2670 return has_value()
2671 ? expected< value_type, detail::transform_invoke_result_t< F, error_type && > >( in_place, std::move( **this ) )
2672 : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
2673 }
2674
2675 template<typename F
2676 nsel_REQUIRES_T(
2677 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type && > >::value
2678 && std::is_constructible< value_type, const value_type && >::value
2679 )
2680 >
2681 nsel_constexpr expected< value_type, detail::transform_invoke_result_t< F, const error_type && > > transform_error( F && f ) const &&
2682 {
2683 return has_value()
2684 ? expected< value_type, detail::transform_invoke_result_t< F, const error_type && > >( in_place, std::move( **this ) )
2685 : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
2686 }
2687#endif
2688#endif // nsel_P2505R >= 3
2689 // unwrap()
2690
2691// template <class U, class E>
2692// constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
2693
2694// template <class T, class E>
2695// constexpr expected<T,E> expected<T,E>::unwrap() const&;
2696
2697// template <class U, class E>
2698// expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
2699
2700// template <class T, class E>
2701// template expected<T,E> expected<T,E>::unwrap() &&;
2702
2703 // factories
2704
2705// template< typename Ex, typename F>
2706// expected<T,E> catch_exception(F&& f);
2707
2708// template< typename F>
2709// expected<decltype(func(declval<T>())),E> map(F&& func) ;
2710
2711// template< typename F>
2712// 'see below' bind(F&& func);
2713
2714// template< typename F>
2715// expected<T,E> catch_error(F&& f);
2716
2717// template< typename F>
2718// 'see below' then(F&& func);
2719
2720private:
2721 detail::storage_t
2722 <
2723 T
2724 ,E
2725 , std::is_copy_constructible<T>::value && std::is_copy_constructible<E>::value
2726 , std::is_move_constructible<T>::value && std::is_move_constructible<E>::value
2727 >
2728 contained;
2729};
2730
2732
2733template< typename E >
2734class nsel_NODISCARD expected< void, E >
2735{
2736private:
2737 template< typename, typename > friend class expected;
2738
2739public:
2740 using value_type = void;
2741 using error_type = E;
2742 using unexpected_type = nonstd::unexpected_type<E>;
2743
2744 // x.x.4.1 constructors
2745
2746 constexpr expected() noexcept
2747 : contained( true )
2748 {}
2749
2750 nsel_constexpr14 expected( expected const & other ) = default;
2751 nsel_constexpr14 expected( expected && other ) = default;
2752
2753 constexpr explicit expected( nonstd_lite_in_place_t(void) )
2754 : contained( true )
2755 {}
2756
2757 template< typename G = E
2758 nsel_REQUIRES_T(
2759 !std::is_convertible<G const &, E>::value /*=> explicit */
2760 )
2761 >
2762 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error )
2763 : contained( false )
2764 {
2765 contained.construct_error( E{ error.error() } );
2766 }
2767
2768 template< typename G = E
2769 nsel_REQUIRES_T(
2770 std::is_convertible<G const &, E>::value /*=> non-explicit */
2771 )
2772 >
2773 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error )
2774 : contained( false )
2775 {
2776 contained.construct_error( error.error() );
2777 }
2778
2779 template< typename G = E
2780 nsel_REQUIRES_T(
2781 !std::is_convertible<G&&, E>::value /*=> explicit */
2782 )
2783 >
2784 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error )
2785 : contained( false )
2786 {
2787 contained.construct_error( E{ std::move( error.error() ) } );
2788 }
2789
2790 template< typename G = E
2791 nsel_REQUIRES_T(
2792 std::is_convertible<G&&, E>::value /*=> non-explicit */
2793 )
2794 >
2795 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error )
2796 : contained( false )
2797 {
2798 contained.construct_error( std::move( error.error() ) );
2799 }
2800
2801 template< typename... Args
2802 nsel_REQUIRES_T(
2803 std::is_constructible<E, Args&&...>::value
2804 )
2805 >
2806 nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
2807 : contained( false )
2808 {
2809 contained.emplace_error( std::forward<Args>( args )... );
2810 }
2811
2812 template< typename U, typename... Args
2813 nsel_REQUIRES_T(
2814 std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
2815 )
2816 >
2817 nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
2818 : contained( false )
2819 {
2820 contained.emplace_error( il, std::forward<Args>( args )... );
2821 }
2822
2823 // destructor
2824
2825 ~expected()
2826 {
2827 if ( ! has_value() )
2828 {
2829 contained.destruct_error();
2830 }
2831 }
2832
2833 // x.x.4.3 assignment
2834
2835 expected & operator=( expected const & other )
2836 {
2837 expected( other ).swap( *this );
2838 return *this;
2839 }
2840
2841 expected & operator=( expected && other ) noexcept
2842 (
2843 std::is_nothrow_move_assignable<E>::value &&
2844 std::is_nothrow_move_constructible<E>::value )
2845 {
2846 expected( std::move( other ) ).swap( *this );
2847 return *this;
2848 }
2849
2850 void emplace()
2851 {
2852 expected().swap( *this );
2853 }
2854
2855 // x.x.4.4 swap
2856
2857 template< typename G = E >
2858 nsel_REQUIRES_R( void,
2859 std17::is_swappable<G>::value
2860 && std::is_move_constructible<G>::value
2861 )
2862 swap( expected & other ) noexcept
2863 (
2864 std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::value
2865 )
2866 {
2867 using std::swap;
2868
2869 if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
2870 else if ( bool(*this) && ! bool(other) ) { contained.construct_error( std::move( other.error() ) );
2871 bool has_value = contained.has_value();
2872 bool other_has_value = other.has_value();
2873 other.contained.set_has_value(has_value);
2874 contained.set_has_value(other_has_value);
2875 }
2876 else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
2877 }
2878
2879 // x.x.4.5 observers
2880
2881 constexpr explicit operator bool() const noexcept
2882 {
2883 return has_value();
2884 }
2885
2886 constexpr bool has_value() const noexcept
2887 {
2888 return contained.has_value();
2889 }
2890
2891 void value() const
2892 {
2893 if ( ! has_value() )
2894 {
2895 error_traits<error_type>::rethrow( contained.error() );
2896 }
2897 }
2898
2899 constexpr error_type const & error() const &
2900 {
2901 return assert( ! has_value() ), contained.error();
2902 }
2903
2904 error_type & error() &
2905 {
2906 return assert( ! has_value() ), contained.error();
2907 }
2908
2909#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2910
2911 constexpr error_type const && error() const &&
2912 {
2913 return std::move( ( assert( ! has_value() ), contained.error() ) );
2914 }
2915
2916 error_type && error() &&
2917 {
2918 return std::move( ( assert( ! has_value() ), contained.error() ) );
2919 }
2920
2921#endif
2922
2923 constexpr unexpected_type get_unexpected() const
2924 {
2925 return make_unexpected( contained.error() );
2926 }
2927
2928 template< typename Ex >
2929 bool has_exception() const
2930 {
2931 using ContainedEx = typename std::remove_reference< decltype( get_unexpected().error() ) >::type;
2932 return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
2933 }
2934
2935#if nsel_P2505R >= 4
2936 template< typename G = E
2937 nsel_REQUIRES_T(
2938 std::is_copy_constructible< E >::value
2939 && std::is_convertible< G, E >::value
2940 )
2941 >
2942 nsel_constexpr error_type error_or( G && e ) const &
2943 {
2944 return has_value()
2945 ? static_cast< E >( std::forward< G >( e ) )
2946 : contained.error();
2947 }
2948
2949 template< typename G = E
2950 nsel_REQUIRES_T(
2951 std::is_move_constructible< E >::value
2952 && std::is_convertible< G, E >::value
2953 )
2954 >
2955 nsel_constexpr14 error_type error_or( G && e ) &&
2956 {
2957 return has_value()
2958 ? static_cast< E >( std::forward< G >( e ) )
2959 : std::move( contained.error() );
2960 }
2961#endif // nsel_P2505R >= 4
2962
2963#if nsel_P2505R >= 3
2964 // Monadic operations (P2505)
2965 template<typename F
2966 nsel_REQUIRES_T(
2967 detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
2968 && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
2969 && std::is_constructible< error_type, error_type & >::value
2970 )
2971 >
2972 nsel_constexpr14 detail::invoke_result_nocvref_t< F > and_then( F && f ) &
2973 {
2974 return has_value()
2975 ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
2976 : detail::invoke_result_nocvref_t< F >( unexpect, error() );
2977 }
2978
2979 template<typename F
2980 nsel_REQUIRES_T(
2981 detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
2982 && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
2983 && std::is_constructible< error_type, const error_type & >::value
2984 )
2985 >
2986 nsel_constexpr detail::invoke_result_nocvref_t< F > and_then( F && f ) const &
2987 {
2988 return has_value()
2989 ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
2990 : detail::invoke_result_nocvref_t< F >( unexpect, error() );
2991 }
2992
2993#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2994 template<typename F
2995 nsel_REQUIRES_T(
2996 detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
2997 && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
2998 && std::is_constructible< error_type, error_type && >::value
2999 )
3000 >
3001 nsel_constexpr14 detail::invoke_result_nocvref_t< F > and_then( F && f ) &&
3002 {
3003 return has_value()
3004 ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
3005 : detail::invoke_result_nocvref_t< F >( unexpect, std::move( error() ) );
3006 }
3007
3008 template<typename F
3009 nsel_REQUIRES_T(
3010 detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
3011 && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
3012 && std::is_constructible< error_type, const error_type && >::value
3013 )
3014 >
3015 nsel_constexpr detail::invoke_result_nocvref_t< F > and_then( F && f ) const &&
3016 {
3017 return has_value()
3018 ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
3019 : detail::invoke_result_nocvref_t< F >( unexpect, std::move( error() ) );
3020 }
3021#endif
3022
3023 template<typename F
3024 nsel_REQUIRES_T(
3025 detail::is_expected< detail::invoke_result_nocvref_t< F, error_type & > >::value
3026 && std::is_void< typename detail::invoke_result_nocvref_t< F, error_type & >::value_type >::value
3027 )
3028 >
3029 nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type & > or_else( F && f ) &
3030 {
3031 return has_value()
3032 ? detail::invoke_result_nocvref_t< F, error_type & >()
3033 : detail::invoke_result_nocvref_t< F, error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
3034 }
3035
3036 template<typename F
3037 nsel_REQUIRES_T(
3038 detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type & > >::value
3039 && std::is_void< typename detail::invoke_result_nocvref_t< F, const error_type & >::value_type >::value
3040 )
3041 >
3042 nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type & > or_else( F && f ) const &
3043 {
3044 return has_value()
3045 ? detail::invoke_result_nocvref_t< F, const error_type & >()
3046 : detail::invoke_result_nocvref_t< F, const error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
3047 }
3048
3049#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
3050 template<typename F
3051 nsel_REQUIRES_T(
3052 detail::is_expected< detail::invoke_result_nocvref_t< F, error_type && > >::value
3053 && std::is_void< typename detail::invoke_result_nocvref_t< F, error_type && >::value_type >::value
3054 )
3055 >
3056 nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type && > or_else( F && f ) &&
3057 {
3058 return has_value()
3059 ? detail::invoke_result_nocvref_t< F, error_type && >()
3060 : detail::invoke_result_nocvref_t< F, error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
3061 }
3062
3063 template<typename F
3064 nsel_REQUIRES_T(
3065 detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type && > >::value
3066 && std::is_void< typename detail::invoke_result_nocvref_t< F, const error_type && >::value_type >::value
3067 )
3068 >
3069 nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type && > or_else( F && f ) const &&
3070 {
3071 return has_value()
3072 ? detail::invoke_result_nocvref_t< F, const error_type && >()
3073 : detail::invoke_result_nocvref_t< F, const error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
3074 }
3075#endif
3076
3077 template<typename F
3078 nsel_REQUIRES_T(
3079 std::is_constructible< error_type, error_type & >::value
3080 && !std::is_void< detail::transform_invoke_result_t< F > >::value
3081 )
3082 >
3083 nsel_constexpr14 expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) &
3084 {
3085 return has_value()
3086 ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
3087 : make_unexpected( error() );
3088 }
3089
3090 template<typename F
3091 nsel_REQUIRES_T(
3092 std::is_constructible< error_type, error_type & >::value
3093 && std::is_void< detail::transform_invoke_result_t< F > >::value
3094 )
3095 >
3096 nsel_constexpr14 expected< void, error_type > transform( F && f ) &
3097 {
3098 return has_value()
3099 ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
3100 : make_unexpected( error() );
3101 }
3102
3103 template<typename F
3104 nsel_REQUIRES_T(
3105 std::is_constructible< error_type, const error_type & >::value
3106 && !std::is_void< detail::transform_invoke_result_t< F > >::value
3107 )
3108 >
3109 nsel_constexpr expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) const &
3110 {
3111 return has_value()
3112 ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
3113 : make_unexpected( error() );
3114 }
3115
3116 template<typename F
3117 nsel_REQUIRES_T(
3118 std::is_constructible< error_type, const error_type & >::value
3119 && std::is_void< detail::transform_invoke_result_t< F > >::value
3120 )
3121 >
3122 nsel_constexpr expected< void, error_type > transform( F && f ) const &
3123 {
3124 return has_value()
3125 ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
3126 : make_unexpected( error() );
3127 }
3128
3129#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
3130 template<typename F
3131 nsel_REQUIRES_T(
3132 std::is_constructible< error_type, error_type && >::value
3133 && !std::is_void< detail::transform_invoke_result_t< F > >::value
3134 )
3135 >
3136 nsel_constexpr14 expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) &&
3137 {
3138 return has_value()
3139 ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
3140 : make_unexpected( error() );
3141 }
3142
3143 template<typename F
3144 nsel_REQUIRES_T(
3145 std::is_constructible< error_type, error_type && >::value
3146 && std::is_void< detail::transform_invoke_result_t< F > >::value
3147 )
3148 >
3149 nsel_constexpr14 expected< void, error_type > transform( F && f ) &&
3150 {
3151 return has_value()
3152 ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
3153 : make_unexpected( error() );
3154 }
3155
3156 template<typename F
3157 nsel_REQUIRES_T(
3158 std::is_constructible< error_type, const error_type && >::value
3159 && !std::is_void< detail::transform_invoke_result_t< F > >::value
3160 )
3161 >
3162 nsel_constexpr expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) const &&
3163 {
3164 return has_value()
3165 ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
3166 : make_unexpected( error() );
3167 }
3168
3169 template<typename F
3170 nsel_REQUIRES_T(
3171 std::is_constructible< error_type, const error_type && >::value
3172 && std::is_void< detail::transform_invoke_result_t< F > >::value
3173 )
3174 >
3175 nsel_constexpr expected< void, error_type > transform( F && f ) const &&
3176 {
3177 return has_value()
3178 ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
3179 : make_unexpected( error() );
3180 }
3181#endif
3182
3183 template<typename F
3184 nsel_REQUIRES_T(
3185 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type & > >::value
3186 )
3187 >
3188 nsel_constexpr14 expected< void, detail::transform_invoke_result_t< F, error_type & > > transform_error( F && f ) &
3189 {
3190 return has_value()
3191 ? expected< void, detail::transform_invoke_result_t< F, error_type & > >()
3192 : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
3193 }
3194
3195 template<typename F
3196 nsel_REQUIRES_T(
3197 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type & > >::value
3198 )
3199 >
3200 nsel_constexpr expected< void, detail::transform_invoke_result_t< F, const error_type & > > transform_error( F && f ) const &
3201 {
3202 return has_value()
3203 ? expected< void, detail::transform_invoke_result_t< F, const error_type & > >()
3204 : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
3205 }
3206
3207#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
3208 template<typename F
3209 nsel_REQUIRES_T(
3210 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type && > >::value
3211 )
3212 >
3213 nsel_constexpr14 expected< void, detail::transform_invoke_result_t< F, error_type && > > transform_error( F && f ) &&
3214 {
3215 return has_value()
3216 ? expected< void, detail::transform_invoke_result_t< F, error_type && > >()
3217 : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
3218 }
3219
3220 template<typename F
3221 nsel_REQUIRES_T(
3222 detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type && > >::value
3223 )
3224 >
3225 nsel_constexpr expected< void, detail::transform_invoke_result_t< F, const error_type && > > transform_error( F && f ) const &&
3226 {
3227 return has_value()
3228 ? expected< void, detail::transform_invoke_result_t< F, const error_type && > >()
3229 : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
3230 }
3231#endif
3232#endif // nsel_P2505R >= 3
3233
3234// template constexpr 'see below' unwrap() const&;
3235//
3236// template 'see below' unwrap() &&;
3237
3238 // factories
3239
3240// template< typename Ex, typename F>
3241// expected<void,E> catch_exception(F&& f);
3242//
3243// template< typename F>
3244// expected<decltype(func()), E> map(F&& func) ;
3245//
3246// template< typename F>
3247// 'see below' bind(F&& func) ;
3248//
3249// template< typename F>
3250// expected<void,E> catch_error(F&& f);
3251//
3252// template< typename F>
3253// 'see below' then(F&& func);
3254
3255private:
3256 detail::storage_t
3257 <
3258 void
3259 , E
3260 , std::is_copy_constructible<E>::value
3261 , std::is_move_constructible<E>::value
3262 >
3263 contained;
3264};
3265
3266// x.x.4.6 expected<>: comparison operators
3267
3268template< typename T1, typename E1, typename T2, typename E2
3269 nsel_REQUIRES_T(
3270 !std::is_void<T1>::value && !std::is_void<T2>::value
3271 )
3272>
3273constexpr bool operator==( expected<T1,E1> const & x, expected<T2,E2> const & y )
3274{
3275 return bool(x) != bool(y) ? false : bool(x) ? *x == *y : x.error() == y.error();
3276}
3277
3278template< typename T1, typename E1, typename T2, typename E2
3279 nsel_REQUIRES_T(
3280 std::is_void<T1>::value && std::is_void<T2>::value
3281 )
3282>
3283constexpr bool operator==( expected<T1,E1> const & x, expected<T2,E2> const & y )
3284{
3285 return bool(x) != bool(y) ? false : bool(x) || static_cast<bool>( x.error() == y.error() );
3286}
3287
3288template< typename T1, typename E1, typename T2, typename E2 >
3289constexpr bool operator!=( expected<T1,E1> const & x, expected<T2,E2> const & y )
3290{
3291 return !(x == y);
3292}
3293
3294#if nsel_P0323R <= 2
3295
3296template< typename T, typename E >
3297constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y )
3298{
3299 return (!y) ? false : (!x) ? true : *x < *y;
3300}
3301
3302template< typename T, typename E >
3303constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y )
3304{
3305 return (y < x);
3306}
3307
3308template< typename T, typename E >
3309constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y )
3310{
3311 return !(y < x);
3312}
3313
3314template< typename T, typename E >
3315constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y )
3316{
3317 return !(x < y);
3318}
3319
3320#endif
3321
3322// x.x.4.7 expected: comparison with T
3323
3324template< typename T1, typename E1, typename T2
3325 nsel_REQUIRES_T(
3326 !std::is_void<T1>::value
3327 )
3328>
3329constexpr bool operator==( expected<T1,E1> const & x, T2 const & v )
3330{
3331 return bool(x) ? *x == v : false;
3332}
3333
3334template< typename T1, typename E1, typename T2
3335 nsel_REQUIRES_T(
3336 !std::is_void<T1>::value
3337 )
3338>
3339constexpr bool operator==(T2 const & v, expected<T1,E1> const & x )
3340{
3341 return bool(x) ? v == *x : false;
3342}
3343
3344template< typename T1, typename E1, typename T2 >
3345constexpr bool operator!=( expected<T1,E1> const & x, T2 const & v )
3346{
3347 return bool(x) ? *x != v : true;
3348}
3349
3350template< typename T1, typename E1, typename T2 >
3351constexpr bool operator!=( T2 const & v, expected<T1,E1> const & x )
3352{
3353 return bool(x) ? v != *x : true;
3354}
3355
3356#if nsel_P0323R <= 2
3357
3358template< typename T, typename E >
3359constexpr bool operator<( expected<T,E> const & x, T const & v )
3360{
3361 return bool(x) ? *x < v : true;
3362}
3363
3364template< typename T, typename E >
3365constexpr bool operator<( T const & v, expected<T,E> const & x )
3366{
3367 return bool(x) ? v < *x : false;
3368}
3369
3370template< typename T, typename E >
3371constexpr bool operator>( T const & v, expected<T,E> const & x )
3372{
3373 return bool(x) ? *x < v : false;
3374}
3375
3376template< typename T, typename E >
3377constexpr bool operator>( expected<T,E> const & x, T const & v )
3378{
3379 return bool(x) ? v < *x : false;
3380}
3381
3382template< typename T, typename E >
3383constexpr bool operator<=( T const & v, expected<T,E> const & x )
3384{
3385 return bool(x) ? ! ( *x < v ) : false;
3386}
3387
3388template< typename T, typename E >
3389constexpr bool operator<=( expected<T,E> const & x, T const & v )
3390{
3391 return bool(x) ? ! ( v < *x ) : true;
3392}
3393
3394template< typename T, typename E >
3395constexpr bool operator>=( expected<T,E> const & x, T const & v )
3396{
3397 return bool(x) ? ! ( *x < v ) : false;
3398}
3399
3400template< typename T, typename E >
3401constexpr bool operator>=( T const & v, expected<T,E> const & x )
3402{
3403 return bool(x) ? ! ( v < *x ) : true;
3404}
3405
3406#endif // nsel_P0323R
3407
3408// x.x.4.8 expected: comparison with unexpected_type
3409
3410template< typename T1, typename E1 , typename E2 >
3411constexpr bool operator==( expected<T1,E1> const & x, unexpected_type<E2> const & u )
3412{
3413 return (!x) ? x.get_unexpected() == u : false;
3414}
3415
3416template< typename T1, typename E1 , typename E2 >
3417constexpr bool operator==( unexpected_type<E2> const & u, expected<T1,E1> const & x )
3418{
3419 return ( x == u );
3420}
3421
3422template< typename T1, typename E1 , typename E2 >
3423constexpr bool operator!=( expected<T1,E1> const & x, unexpected_type<E2> const & u )
3424{
3425 return ! ( x == u );
3426}
3427
3428template< typename T1, typename E1 , typename E2 >
3429constexpr bool operator!=( unexpected_type<E2> const & u, expected<T1,E1> const & x )
3430{
3431 return ! ( x == u );
3432}
3433
3434#if nsel_P0323R <= 2
3435
3436template< typename T, typename E >
3437constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u )
3438{
3439 return (!x) ? ( x.get_unexpected() < u ) : false;
3440}
3441
3442template< typename T, typename E >
3443constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x )
3444{
3445 return (!x) ? ( u < x.get_unexpected() ) : true ;
3446}
3447
3448template< typename T, typename E >
3449constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u )
3450{
3451 return ( u < x );
3452}
3453
3454template< typename T, typename E >
3455constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x )
3456{
3457 return ( x < u );
3458}
3459
3460template< typename T, typename E >
3461constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u )
3462{
3463 return ! ( u < x );
3464}
3465
3466template< typename T, typename E >
3467constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x)
3468{
3469 return ! ( x < u );
3470}
3471
3472template< typename T, typename E >
3473constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u )
3474{
3475 return ! ( u > x );
3476}
3477
3478template< typename T, typename E >
3479constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x )
3480{
3481 return ! ( x > u );
3482}
3483
3484#endif // nsel_P0323R
3485
3487
3488template< typename T, typename E
3489 nsel_REQUIRES_T(
3490 ( std::is_void<T>::value || std::is_move_constructible<T>::value )
3491 && std::is_move_constructible<E>::value
3492 && std17::is_swappable<T>::value
3493 && std17::is_swappable<E>::value )
3494>
3495void swap( expected<T,E> & x, expected<T,E> & y ) noexcept ( noexcept ( x.swap(y) ) )
3496{
3497 x.swap( y );
3498}
3499
3500#if nsel_P0323R <= 3
3501
3502template< typename T >
3503constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
3504{
3505 return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
3506}
3507
3508// expected<void> specialization:
3509
3510auto inline make_expected() -> expected<void>
3511{
3512 return expected<void>( in_place );
3513}
3514
3515template< typename T >
3516constexpr auto make_expected_from_current_exception() -> expected<T>
3517{
3518 return expected<T>( make_unexpected_from_current_exception() );
3519}
3520
3521template< typename T >
3522auto make_expected_from_exception( std::exception_ptr v ) -> expected<T>
3523{
3524 return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) );
3525}
3526
3527template< typename T, typename E >
3528constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
3529{
3530 return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
3531}
3532
3533template< typename F
3534 nsel_REQUIRES_T( ! std::is_same<typename std::result_of<F()>::type, void>::value )
3535>
3536/*nsel_constexpr14*/
3537auto make_expected_from_call( F f ) -> expected< typename std::result_of<F()>::type >
3538{
3539 try
3540 {
3541 return make_expected( f() );
3542 }
3543 catch (...)
3544 {
3545 return make_unexpected_from_current_exception();
3546 }
3547}
3548
3549template< typename F
3550 nsel_REQUIRES_T( std::is_same<typename std::result_of<F()>::type, void>::value )
3551>
3552/*nsel_constexpr14*/
3553auto make_expected_from_call( F f ) -> expected<void>
3554{
3555 try
3556 {
3557 f();
3558 return make_expected();
3559 }
3560 catch (...)
3561 {
3562 return make_unexpected_from_current_exception();
3563 }
3564}
3565
3566#endif // nsel_P0323R
3567
3568} // namespace expected_lite
3569
3570using namespace expected_lite;
3571
3572// using expected_lite::expected;
3573// using ...
3574
3575} // namespace nonstd
3576
3577namespace std {
3578
3579// expected: hash support
3580
3581template< typename T, typename E >
3582struct hash< nonstd::expected<T,E> >
3583{
3584 using result_type = std::size_t;
3585 using argument_type = nonstd::expected<T,E>;
3586
3587 constexpr result_type operator()(argument_type const & arg) const
3588 {
3589 return arg ? std::hash<T>{}(*arg) : result_type{};
3590 }
3591};
3592
3593// TBD - ?? remove? see spec.
3594template< typename T, typename E >
3595struct hash< nonstd::expected<T&,E> >
3596{
3597 using result_type = std::size_t;
3598 using argument_type = nonstd::expected<T&,E>;
3599
3600 constexpr result_type operator()(argument_type const & arg) const
3601 {
3602 return arg ? std::hash<T>{}(*arg) : result_type{};
3603 }
3604};
3605
3606// TBD - implement
3607// bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true;
3608// otherwise it evaluates to an unspecified value if E is exception_ptr or
3609// a combination of hashing false and hash<E>()(e.error()).
3610
3611template< typename E >
3612struct hash< nonstd::expected<void,E> >
3613{
3614};
3615
3616} // namespace std
3617
3618namespace nonstd {
3619
3620// void unexpected() is deprecated && removed in C++17
3621
3622#if nsel_CPP17_OR_GREATER || nsel_COMPILER_MSVC_VERSION > 141
3623template< typename E >
3624using unexpected = unexpected_type<E>;
3625#endif
3626
3627} // namespace nonstd
3628
3629#undef nsel_REQUIRES
3630#undef nsel_REQUIRES_0
3631#undef nsel_REQUIRES_T
3632
3633nsel_RESTORE_WARNINGS()
3634
3635#endif // nsel_USES_STD_EXPECTED
3636
3637#endif // NONSTD_EXPECTED_LITE_HPP
void error(const char *msg)
Send error message to std::cerr.
Definition logging_utils.cpp:33
std::is_same< bool_pack< true, Bs... >, bool_pack< Bs..., true > > conjunction
Definition traits.hpp:19
Definition expected.hpp:190
in_place_t in_place_type(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())
Definition expected.hpp:216
in_place_t in_place_index(detail::in_place_index_tag< K >=detail::in_place_index_tag< K >())
Definition expected.hpp:222
in_place_t in_place(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())
Definition expected.hpp:204
STL namespace.
Definition expected.hpp:197
Definition expected.hpp:194
Definition expected.hpp:201
std::size_t result_type
Definition expected.hpp:3584
nonstd::expected< T, E > argument_type
Definition expected.hpp:3585
constexpr result_type operator()(argument_type const &arg) const
Definition expected.hpp:3587
nonstd::expected< T &, E > argument_type
Definition expected.hpp:3598
std::size_t result_type
Definition expected.hpp:3597
constexpr result_type operator()(argument_type const &arg) const
Definition expected.hpp:3600