RESTinio
expected.hpp
Go to the documentation of this file.
1// This version targets C++11 and later.
2//
3// Copyright (C) 2016-2018 Martin Moene.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7//
8// expected lite is based on:
9// A proposal to add a utility class to represent expected monad
10// by Vicente J. Botet Escriba and Pierre Talbot. http:://wg21.link/p0323
11
12#ifndef NONSTD_EXPECTED_LITE_HPP
13#define NONSTD_EXPECTED_LITE_HPP
14
15#define expected_lite_MAJOR 0
16#define expected_lite_MINOR 4
17#define expected_lite_PATCH 0
18
19#define expected_lite_VERSION expected_STRINGIFY(expected_lite_MAJOR) "." expected_STRINGIFY(expected_lite_MINOR) "." expected_STRINGIFY(expected_lite_PATCH)
20
21#define expected_STRINGIFY( x ) expected_STRINGIFY_( x )
22#define expected_STRINGIFY_( x ) #x
23
24// expected-lite configuration:
25
26#define nsel_EXPECTED_DEFAULT 0
27#define nsel_EXPECTED_NONSTD 1
28#define nsel_EXPECTED_STD 2
29
30#if !defined( nsel_CONFIG_SELECT_EXPECTED )
31# define nsel_CONFIG_SELECT_EXPECTED ( nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD )
32#endif
33
34// Proposal revisions:
35//
36// DXXXXR0: --
37// N4015 : -2 (2014-05-26)
38// N4109 : -1 (2014-06-29)
39// P0323R0: 0 (2016-05-28)
40// P0323R1: 1 (2016-10-12)
41// -------:
42// P0323R2: 2 (2017-06-15)
43// P0323R3: 3 (2017-10-15)
44// P0323R4: 4 (2017-11-26)
45// P0323R5: 5 (2018-02-08)
46// P0323R6: 6 (2018-04-02)
47// P0323R7: 7 (2018-06-22) *
48//
49// expected-lite uses 2 and higher
50
51#ifndef nsel_P0323R
52# define nsel_P0323R 7
53#endif
54
55// Control presence of exception handling (try and auto discover):
56
57#ifndef nsel_CONFIG_NO_EXCEPTIONS
58# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
59# define nsel_CONFIG_NO_EXCEPTIONS 0
60# else
61# define nsel_CONFIG_NO_EXCEPTIONS 1
62# endif
63#endif
64
65// C++ language version detection (C++20 is speculative):
66// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
67
68#ifndef nsel_CPLUSPLUS
69# if defined(_MSVC_LANG ) && !defined(__clang__)
70# define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
71# else
72# define nsel_CPLUSPLUS __cplusplus
73# endif
74#endif
75
76#define nsel_CPP98_OR_GREATER ( nsel_CPLUSPLUS >= 199711L )
77#define nsel_CPP11_OR_GREATER ( nsel_CPLUSPLUS >= 201103L )
78#define nsel_CPP14_OR_GREATER ( nsel_CPLUSPLUS >= 201402L )
79#define nsel_CPP17_OR_GREATER ( nsel_CPLUSPLUS >= 201703L )
80#define nsel_CPP20_OR_GREATER ( nsel_CPLUSPLUS >= 202000L )
81
82// Use C++20 std::expected if available and requested:
83
84#if nsel_CPP20_OR_GREATER && defined(__has_include )
85# if __has_include( <expected> )
86# define nsel_HAVE_STD_EXPECTED 1
87# else
88# define nsel_HAVE_STD_EXPECTED 0
89# endif
90#else
91# define nsel_HAVE_STD_EXPECTED 0
92#endif
93
94#define nsel_USES_STD_EXPECTED ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) )
95
96//
97// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
98//
99
100#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
101#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
102
103// C++17 std::in_place in <utility>:
104
105#if nsel_CPP17_OR_GREATER
106
107#include <utility>
108
109namespace nonstd {
110
111using std::in_place;
114using std::in_place_t;
115using std::in_place_type_t;
116using std::in_place_index_t;
117
118#define nonstd_lite_in_place_t( T) std::in_place_t
119#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
120#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
121
122#define nonstd_lite_in_place( T) std::in_place_t{}
123#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
124#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
125
126} // namespace nonstd
127
128#else // nsel_CPP17_OR_GREATER
129
130#include <cstddef>
131
132namespace nonstd {
133namespace detail {
134
135template< class T >
137
138template< std::size_t K >
140
141} // namespace detail
142
143struct in_place_t {};
144
145template< class T >
147{
148 return in_place_t();
149}
150
151template< std::size_t K >
153{
154 return in_place_t();
155}
156
157template< class T >
159{
160 return in_place_t();
161}
162
163template< std::size_t K >
165{
166 return in_place_t();
167}
168
169// mimic templated typedef:
170
171#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
172#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
173#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
174
175#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
176#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
177#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
178
179} // namespace nonstd
180
181#endif // nsel_CPP17_OR_GREATER
182#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
183
184//
185// Using std::expected:
186//
187
188#if nsel_USES_STD_EXPECTED
189
190#include <expected>
191
192namespace nonstd {
193
194 using std::expected;
195// ...
196}
197
198#else // nsel_USES_STD_EXPECTED
199
200#include <cassert>
201#include <exception>
202#include <functional>
203#include <initializer_list>
204#include <memory>
205#include <new>
206#include <system_error>
207#include <type_traits>
208#include <utility>
209
210// additional includes:
211
212#if nsel_CONFIG_NO_EXCEPTIONS
213// already included: <cassert>
214#else
215# include <stdexcept>
216#endif
217
218// C++ feature usage:
219
220#if nsel_CPP11_OR_GREATER
221# define nsel_constexpr constexpr
222#else
223# define nsel_constexpr /*constexpr*/
224#endif
225
226#if nsel_CPP14_OR_GREATER
227# define nsel_constexpr14 constexpr
228#else
229# define nsel_constexpr14 /*constexpr*/
230#endif
231
232#if nsel_CPP17_OR_GREATER
233# define nsel_inline17 inline
234#else
235# define nsel_inline17 /*inline*/
236#endif
237
238// Compiler versions:
239//
240// MSVC++ 6.0 _MSC_VER == 1200 nsel_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
241// MSVC++ 7.0 _MSC_VER == 1300 nsel_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
242// MSVC++ 7.1 _MSC_VER == 1310 nsel_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
243// MSVC++ 8.0 _MSC_VER == 1400 nsel_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
244// MSVC++ 9.0 _MSC_VER == 1500 nsel_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
245// MSVC++ 10.0 _MSC_VER == 1600 nsel_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
246// MSVC++ 11.0 _MSC_VER == 1700 nsel_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
247// MSVC++ 12.0 _MSC_VER == 1800 nsel_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
248// MSVC++ 14.0 _MSC_VER == 1900 nsel_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
249// MSVC++ 14.1 _MSC_VER >= 1910 nsel_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
250// MSVC++ 14.2 _MSC_VER >= 1920 nsel_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
251
252#if defined(_MSC_VER) && !defined(__clang__)
253# define nsel_COMPILER_MSVC_VER (_MSC_VER )
254# define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) )
255#else
256# define nsel_COMPILER_MSVC_VER 0
257# define nsel_COMPILER_MSVC_VERSION 0
258#endif
259
260#define nsel_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
261
262#if defined(__clang__)
263# define nsel_COMPILER_CLANG_VERSION nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
264#else
265# define nsel_COMPILER_CLANG_VERSION 0
266#endif
267
268#if defined(__GNUC__) && !defined(__clang__)
269# define nsel_COMPILER_GNUC_VERSION nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
270#else
271# define nsel_COMPILER_GNUC_VERSION 0
272#endif
273
274// half-open range [lo..hi):
275//#define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
276
277// Method enabling
278
279#define nsel_REQUIRES_0(...) \
280 template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
281
282#define nsel_REQUIRES_T(...) \
283 , typename std::enable_if< (__VA_ARGS__), int >::type = 0
284
285#define nsel_REQUIRES_R(R, ...) \
286 typename std::enable_if< (__VA_ARGS__), R>::type
287
288#define nsel_REQUIRES_A(...) \
289 , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
290
291// Presence of language and library features:
292
293#ifdef _HAS_CPP0X
294# define nsel_HAS_CPP0X _HAS_CPP0X
295#else
296# define nsel_HAS_CPP0X 0
297#endif
298
299//#define nsel_CPP11_140 (nsel_CPP11_OR_GREATER || nsel_COMPILER_MSVC_VER >= 1900)
300
301// Clang, GNUC, MSVC warning suppression macros:
302
303#ifdef __clang__
304# pragma clang diagnostic push
305#elif defined __GNUC__
306# pragma GCC diagnostic push
307#endif // __clang__
308
309#if nsel_COMPILER_MSVC_VERSION >= 140
310# pragma warning( push )
311# define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(disable: codes) )
312#else
313# define nsel_DISABLE_MSVC_WARNINGS(codes)
314#endif
315
316#ifdef __clang__
317# define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
318#elif defined __GNUC__
319# define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
320#elif nsel_COMPILER_MSVC_VERSION >= 140
321# define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) )
322#else
323# define nsel_RESTORE_WARNINGS()
324#endif
325
326// Suppress the following MSVC (GSL) warnings:
327// - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11)
328
330
331//
332// expected:
333//
334
335namespace nonstd { namespace expected_lite {
336
337// type traits C++17:
338
339namespace std17 {
340
341#if nsel_CPP17_OR_GREATER
342
343using std::conjunction;
344using std::is_swappable;
345using std::is_nothrow_swappable;
346
347#else // nsel_CPP17_OR_GREATER
348
349namespace detail {
350
351using std::swap;
352
353struct is_swappable
354{
355 template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
356 static std::true_type test( int /* unused */);
357
358 template< typename >
359 static std::false_type test(...);
360};
361
362struct is_nothrow_swappable
363{
364 // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
365
366 template< typename T >
367 static constexpr bool satisfies()
368 {
369 return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
370 }
371
372 template< typename T >
373 static auto test( int ) -> std::integral_constant<bool, satisfies<T>()>{}
374
375 template< typename >
376 static auto test(...) -> std::false_type;
377};
378} // namespace detail
379
380// is [nothow] swappable:
381
382template< typename T >
383struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
384
385template< typename T >
386struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
387
388// conjunction:
389
390template< typename... > struct conjunction : std::true_type{};
391template< typename B1 > struct conjunction<B1> : B1{};
392
393template< typename B1, typename... Bn >
394struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type{};
395
396#endif // nsel_CPP17_OR_GREATER
397
398} // namespace std17
399
400// type traits C++20:
401
402namespace std20 {
403
404#if nsel_CPP20_OR_GREATER
405
406using std::remove_cvref;
407
408#else
409
410template< typename T >
411struct remove_cvref
412{
413 typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
414};
415
416#endif
417
418} // namespace std20
419
420// forward declaration:
421
422template< typename T, typename E >
423class expected;
424
425namespace detail {
426
428
429template< typename T, typename E >
430class storage_t_impl
431{
432 template< typename, typename > friend class nonstd::expected_lite::expected;
433
434public:
435 using value_type = T;
436 using error_type = E;
437
438 // no-op construction
439 storage_t_impl() {}
440 ~storage_t_impl() {}
441
442 explicit storage_t_impl( bool has_value )
443 : m_has_value( has_value )
444 {}
445
446 void construct_value( value_type const & e )
447 {
448 new( &m_value ) value_type( e );
449 }
450
451 void construct_value( value_type && e )
452 {
453 new( &m_value ) value_type( std::move( e ) );
454 }
455
456 template< class... Args >
457 void emplace_value( Args&&... args )
458 {
459 new( &m_value ) value_type( std::forward<Args>(args)...);
460 }
461
462 template< class U, class... Args >
463 void emplace_value( std::initializer_list<U> il, Args&&... args )
464 {
465 new( &m_value ) value_type( il, std::forward<Args>(args)... );
466 }
467
468 void destruct_value()
469 {
470 m_value.~value_type();
471 }
472
473 void construct_error( error_type const & e )
474 {
475 new( &m_error ) error_type( e );
476 }
477
478 void construct_error( error_type && e )
479 {
480 new( &m_error ) error_type( std::move( e ) );
481 }
482
483 template< class... Args >
484 void emplace_error( Args&&... args )
485 {
486 new( &m_error ) error_type( std::forward<Args>(args)...);
487 }
488
489 template< class U, class... Args >
490 void emplace_error( std::initializer_list<U> il, Args&&... args )
491 {
492 new( &m_error ) error_type( il, std::forward<Args>(args)... );
493 }
494
495 void destruct_error()
496 {
497 m_error.~error_type();
498 }
499
500 constexpr value_type const & value() const &
501 {
502 return m_value;
503 }
504
505 value_type & value() &
506 {
507 return m_value;
508 }
509
510 constexpr value_type const && value() const &&
511 {
512 return std::move( m_value );
513 }
514
515 nsel_constexpr14 value_type && value() &&
516 {
517 return std::move( m_value );
518 }
519
520 value_type const * value_ptr() const
521 {
522 return &m_value;
523 }
524
525 value_type * value_ptr()
526 {
527 return &m_value;
528 }
529
530 error_type const & error() const &
531 {
532 return m_error;
533 }
534
535 error_type & error() &
536 {
537 return m_error;
538 }
539
540 constexpr error_type const && error() const &&
541 {
542 return std::move( m_error );
543 }
544
545 nsel_constexpr14 error_type && error() &&
546 {
547 return std::move( m_error );
548 }
549
550 bool has_value() const
551 {
552 return m_has_value;
553 }
554
555 void set_has_value( bool v )
556 {
557 m_has_value = v;
558 }
559
560private:
561 union
562 {
563 value_type m_value;
564 error_type m_error;
565 };
566
567 bool m_has_value = false;
568};
569
571
572template< typename E >
573struct storage_t_impl<void, E>
574{
575 template< typename, typename > friend class nonstd::expected_lite::expected;
576
577public:
578 using value_type = void;
579 using error_type = E;
580
581 // no-op construction
582 storage_t_impl() {}
583 ~storage_t_impl() {}
584
585 explicit storage_t_impl( bool has_value )
586 : m_has_value( has_value )
587 {}
588
589 void construct_error( error_type const & e )
590 {
591 new( &m_error ) error_type( e );
592 }
593
594 void construct_error( error_type && e )
595 {
596 new( &m_error ) error_type( std::move( e ) );
597 }
598
599 template< class... Args >
600 void emplace_error( Args&&... args )
601 {
602 new( &m_error ) error_type( std::forward<Args>(args)...);
603 }
604
605 template< class U, class... Args >
606 void emplace_error( std::initializer_list<U> il, Args&&... args )
607 {
608 new( &m_error ) error_type( il, std::forward<Args>(args)... );
609 }
610
611 void destruct_error()
612 {
613 m_error.~error_type();
614 }
615
616 error_type const & error() const &
617 {
618 return m_error;
619 }
620
621 error_type & error() &
622 {
623 return m_error;
624 }
625
626 constexpr error_type const && error() const &&
627 {
628 return std::move( m_error );
629 }
630
631 nsel_constexpr14 error_type && error() &&
632 {
633 return std::move( m_error );
634 }
635
636 bool has_value() const
637 {
638 return m_has_value;
639 }
640
641 void set_has_value( bool v )
642 {
643 m_has_value = v;
644 }
645
646private:
647 union
648 {
649 char m_dummy;
650 error_type m_error;
651 };
652
653 bool m_has_value = false;
654};
655
656template< typename T, typename E, bool isConstructable, bool isMoveable >
657class storage_t
658{
659public:
660 storage_t() = default;
661 ~storage_t() = default;
662
663 explicit storage_t( bool has_value )
664 : storage_t_impl<T, E>( has_value )
665 {}
666
667 storage_t( storage_t const & other ) = delete;
668 storage_t( storage_t && other ) = delete;
669};
670
671template< typename T, typename E >
672class storage_t<T, E, true, true> : public storage_t_impl<T, E>
673{
674public:
675 storage_t() = default;
676 ~storage_t() = default;
677
678 explicit storage_t( bool has_value )
679 : storage_t_impl<T, E>( has_value )
680 {}
681
682 storage_t( storage_t const & other )
683 : storage_t_impl<T, E>( other.has_value() )
684 {
685 if ( this->has_value() ) this->construct_value( other.value() );
686 else this->construct_error( other.error() );
687 }
688
689 storage_t(storage_t && other )
690 : storage_t_impl<T, E>( other.has_value() )
691 {
692 if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
693 else this->construct_error( std::move( other.error() ) );
694 }
695};
696
697template< typename E >
698class storage_t<void, E, true, true> : public storage_t_impl<void, E>
699{
700public:
701 storage_t() = default;
702 ~storage_t() = default;
703
704 explicit storage_t( bool has_value )
705 : storage_t_impl<void, E>( has_value )
706 {}
707
708 storage_t( storage_t const & other )
709 : storage_t_impl<void, E>( other.has_value() )
710 {
711 if ( this->has_value() ) ;
712 else this->construct_error( other.error() );
713 }
714
715 storage_t(storage_t && other )
716 : storage_t_impl<void, E>( other.has_value() )
717 {
718 if ( this->has_value() ) ;
719 else this->construct_error( std::move( other.error() ) );
720 }
721};
722
723template< typename T, typename E >
724class storage_t<T, E, true, false> : public storage_t_impl<T, E>
725{
726public:
727 storage_t() = default;
728 ~storage_t() = default;
729
730 explicit storage_t( bool has_value )
731 : storage_t_impl<T, E>( has_value )
732 {}
733
734 storage_t( storage_t const & other )
735 : storage_t_impl<T, E>(other.has_value())
736 {
737 if ( this->has_value() ) this->construct_value( other.value() );
738 else this->construct_error( other.error() );
739 }
740
741 storage_t( storage_t && other ) = delete;
742};
743
744template< typename E >
745class storage_t<void, E, true, false> : public storage_t_impl<void, E>
746{
747public:
748 storage_t() = default;
749 ~storage_t() = default;
750
751 explicit storage_t( bool has_value )
752 : storage_t_impl<void, E>( has_value )
753 {}
754
755 storage_t( storage_t const & other )
756 : storage_t_impl<void, E>(other.has_value())
757 {
758 if ( this->has_value() ) ;
759 else this->construct_error( other.error() );
760 }
761
762 storage_t( storage_t && other ) = delete;
763};
764
765template< typename T, typename E >
766class storage_t<T, E, false, true> : public storage_t_impl<T, E>
767{
768public:
769 storage_t() = default;
770 ~storage_t() = default;
771
772 explicit storage_t( bool has_value )
773 : storage_t_impl<T, E>( has_value )
774 {}
775
776 storage_t( storage_t const & other ) = delete;
777
778 storage_t( storage_t && other )
779 : storage_t_impl<T, E>( other.has_value() )
780 {
781 if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
782 else this->construct_error( std::move( other.error() ) );
783 }
784};
785
786template< typename E >
787class storage_t<void, E, false, true> : public storage_t_impl<void, E>
788{
789public:
790 storage_t() = default;
791 ~storage_t() = default;
792
793 explicit storage_t( bool has_value )
794 : storage_t_impl<void, E>( has_value )
795 {}
796
797 storage_t( storage_t const & other ) = delete;
798
799 storage_t( storage_t && other )
800 : storage_t_impl<void, E>( other.has_value() )
801 {
802 if ( this->has_value() ) ;
803 else this->construct_error( std::move( other.error() ) );
804 }
805};
806
807} // namespace detail
808
810
811#if nsel_P0323R <= 2
812template< typename E = std::exception_ptr >
813class unexpected_type
814#else
815template< typename E >
816class unexpected_type
817#endif // nsel_P0323R
818{
819public:
820 using error_type = E;
821
822 // x.x.5.2.1 Constructors
823
824// unexpected_type() = delete;
825
826 constexpr unexpected_type( unexpected_type const & ) = default;
827 constexpr unexpected_type( unexpected_type && ) = default;
828
829 template< typename... Args
831 std::is_constructible<E, Args&&...>::value
832 )
833 >
834 constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), Args &&... args )
835 : m_error( std::forward<Args>( args )...)
836 {}
837
838 template< typename U, typename... Args
840 std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
841 )
842 >
843 constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), std::initializer_list<U> il, Args &&... args )
844 : m_error( il, std::forward<Args>( args )...)
845 {}
846
847 template< typename E2
849 std::is_constructible<E,E2>::value
850 && !std::is_same< typename std20::remove_cvref<E2>::type, nonstd_lite_in_place_t(E2) >::value
851 && !std::is_same< typename std20::remove_cvref<E2>::type, unexpected_type >::value
852 )
853 >
854 constexpr explicit unexpected_type( E2 && error )
855 : m_error( std::forward<E2>( error ) )
856 {}
857
858 template< typename E2
860 std::is_constructible< E, E2>::value
861 && !std::is_constructible<E, unexpected_type<E2> & >::value
862 && !std::is_constructible<E, unexpected_type<E2> >::value
863 && !std::is_constructible<E, unexpected_type<E2> const & >::value
864 && !std::is_constructible<E, unexpected_type<E2> const >::value
865 && !std::is_convertible< unexpected_type<E2> &, E>::value
866 && !std::is_convertible< unexpected_type<E2> , E>::value
867 && !std::is_convertible< unexpected_type<E2> const &, E>::value
868 && !std::is_convertible< unexpected_type<E2> const , E>::value
869 && !std::is_convertible< E2 const &, E>::value /*=> explicit */
870 )
871 >
872 constexpr explicit unexpected_type( unexpected_type<E2> const & error )
873 : m_error( E{ error.value() } )
874 {}
875
876 template< typename E2
878 std::is_constructible< E, E2>::value
879 && !std::is_constructible<E, unexpected_type<E2> & >::value
880 && !std::is_constructible<E, unexpected_type<E2> >::value
881 && !std::is_constructible<E, unexpected_type<E2> const & >::value
882 && !std::is_constructible<E, unexpected_type<E2> const >::value
883 && !std::is_convertible< unexpected_type<E2> &, E>::value
884 && !std::is_convertible< unexpected_type<E2> , E>::value
885 && !std::is_convertible< unexpected_type<E2> const &, E>::value
886 && !std::is_convertible< unexpected_type<E2> const , E>::value
887 && std::is_convertible< E2 const &, E>::value /*=> explicit */
888 )
889 >
890 constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> const & error )
891 : m_error( error.value() )
892 {}
893
894 template< typename E2
896 std::is_constructible< E, E2>::value
897 && !std::is_constructible<E, unexpected_type<E2> & >::value
898 && !std::is_constructible<E, unexpected_type<E2> >::value
899 && !std::is_constructible<E, unexpected_type<E2> const & >::value
900 && !std::is_constructible<E, unexpected_type<E2> const >::value
901 && !std::is_convertible< unexpected_type<E2> &, E>::value
902 && !std::is_convertible< unexpected_type<E2> , E>::value
903 && !std::is_convertible< unexpected_type<E2> const &, E>::value
904 && !std::is_convertible< unexpected_type<E2> const , E>::value
905 && !std::is_convertible< E2 const &, E>::value /*=> explicit */
906 )
907 >
908 constexpr explicit unexpected_type( unexpected_type<E2> && error )
909 : m_error( E{ std::move( error.value() ) } )
910 {}
911
912 template< typename E2
914 std::is_constructible< E, E2>::value
915 && !std::is_constructible<E, unexpected_type<E2> & >::value
916 && !std::is_constructible<E, unexpected_type<E2> >::value
917 && !std::is_constructible<E, unexpected_type<E2> const & >::value
918 && !std::is_constructible<E, unexpected_type<E2> const >::value
919 && !std::is_convertible< unexpected_type<E2> &, E>::value
920 && !std::is_convertible< unexpected_type<E2> , E>::value
921 && !std::is_convertible< unexpected_type<E2> const &, E>::value
922 && !std::is_convertible< unexpected_type<E2> const , E>::value
923 && std::is_convertible< E2 const &, E>::value /*=> non-explicit */
924 )
925 >
926 constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> && error )
927 : m_error( std::move( error.value() ) )
928 {}
929
930 // x.x.5.2.2 Assignment
931
932 nsel_constexpr14 unexpected_type& operator=( unexpected_type const & ) = default;
933 nsel_constexpr14 unexpected_type& operator=( unexpected_type && ) = default;
934
935 template< typename E2 = E >
936 nsel_constexpr14 unexpected_type & operator=( unexpected_type<E2> const & other )
937 {
938 unexpected_type{ other.value() }.swap( *this );
939 return *this;
940 }
941
942 template< typename E2 = E >
943 nsel_constexpr14 unexpected_type & operator=( unexpected_type<E2> && other )
944 {
945 unexpected_type{ std::move( other.value() ) }.swap( *this );
946 return *this;
947 }
948
949 // x.x.5.2.3 Observers
950
951 nsel_constexpr14 E & value() & noexcept
952 {
953 return m_error;
954 }
955
956 constexpr E const & value() const & noexcept
957 {
958 return m_error;
959 }
960
961#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
962
963 nsel_constexpr14 E && value() && noexcept
964 {
965 return std::move( m_error );
966 }
967
968 constexpr E const && value() const && noexcept
969 {
970 return std::move( m_error );
971 }
972
973#endif
974
975 // x.x.5.2.4 Swap
976
977 nsel_REQUIRES_R( void,
978 std17::is_swappable<E>::value
979 )
980 swap( unexpected_type & other ) noexcept (
981 std17::is_nothrow_swappable<E>::value
982 )
983 {
984 using std::swap;
985 swap( m_error, other.m_error );
986 }
987
988 // TODO: ??? unexpected_type: in-class friend operator==, !=
989
990private:
991 error_type m_error;
992};
993
994#if nsel_CPP17_OR_GREATER
995
997
998template< typename E >
999unexpected_type( E ) -> unexpected_type< E >;
1000
1001#endif
1002
1004
1005#if !nsel_CONFIG_NO_EXCEPTIONS
1006#if nsel_P0323R <= 2
1007
1008// TODO: Should expected be specialized for particular E types such as exception_ptr and how?
1009// See p0323r7 2.1. Ergonomics, http://wg21.link/p0323
1010template<>
1011class unexpected_type< std::exception_ptr >
1012{
1013public:
1014 using error_type = std::exception_ptr;
1015
1016 unexpected_type() = delete;
1017
1018 ~unexpected_type(){}
1019
1020 explicit unexpected_type( std::exception_ptr const & error )
1021 : m_error( error )
1022 {}
1023
1024 explicit unexpected_type(std::exception_ptr && error )
1025 : m_error( std::move( error ) )
1026 {}
1027
1028 template< typename E >
1029 explicit unexpected_type( E error )
1030 : m_error( std::make_exception_ptr( error ) )
1031 {}
1032
1033 std::exception_ptr const & value() const
1034 {
1035 return m_error;
1036 }
1037
1038 std::exception_ptr & value()
1039 {
1040 return m_error;
1041 }
1042
1043private:
1044 std::exception_ptr m_error;
1045};
1046
1047#endif // nsel_P0323R
1048#endif // !nsel_CONFIG_NO_EXCEPTIONS
1049
1051
1052template< typename E1, typename E2 >
1053constexpr bool operator==( unexpected_type<E1> const & x, unexpected_type<E2> const & y )
1054{
1055 return x.value() == y.value();
1056}
1057
1058template< typename E1, typename E2 >
1059constexpr bool operator!=( unexpected_type<E1> const & x, unexpected_type<E2> const & y )
1060{
1061 return ! ( x == y );
1062}
1063
1064#if nsel_P0323R <= 2
1065
1066template< typename E >
1067constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y )
1068{
1069 return x.value() < y.value();
1070}
1071
1072template< typename E >
1073constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y )
1074{
1075 return ( y < x );
1076}
1077
1078template< typename E >
1079constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y )
1080{
1081 return ! ( y < x );
1082}
1083
1084template< typename E >
1085constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y )
1086{
1087 return ! ( x < y );
1088}
1089
1090#endif // nsel_P0323R
1091
1093
1094template< typename E
1096 std17::is_swappable<E>::value
1097 )
1098>
1099void swap( unexpected_type<E> & x, unexpected_type<E> & y) noexcept ( noexcept ( x.swap(y) ) )
1100{
1101 x.swap( y );
1102}
1103
1104#if nsel_P0323R <= 2
1105
1106// unexpected: relational operators for std::exception_ptr:
1107
1108inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
1109{
1110 return false;
1111}
1112
1113inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
1114{
1115 return false;
1116}
1117
1118inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
1119{
1120 return ( x == y );
1121}
1122
1123inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
1124{
1125 return ( x == y );
1126}
1127
1128#endif // nsel_P0323R
1129
1130// unexpected: traits
1131
1132#if nsel_P0323R <= 3
1133
1134template< typename E>
1135struct is_unexpected : std::false_type {};
1136
1137template< typename E>
1138struct is_unexpected< unexpected_type<E> > : std::true_type {};
1139
1140#endif // nsel_P0323R
1141
1142// unexpected: factory
1143
1144// keep make_unexpected() removed in p0323r2 for pre-C++17:
1145
1146template< typename E>
1148make_unexpected( E && value ) -> unexpected_type< typename std::decay<E>::type >
1149{
1150 return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
1151}
1152
1153#if nsel_P0323R <= 3
1154
1155/*nsel_constexpr14*/ auto inline
1156make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
1157{
1158 return unexpected_type< std::exception_ptr >( std::current_exception() );
1159}
1160
1161#endif // nsel_P0323R
1162
1164
1165template< typename E >
1166class bad_expected_access;
1167
1169
1170template <>
1171class bad_expected_access< void > : public std::exception
1172{
1173public:
1174 explicit bad_expected_access()
1175 : std::exception()
1176 {}
1177};
1178
1180
1181#if !nsel_CONFIG_NO_EXCEPTIONS
1182
1183template< typename E >
1184class bad_expected_access : public bad_expected_access< void >
1185{
1186public:
1187 using error_type = E;
1188
1189 explicit bad_expected_access( error_type error )
1190 : m_error( error )
1191 {}
1192
1193 virtual char const * what() const noexcept override
1194 {
1195 return "bad_expected_access";
1196 }
1197
1198 nsel_constexpr14 error_type & error() &
1199 {
1200 return m_error;
1201 }
1202
1203 constexpr error_type const & error() const &
1204 {
1205 return m_error;
1206 }
1207
1208#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1209
1210 nsel_constexpr14 error_type && error() &&
1211 {
1212 return std::move( m_error );
1213 }
1214
1215 constexpr error_type const && error() const &&
1216 {
1217 return std::move( m_error );
1218 }
1219
1220#endif
1221
1222private:
1223 error_type m_error;
1224};
1225
1226#endif // nsel_CONFIG_NO_EXCEPTIONS
1227
1229
1230struct unexpect_t{};
1231using in_place_unexpected_t = unexpect_t;
1232
1233nsel_inline17 constexpr unexpect_t unexpect{};
1234nsel_inline17 constexpr unexpect_t in_place_unexpected{};
1235
1237
1238#if nsel_CONFIG_NO_EXCEPTIONS
1239
1240namespace detail {
1241 bool text( char const * /*text*/ ) { return true; }
1242}
1243template< typename Error >
1244struct error_traits
1245{
1246 static void rethrow( Error const & /*e*/ )
1247 {
1248 assert( false && detail::text("throw bad_expected_access<Error>{ e };") );
1249 }
1250};
1251
1252template<>
1253struct error_traits< std::exception_ptr >
1254{
1255 static void rethrow( std::exception_ptr const & /*e*/ )
1256 {
1257 assert( false && detail::text("throw bad_expected_access<std::exception_ptr>{ e };") );
1258 }
1259};
1260
1261template<>
1262struct error_traits< std::error_code >
1263{
1264 static void rethrow( std::error_code const & /*e*/ )
1265 {
1266 assert( false && detail::text("throw std::system_error( e );") );
1267 }
1268};
1269
1270#else // nsel_CONFIG_NO_EXCEPTIONS
1271
1272template< typename Error >
1273struct error_traits
1274{
1275 static void rethrow( Error const & e )
1276 {
1277 throw bad_expected_access<Error>{ e };
1278 }
1279};
1280
1281template<>
1282struct error_traits< std::exception_ptr >
1283{
1284 static void rethrow( std::exception_ptr const & e )
1285 {
1286 std::rethrow_exception( e );
1287 }
1288};
1289
1290template<>
1291struct error_traits< std::error_code >
1292{
1293 static void rethrow( std::error_code const & e )
1294 {
1295 throw std::system_error( e );
1296 }
1297};
1298
1299#endif // nsel_CONFIG_NO_EXCEPTIONS
1300
1301} // namespace expected_lite
1302
1303// provide nonstd::unexpected_type:
1304
1305using expected_lite::unexpected_type;
1306
1307namespace expected_lite {
1308
1310
1311#if nsel_P0323R <= 2
1312template< typename T, typename E = std::exception_ptr >
1313class expected
1314#else
1315template< typename T, typename E >
1316class expected
1317#endif // nsel_P0323R
1318{
1319private:
1320 template< typename, typename > friend class expected;
1321
1322public:
1323 using value_type = T;
1324 using error_type = E;
1325 using unexpected_type = nonstd::unexpected_type<E>;
1326
1327 template< typename U >
1328 struct rebind
1329 {
1330 using type = expected<U, error_type>;
1331 };
1332
1333 // x.x.4.1 constructors
1334
1336 std::is_default_constructible<T>::value
1337 )
1338 nsel_constexpr14 expected()
1339 : contained( true )
1340 {
1341 contained.construct_value( value_type() );
1342 }
1343
1344 nsel_constexpr14 expected( expected const & ) = default;
1345 nsel_constexpr14 expected( expected && ) = default;
1346
1347 template< typename U, typename G
1349 std::is_constructible< T, U const &>::value
1350 && std::is_constructible<E, G const &>::value
1351 && !std::is_constructible<T, expected<U, G> & >::value
1352 && !std::is_constructible<T, expected<U, G> && >::value
1353 && !std::is_constructible<T, expected<U, G> const & >::value
1354 && !std::is_constructible<T, expected<U, G> const && >::value
1355 && !std::is_convertible< expected<U, G> & , T>::value
1356 && !std::is_convertible< expected<U, G> &&, T>::value
1357 && !std::is_convertible< expected<U, G> const & , T>::value
1358 && !std::is_convertible< expected<U, G> const &&, T>::value
1359 && (!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> explicit */
1360 )
1361 >
1362 nsel_constexpr14 explicit expected( expected<U, G> const & other )
1363 : contained( other.has_value() )
1364 {
1365 if ( has_value() ) contained.construct_value( T{ other.contained.value() } );
1366 else contained.construct_error( E{ other.contained.error() } );
1367 }
1368
1369 template< typename U, typename G
1371 std::is_constructible< T, U const &>::value
1372 && std::is_constructible<E, G const &>::value
1373 && !std::is_constructible<T, expected<U, G> & >::value
1374 && !std::is_constructible<T, expected<U, G> && >::value
1375 && !std::is_constructible<T, expected<U, G> const & >::value
1376 && !std::is_constructible<T, expected<U, G> const && >::value
1377 && !std::is_convertible< expected<U, G> & , T>::value
1378 && !std::is_convertible< expected<U, G> &&, T>::value
1379 && !std::is_convertible< expected<U, G> const &, T>::value
1380 && !std::is_convertible< expected<U, G> const &&, T>::value
1381 && !(!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> non-explicit */
1382 )
1383 >
1384 nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> const & other )
1385 : contained( other.has_value() )
1386 {
1387 if ( has_value() ) contained.construct_value( other.contained.value() );
1388 else contained.construct_error( other.contained.error() );
1389 }
1390
1391 template< typename U, typename G
1393 std::is_constructible< T, U>::value
1394 && std::is_constructible<E, G>::value
1395 && !std::is_constructible<T, expected<U, G> & >::value
1396 && !std::is_constructible<T, expected<U, G> && >::value
1397 && !std::is_constructible<T, expected<U, G> const & >::value
1398 && !std::is_constructible<T, expected<U, G> const && >::value
1399 && !std::is_convertible< expected<U, G> & , T>::value
1400 && !std::is_convertible< expected<U, G> &&, T>::value
1401 && !std::is_convertible< expected<U, G> const & , T>::value
1402 && !std::is_convertible< expected<U, G> const &&, T>::value
1403 && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> explicit */
1404 )
1405 >
1406 nsel_constexpr14 explicit expected( expected<U, G> && other )
1407 : contained( other.has_value() )
1408 {
1409 if ( has_value() ) contained.construct_value( T{ std::move( other.contained.value() ) } );
1410 else contained.construct_error( E{ std::move( other.contained.error() ) } );
1411 }
1412
1413 template< typename U, typename G
1415 std::is_constructible< T, U>::value
1416 && std::is_constructible<E, G>::value
1417 && !std::is_constructible<T, expected<U, G> & >::value
1418 && !std::is_constructible<T, expected<U, G> && >::value
1419 && !std::is_constructible<T, expected<U, G> const & >::value
1420 && !std::is_constructible<T, expected<U, G> const && >::value
1421 && !std::is_convertible< expected<U, G> & , T>::value
1422 && !std::is_convertible< expected<U, G> &&, T>::value
1423 && !std::is_convertible< expected<U, G> const & , T>::value
1424 && !std::is_convertible< expected<U, G> const &&, T>::value
1425 && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> non-explicit */
1426 )
1427 >
1428 nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> && other )
1429 : contained( other.has_value() )
1430 {
1431 if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
1432 else contained.construct_error( std::move( other.contained.error() ) );
1433 }
1434
1435 template< typename U = T
1437 std::is_copy_constructible<U>::value
1438 )
1439 >
1440 nsel_constexpr14 expected( value_type const & value )
1441 : contained( true )
1442 {
1443 contained.construct_value( value );
1444 }
1445
1446 template< typename U = T
1448 std::is_constructible<T,U&&>::value
1449 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1450 && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value
1451 && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
1452 && !std::is_convertible<U&&,T>::value /*=> explicit */
1453 )
1454 >
1455 nsel_constexpr14 explicit expected( U && value ) noexcept
1456 (
1457 std::is_nothrow_move_constructible<U>::value &&
1458 std::is_nothrow_move_constructible<E>::value
1459 )
1460 : contained( true )
1461 {
1462 contained.construct_value( T{ std::forward<U>( value ) } );
1463 }
1464
1465 template< typename U = T
1467 std::is_constructible<T,U&&>::value
1468 && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1469 && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value
1470 && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
1471 && std::is_convertible<U&&,T>::value /*=> non-explicit */
1472 )
1473 >
1474 nsel_constexpr14 /*non-explicit*/ expected( U && value ) noexcept
1475 (
1476 std::is_nothrow_move_constructible<U>::value &&
1477 std::is_nothrow_move_constructible<E>::value
1478 )
1479 : contained( true )
1480 {
1481 contained.construct_value( std::forward<U>( value ) );
1482 }
1483
1484 // construct error:
1485
1486 template< typename G = E
1488 std::is_constructible<E, G const & >::value
1489 && !std::is_convertible< G const &, E>::value /*=> explicit */
1490 )
1491 >
1492 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error )
1493 : contained( false )
1494 {
1495 contained.construct_error( E{ error.value() } );
1496 }
1497
1498 template< typename G = E
1500 std::is_constructible<E, G const & >::value
1501 && std::is_convertible< G const &, E>::value /*=> non-explicit */
1502 )
1503 >
1504 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error )
1505 : contained( false )
1506 {
1507 contained.construct_error( error.value() );
1508 }
1509
1510 template< typename G = E
1512 std::is_constructible<E, G&& >::value
1513 && !std::is_convertible< G&&, E>::value /*=> explicit */
1514 )
1515 >
1516 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error )
1517 : contained( false )
1518 {
1519 contained.construct_error( E{ std::move( error.value() ) } );
1520 }
1521
1522 template< typename G = E
1524 std::is_constructible<E, G&& >::value
1525 && std::is_convertible< G&&, E>::value /*=> non-explicit */
1526 )
1527 >
1528 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error )
1529 : contained( false )
1530 {
1531 contained.construct_error( std::move( error.value() ) );
1532 }
1533
1534 // in-place construction, value
1535
1536 template< typename... Args
1538 std::is_constructible<T, Args&&...>::value
1539 )
1540 >
1541 nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), Args&&... args )
1542 : contained( true )
1543 {
1544 contained.emplace_value( std::forward<Args>( args )... );
1545 }
1546
1547 template< typename U, typename... Args
1549 std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
1550 )
1551 >
1552 nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
1553 : contained( true )
1554 {
1555 contained.emplace_value( il, std::forward<Args>( args )... );
1556 }
1557
1558 // in-place construction, error
1559
1560 template< typename... Args
1562 std::is_constructible<E, Args&&...>::value
1563 )
1564 >
1565 nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
1566 : contained( false )
1567 {
1568 contained.emplace_error( std::forward<Args>( args )... );
1569 }
1570
1571 template< typename U, typename... Args
1573 std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
1574 )
1575 >
1576 nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
1577 : contained( false )
1578 {
1579 contained.emplace_error( il, std::forward<Args>( args )... );
1580 }
1581
1582 // x.x.4.2 destructor
1583
1584 // TODO: ~expected: triviality
1585 // 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>().
1586 // 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.
1587
1588 ~expected()
1589 {
1590 if ( has_value() ) contained.destruct_value();
1591 else contained.destruct_error();
1592 }
1593
1594 // x.x.4.3 assignment
1595
1596 expected & operator=( expected const & other )
1597 {
1598 expected( other ).swap( *this );
1599 return *this;
1600 }
1601
1602 expected & operator=( expected && other ) noexcept
1603 (
1604 std::is_nothrow_move_constructible< T>::value
1605 && std::is_nothrow_move_assignable< T>::value
1606 && std::is_nothrow_move_constructible<E>::value // added for missing
1607 && std::is_nothrow_move_assignable< E>::value ) // nothrow above
1608 {
1609 expected( std::move( other ) ).swap( *this );
1610 return *this;
1611 }
1612
1613 template< typename U
1615 !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value
1616 && std17::conjunction<std::is_scalar<T>, std::is_same<T, std::decay<U>> >::value
1617 && std::is_constructible<T ,U>::value
1618 && std::is_assignable< T&,U>::value
1619 && std::is_nothrow_move_constructible<E>::value )
1620 >
1621 expected & operator=( U && value )
1622 {
1623 expected( std::forward<U>( value ) ).swap( *this );
1624 return *this;
1625 }
1626
1627 template< typename G
1629 std::is_copy_constructible<E>::value // TODO: std::is_nothrow_copy_constructible<E>
1630 && std::is_copy_assignable<E>::value
1631 )
1632 >
1633 expected & operator=( nonstd::unexpected_type<G> const & error )
1634 {
1635 expected( unexpect, error.value() ).swap( *this );
1636 return *this;
1637 }
1638
1639 template< typename G
1641 std::is_move_constructible<E>::value // TODO: std::is_nothrow_move_constructible<E>
1642 && std::is_move_assignable<E>::value
1643 )
1644 >
1645 expected & operator=( nonstd::unexpected_type<G> && error )
1646 {
1647 expected( unexpect, std::move( error.value() ) ).swap( *this );
1648 return *this;
1649 }
1650
1651 template< typename... Args
1653 std::is_nothrow_constructible<T, Args&&...>::value
1654 )
1655 >
1656 value_type & emplace( Args &&... args )
1657 {
1658 expected( nonstd_lite_in_place(T), std::forward<Args>(args)... ).swap( *this );
1659 return value();
1660 }
1661
1662 template< typename U, typename... Args
1664 std::is_nothrow_constructible<T, std::initializer_list<U>&, Args&&...>::value
1665 )
1666 >
1667 value_type & emplace( std::initializer_list<U> il, Args &&... args )
1668 {
1669 expected( nonstd_lite_in_place(T), il, std::forward<Args>(args)... ).swap( *this );
1670 return value();
1671 }
1672
1673 // x.x.4.4 swap
1674
1675 template< typename U=T, typename G=E >
1676 nsel_REQUIRES_R( void,
1677 std17::is_swappable< U>::value
1678 && std17::is_swappable<G>::value
1679 && ( std::is_move_constructible<U>::value || std::is_move_constructible<G>::value )
1680 )
1681 swap( expected & other ) noexcept
1682 (
1683 std::is_nothrow_move_constructible<T>::value && std17::is_nothrow_swappable<T&>::value &&
1684 std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::value
1685 )
1686 {
1687 using std::swap;
1688
1689 if ( bool(*this) && bool(other) ) { swap( contained.value(), other.contained.value() ); }
1690 else if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
1691 else if ( bool(*this) && ! bool(other) ) { error_type t( std::move( other.error() ) );
1692 other.contained.destruct_error();
1693 other.contained.construct_value( std::move( contained.value() ) );
1694 contained.destruct_value();
1695 contained.construct_error( std::move( t ) );
1696 bool has_value = contained.has_value();
1697 bool other_has_value = other.has_value();
1698 other.contained.set_has_value(has_value);
1699 contained.set_has_value(other_has_value);
1700 }
1701 else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
1702 }
1703
1704 // x.x.4.5 observers
1705
1706 constexpr value_type const * operator ->() const
1707 {
1708 return assert( has_value() ), contained.value_ptr();
1709 }
1710
1711 value_type * operator ->()
1712 {
1713 return assert( has_value() ), contained.value_ptr();
1714 }
1715
1716 constexpr value_type const & operator *() const &
1717 {
1718 return assert( has_value() ), contained.value();
1719 }
1720
1721 value_type & operator *() &
1722 {
1723 return assert( has_value() ), contained.value();
1724 }
1725
1726#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1727
1728 constexpr value_type const && operator *() const &&
1729 {
1730 return assert( has_value() ), std::move( contained.value() );
1731 }
1732
1733 nsel_constexpr14 value_type && operator *() &&
1734 {
1735 return assert( has_value() ), std::move( contained.value() );
1736 }
1737
1738#endif
1739
1740 constexpr explicit operator bool() const noexcept
1741 {
1742 return has_value();
1743 }
1744
1745 constexpr bool has_value() const noexcept
1746 {
1747 return contained.has_value();
1748 }
1749
1750 constexpr value_type const & value() const &
1751 {
1752 return has_value()
1753 ? ( contained.value() )
1754 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
1755 }
1756
1757 value_type & value() &
1758 {
1759 return has_value()
1760 ? ( contained.value() )
1761 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
1762 }
1763
1764#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1765
1766 constexpr value_type const && value() const &&
1767 {
1768 return std::move( has_value()
1769 ? ( contained.value() )
1770 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
1771 }
1772
1773 nsel_constexpr14 value_type && value() &&
1774 {
1775 return std::move( has_value()
1776 ? ( contained.value() )
1777 : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
1778 }
1779
1780#endif
1781
1782 constexpr error_type const & error() const &
1783 {
1784 return assert( ! has_value() ), contained.error();
1785 }
1786
1787 error_type & error() &
1788 {
1789 return assert( ! has_value() ), contained.error();
1790 }
1791
1792#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
1793
1794 constexpr error_type const && error() const &&
1795 {
1796 return assert( ! has_value() ), std::move( contained.error() );
1797 }
1798
1799 error_type && error() &&
1800 {
1801 return assert( ! has_value() ), std::move( contained.error() );
1802 }
1803
1804#endif
1805
1806 constexpr unexpected_type get_unexpected() const
1807 {
1808 return make_unexpected( contained.error() );
1809 }
1810
1811 template< typename Ex >
1812 bool has_exception() const
1813 {
1814 using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type;
1815 return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
1816 }
1817
1818 template< typename U
1820 std::is_copy_constructible< T>::value
1821 && std::is_convertible<U&&, T>::value
1822 )
1823 >
1824 value_type value_or( U && v ) const &
1825 {
1826 return has_value()
1827 ? contained.value()
1828 : static_cast<T>( std::forward<U>( v ) );
1829 }
1830
1831 template< typename U
1833 std::is_move_constructible< T>::value
1834 && std::is_convertible<U&&, T>::value
1835 )
1836 >
1837 value_type value_or( U && v ) &&
1838 {
1839 return has_value()
1840 ? std::move( contained.value() )
1841 : static_cast<T>( std::forward<U>( v ) );
1842 }
1843
1844 // unwrap()
1845
1846// template <class U, class E>
1847// constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
1848
1849// template <class T, class E>
1850// constexpr expected<T,E> expected<T,E>::unwrap() const&;
1851
1852// template <class U, class E>
1853// expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
1854
1855// template <class T, class E>
1856// template expected<T,E> expected<T,E>::unwrap() &&;
1857
1858 // factories
1859
1860// template< typename Ex, typename F>
1861// expected<T,E> catch_exception(F&& f);
1862
1863// template< typename F>
1864// expected<decltype(func(declval<T>())),E> map(F&& func) ;
1865
1866// template< typename F>
1867// 'see below' bind(F&& func);
1868
1869// template< typename F>
1870// expected<T,E> catch_error(F&& f);
1871
1872// template< typename F>
1873// 'see below' then(F&& func);
1874
1875private:
1876 detail::storage_t
1877 <
1878 T
1879 ,E
1880 , std::is_copy_constructible<T>::value && std::is_copy_constructible<E>::value
1881 , std::is_move_constructible<T>::value && std::is_move_constructible<E>::value
1882 >
1883 contained;
1884};
1885
1887
1888template< typename E >
1889class expected<void, E>
1890{
1891private:
1892 template< typename, typename > friend class expected;
1893
1894public:
1895 using value_type = void;
1896 using error_type = E;
1897 using unexpected_type = nonstd::unexpected_type<E>;
1898
1899 // x.x.4.1 constructors
1900
1901 constexpr expected() noexcept
1902 : contained( true )
1903 {}
1904
1905 nsel_constexpr14 expected( expected const & other ) = default;
1906 nsel_constexpr14 expected( expected && other ) = default;
1907
1908 constexpr explicit expected( nonstd_lite_in_place_t(void) )
1909 : contained( true )
1910 {}
1911
1912 template< typename G = E
1914 !std::is_convertible<G const &, E>::value /*=> explicit */
1915 )
1916 >
1917 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error )
1918 : contained( false )
1919 {
1920 contained.construct_error( E{ error.value() } );
1921 }
1922
1923 template< typename G = E
1925 std::is_convertible<G const &, E>::value /*=> non-explicit */
1926 )
1927 >
1928 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error )
1929 : contained( false )
1930 {
1931 contained.construct_error( error.value() );
1932 }
1933
1934 template< typename G = E
1936 !std::is_convertible<G&&, E>::value /*=> explicit */
1937 )
1938 >
1939 nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error )
1940 : contained( false )
1941 {
1942 contained.construct_error( E{ std::move( error.value() ) } );
1943 }
1944
1945 template< typename G = E
1947 std::is_convertible<G&&, E>::value /*=> non-explicit */
1948 )
1949 >
1950 nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error )
1951 : contained( false )
1952 {
1953 contained.construct_error( std::move( error.value() ) );
1954 }
1955
1956 template< typename... Args
1958 std::is_constructible<E, Args&&...>::value
1959 )
1960 >
1961 nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
1962 : contained( false )
1963 {
1964 contained.emplace_error( std::forward<Args>( args )... );
1965 }
1966
1967 template< typename U, typename... Args
1969 std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
1970 )
1971 >
1972 nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
1973 : contained( false )
1974 {
1975 contained.emplace_error( il, std::forward<Args>( args )... );
1976 }
1977
1978 // destructor
1979
1980 ~expected()
1981 {
1982 if ( ! has_value() )
1983 {
1984 contained.destruct_error();
1985 }
1986 }
1987
1988 // x.x.4.3 assignment
1989
1990 expected & operator=( expected const & other )
1991 {
1992 expected( other ).swap( *this );
1993 return *this;
1994 }
1995
1996 expected & operator=( expected && other ) noexcept
1997 (
1998 std::is_nothrow_move_assignable<E>::value &&
1999 std::is_nothrow_move_constructible<E>::value )
2000 {
2001 expected( std::move( other ) ).swap( *this );
2002 return *this;
2003 }
2004
2005 void emplace()
2006 {
2007 expected().swap( *this );
2008 }
2009
2010 // x.x.4.4 swap
2011
2012 template< typename G = E >
2013 nsel_REQUIRES_R( void,
2014 std17::is_swappable<G>::value
2015 && std::is_move_constructible<G>::value
2016 )
2017 swap( expected & other ) noexcept
2018 (
2019 std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::value
2020 )
2021 {
2022 using std::swap;
2023
2024 if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
2025 else if ( bool(*this) && ! bool(other) ) { contained.construct_error( std::move( other.error() ) );
2026 bool has_value = contained.has_value();
2027 bool other_has_value = other.has_value();
2028 other.contained.set_has_value(has_value);
2029 contained.set_has_value(other_has_value);
2030 }
2031 else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
2032 }
2033
2034 // x.x.4.5 observers
2035
2036 constexpr explicit operator bool() const noexcept
2037 {
2038 return has_value();
2039 }
2040
2041 constexpr bool has_value() const noexcept
2042 {
2043 return contained.has_value();
2044 }
2045
2046 void value() const
2047 {
2048 if ( ! has_value() )
2049 {
2050 error_traits<error_type>::rethrow( contained.error() );
2051 }
2052 }
2053
2054 constexpr error_type const & error() const &
2055 {
2056 return assert( ! has_value() ), contained.error();
2057 }
2058
2059 error_type & error() &
2060 {
2061 return assert( ! has_value() ), contained.error();
2062 }
2063
2064#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
2065
2066 constexpr error_type const && error() const &&
2067 {
2068 return assert( ! has_value() ), std::move( contained.error() );
2069 }
2070
2071 error_type && error() &&
2072 {
2073 return assert( ! has_value() ), std::move( contained.error() );
2074 }
2075
2076#endif
2077
2078 constexpr unexpected_type get_unexpected() const
2079 {
2080 return make_unexpected( contained.error() );
2081 }
2082
2083 template< typename Ex >
2084 bool has_exception() const
2085 {
2086 using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type;
2087 return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
2088 }
2089
2090// template constexpr 'see below' unwrap() const&;
2091//
2092// template 'see below' unwrap() &&;
2093
2094 // factories
2095
2096// template< typename Ex, typename F>
2097// expected<void,E> catch_exception(F&& f);
2098//
2099// template< typename F>
2100// expected<decltype(func()), E> map(F&& func) ;
2101//
2102// template< typename F>
2103// 'see below' bind(F&& func) ;
2104//
2105// template< typename F>
2106// expected<void,E> catch_error(F&& f);
2107//
2108// template< typename F>
2109// 'see below' then(F&& func);
2110
2111private:
2112 detail::storage_t
2113 <
2114 void
2115 , E
2116 , std::is_copy_constructible<E>::value
2117 , std::is_move_constructible<E>::value
2118 >
2119 contained;
2120};
2121
2122// x.x.4.6 expected<>: comparison operators
2123
2124template< typename T1, typename E1, typename T2, typename E2 >
2125constexpr bool operator==( expected<T1,E1> const & x, expected<T2,E2> const & y )
2126{
2127 return bool(x) != bool(y) ? false : bool(x) == false ? x.error() == y.error() : *x == *y;
2128}
2129
2130template< typename T1, typename E1, typename T2, typename E2 >
2131constexpr bool operator!=( expected<T1,E1> const & x, expected<T2,E2> const & y )
2132{
2133 return !(x == y);
2134}
2135
2136template< typename E1, typename E2 >
2137constexpr bool operator==( expected<void,E1> const & x, expected<void,E1> const & y )
2138{
2139 return bool(x) != bool(y) ? false : bool(x) == false ? x.error() == y.error() : true;
2140}
2141
2142#if nsel_P0323R <= 2
2143
2144template< typename T, typename E >
2145constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y )
2146{
2147 return (!y) ? false : (!x) ? true : *x < *y;
2148}
2149
2150template< typename T, typename E >
2151constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y )
2152{
2153 return (y < x);
2154}
2155
2156template< typename T, typename E >
2157constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y )
2158{
2159 return !(y < x);
2160}
2161
2162template< typename T, typename E >
2163constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y )
2164{
2165 return !(x < y);
2166}
2167
2168#endif
2169
2170// x.x.4.7 expected: comparison with T
2171
2172template< typename T1, typename E1, typename T2 >
2173constexpr bool operator==( expected<T1,E1> const & x, T2 const & v )
2174{
2175 return bool(x) ? *x == v : false;
2176}
2177
2178template< typename T1, typename E1, typename T2 >
2179constexpr bool operator==(T2 const & v, expected<T1,E1> const & x )
2180{
2181 return bool(x) ? v == *x : false;
2182}
2183
2184template< typename T1, typename E1, typename T2 >
2185constexpr bool operator!=( expected<T1,E1> const & x, T2 const & v )
2186{
2187 return bool(x) ? *x != v : true;
2188}
2189
2190template< typename T1, typename E1, typename T2 >
2191constexpr bool operator!=( T2 const & v, expected<T1,E1> const & x )
2192{
2193 return bool(x) ? v != *x : true;
2194}
2195
2196#if nsel_P0323R <= 2
2197
2198template< typename T, typename E >
2199constexpr bool operator<( expected<T,E> const & x, T const & v )
2200{
2201 return bool(x) ? *x < v : true;
2202}
2203
2204template< typename T, typename E >
2205constexpr bool operator<( T const & v, expected<T,E> const & x )
2206{
2207 return bool(x) ? v < *x : false;
2208}
2209
2210template< typename T, typename E >
2211constexpr bool operator>( T const & v, expected<T,E> const & x )
2212{
2213 return bool(x) ? *x < v : false;
2214}
2215
2216template< typename T, typename E >
2217constexpr bool operator>( expected<T,E> const & x, T const & v )
2218{
2219 return bool(x) ? v < *x : false;
2220}
2221
2222template< typename T, typename E >
2223constexpr bool operator<=( T const & v, expected<T,E> const & x )
2224{
2225 return bool(x) ? ! ( *x < v ) : false;
2226}
2227
2228template< typename T, typename E >
2229constexpr bool operator<=( expected<T,E> const & x, T const & v )
2230{
2231 return bool(x) ? ! ( v < *x ) : true;
2232}
2233
2234template< typename T, typename E >
2235constexpr bool operator>=( expected<T,E> const & x, T const & v )
2236{
2237 return bool(x) ? ! ( *x < v ) : false;
2238}
2239
2240template< typename T, typename E >
2241constexpr bool operator>=( T const & v, expected<T,E> const & x )
2242{
2243 return bool(x) ? ! ( v < *x ) : true;
2244}
2245
2246#endif // nsel_P0323R
2247
2248// x.x.4.8 expected: comparison with unexpected_type
2249
2250template< typename T1, typename E1 , typename E2 >
2251constexpr bool operator==( expected<T1,E1> const & x, unexpected_type<E2> const & u )
2252{
2253 return (!x) ? x.get_unexpected() == u : false;
2254}
2255
2256template< typename T1, typename E1 , typename E2 >
2257constexpr bool operator==( unexpected_type<E2> const & u, expected<T1,E1> const & x )
2258{
2259 return ( x == u );
2260}
2261
2262template< typename T1, typename E1 , typename E2 >
2263constexpr bool operator!=( expected<T1,E1> const & x, unexpected_type<E2> const & u )
2264{
2265 return ! ( x == u );
2266}
2267
2268template< typename T1, typename E1 , typename E2 >
2269constexpr bool operator!=( unexpected_type<E2> const & u, expected<T1,E1> const & x )
2270{
2271 return ! ( x == u );
2272}
2273
2274#if nsel_P0323R <= 2
2275
2276template< typename T, typename E >
2277constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u )
2278{
2279 return (!x) ? ( x.get_unexpected() < u ) : false;
2280}
2281
2282template< typename T, typename E >
2283constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x )
2284{
2285 return (!x) ? ( u < x.get_unexpected() ) : true ;
2286}
2287
2288template< typename T, typename E >
2289constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u )
2290{
2291 return ( u < x );
2292}
2293
2294template< typename T, typename E >
2295constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x )
2296{
2297 return ( x < u );
2298}
2299
2300template< typename T, typename E >
2301constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u )
2302{
2303 return ! ( u < x );
2304}
2305
2306template< typename T, typename E >
2307constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x)
2308{
2309 return ! ( x < u );
2310}
2311
2312template< typename T, typename E >
2313constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u )
2314{
2315 return ! ( u > x );
2316}
2317
2318template< typename T, typename E >
2319constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x )
2320{
2321 return ! ( x > u );
2322}
2323
2324#endif // nsel_P0323R
2325
2327
2328template< typename T, typename E
2330 ( std::is_void<T>::value || std::is_move_constructible<T>::value )
2331 && std::is_move_constructible<E>::value
2332 && std17::is_swappable<T>::value
2333 && std17::is_swappable<E>::value )
2334>
2335void swap( expected<T,E> & x, expected<T,E> & y ) noexcept ( noexcept ( x.swap(y) ) )
2336{
2337 x.swap( y );
2338}
2339
2340#if nsel_P0323R <= 3
2341
2342template< typename T >
2343constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
2344{
2345 return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
2346}
2347
2348// expected<void> specialization:
2349
2350auto inline make_expected() -> expected<void>
2351{
2352 return expected<void>( in_place );
2353}
2354
2355template< typename T >
2356constexpr auto make_expected_from_current_exception() -> expected<T>
2357{
2358 return expected<T>( make_unexpected_from_current_exception() );
2359}
2360
2361template< typename T >
2362auto make_expected_from_exception( std::exception_ptr v ) -> expected<T>
2363{
2364 return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) );
2365}
2366
2367template< typename T, typename E >
2368constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
2369{
2370 return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
2371}
2372
2373template< typename F
2374 nsel_REQUIRES_T( ! std::is_same<typename std::result_of<F()>::type, void>::value )
2375>
2376/*nsel_constexpr14*/
2377auto make_expected_from_call( F f ) -> expected< typename std::result_of<F()>::type >
2378{
2379 try
2380 {
2381 return make_expected( f() );
2382 }
2383 catch (...)
2384 {
2385 return make_unexpected_from_current_exception();
2386 }
2387}
2388
2389template< typename F
2390 nsel_REQUIRES_T( std::is_same<typename std::result_of<F()>::type, void>::value )
2391>
2392/*nsel_constexpr14*/
2393auto make_expected_from_call( F f ) -> expected<void>
2394{
2395 try
2396 {
2397 f();
2398 return make_expected();
2399 }
2400 catch (...)
2401 {
2402 return make_unexpected_from_current_exception();
2403 }
2404}
2405
2406#endif // nsel_P0323R
2407
2408} // namespace expected_lite
2409
2410using namespace expected_lite;
2411
2412// using expected_lite::expected;
2413// using ...
2414
2415} // namespace nonstd
2416
2417namespace std {
2418
2419// expected: hash support
2420
2421template< typename T, typename E >
2422struct hash< nonstd::expected<T,E> >
2423{
2424 using result_type = std::size_t;
2425 using argument_type = nonstd::expected<T,E>;
2426
2427 constexpr result_type operator()(argument_type const & arg) const
2428 {
2429 return arg ? std::hash<T>{}(*arg) : result_type{};
2430 }
2431};
2432
2433// TBD - ?? remove? see spec.
2434template< typename T, typename E >
2435struct hash< nonstd::expected<T&,E> >
2436{
2437 using result_type = std::size_t;
2438 using argument_type = nonstd::expected<T&,E>;
2439
2440 constexpr result_type operator()(argument_type const & arg) const
2441 {
2442 return arg ? std::hash<T>{}(*arg) : result_type{};
2443 }
2444};
2445
2446// TBD - implement
2447// bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true;
2448// otherwise it evaluates to an unspecified value if E is exception_ptr or
2449// a combination of hashing false and hash<E>()(e.error()).
2450
2451template< typename E >
2452struct hash< nonstd::expected<void,E> >
2453{
2454};
2455
2456} // namespace std
2457
2458namespace nonstd {
2459
2460// void unexpected() is deprecated && removed in C++17
2461
2462#if nsel_CPP17_OR_GREATER || nsel_COMPILER_MSVC_VERSION > 141
2463template< typename E >
2464using unexpected = unexpected_type<E>;
2465#endif
2466
2467} // namespace nonstd
2468
2469#undef nsel_REQUIRES
2470#undef nsel_REQUIRES_0
2471#undef nsel_REQUIRES_T
2472
2474
2475#endif // nsel_USES_STD_EXPECTED
2476
2477#endif // NONSTD_EXPECTED_LITE_HPP
bool_constant< false > false_type
Definition: optional.hpp:460
bool_constant< true > true_type
Definition: optional.hpp:459
optional_constexpr bool operator>(optional< T > const &x, optional< U > const &y)
Definition: optional.hpp:1531
void swap(optional< T > &x, optional< T > &y)
Definition: optional.hpp:1705
optional_constexpr bool operator>=(optional< T > const &x, optional< U > const &y)
Definition: optional.hpp:1543
in_place_t in_place_type(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())
Definition: expected.hpp:158
in_place_t in_place_index(detail::in_place_index_tag< K >=detail::in_place_index_tag< K >())
Definition: expected.hpp:164
in_place_t in_place(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())
Definition: expected.hpp:146
in_place_t in_place(detail::in_place_index_tag< K >=detail::in_place_index_tag< K >())
Definition: expected.hpp:152
RESTINIO_NODISCARD bool operator==(const character_t &a, const character_t &b) noexcept
RESTINIO_NODISCARD bool operator!=(const character_t &a, const character_t &b) noexcept
RESTINIO_NODISCARD bool operator<(const qvalue_t &a, const qvalue_t &b) noexcept
Definition: basics.hpp:234
RESTINIO_NODISCARD bool operator<=(const qvalue_t &a, const qvalue_t &b) noexcept
Definition: basics.hpp:241
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, Value_Type >::type value_or(const Parameter_Container &params, string_view_t key, Value_Type default_value)
Get parameter value or a given default.
Definition: value_or.hpp:36
STL namespace.
nonstd::expected< T, E > argument_type
Definition: expected.hpp:2425
constexpr result_type operator()(argument_type const &arg) const
Definition: expected.hpp:2427
nonstd::expected< T &, E > argument_type
Definition: expected.hpp:2438
constexpr result_type operator()(argument_type const &arg) const
Definition: expected.hpp:2440
#define nsel_inline17
Definition: expected.hpp:235
#define nsel_REQUIRES_T(...)
Definition: expected.hpp:282
#define nsel_RESTORE_WARNINGS()
Definition: expected.hpp:323
#define nonstd_lite_in_place( T)
Definition: expected.hpp:175
#define nsel_REQUIRES_0(...)
Definition: expected.hpp:279
#define nsel_constexpr14
Definition: expected.hpp:229
#define nonstd_lite_in_place_t( T)
Definition: expected.hpp:171
#define nsel_REQUIRES_R(R,...)
Definition: expected.hpp:285
#define nsel_DISABLE_MSVC_WARNINGS(codes)
Definition: expected.hpp:313