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