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 2
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 5
53 #endif
54 
55 // C++ language version detection (C++20 is speculative):
56 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
57 
58 #ifndef nsel_CPLUSPLUS
59 # if defined(_MSVC_LANG ) && !defined(__clang__)
60 # define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
61 # else
62 # define nsel_CPLUSPLUS __cplusplus
63 # endif
64 #endif
65 
66 #define nsel_CPP98_OR_GREATER ( nsel_CPLUSPLUS >= 199711L )
67 #define nsel_CPP11_OR_GREATER ( nsel_CPLUSPLUS >= 201103L )
68 #define nsel_CPP14_OR_GREATER ( nsel_CPLUSPLUS >= 201402L )
69 #define nsel_CPP17_OR_GREATER ( nsel_CPLUSPLUS >= 201703L )
70 #define nsel_CPP20_OR_GREATER ( nsel_CPLUSPLUS >= 202000L )
71 
72 // Use C++20 std::expected if available and requested:
73 
74 #if nsel_CPP20_OR_GREATER && defined(__has_include )
75 # if __has_include( <expected> )
76 # define nsel_HAVE_STD_EXPECTED 1
77 # else
78 # define nsel_HAVE_STD_EXPECTED 0
79 # endif
80 #else
81 # define nsel_HAVE_STD_EXPECTED 0
82 #endif
83 
84 #define nsel_USES_STD_EXPECTED ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) )
85 
86 //
87 // in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
88 //
89 
90 #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
91 #define nonstd_lite_HAVE_IN_PLACE_TYPES 1
92 
93 // C++17 std::in_place in <utility>:
94 
95 #if nsel_CPP17_OR_GREATER
96 
97 #include <utility>
98 
99 namespace nonstd {
100 
101 using std::in_place;
102 using std::in_place_type;
103 using std::in_place_index;
104 using std::in_place_t;
105 using std::in_place_type_t;
106 using std::in_place_index_t;
107 
108 #define nonstd_lite_in_place_t( T) std::in_place_t
109 #define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
110 #define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
111 
112 #define nonstd_lite_in_place( T) std::in_place_t{}
113 #define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
114 #define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
115 
116 } // namespace nonstd
117 
118 #else // nsel_CPP17_OR_GREATER
119 
120 #include <cstddef>
121 
122 namespace nonstd {
123 namespace detail {
124 
125 template< class T >
127 
128 template< std::size_t K >
130 
131 } // namespace detail
132 
133 struct in_place_t {};
134 
135 template< class T >
137 {
138  return in_place_t();
139 }
140 
141 template< std::size_t K >
143 {
144  return in_place_t();
145 }
146 
147 template< class T >
149 {
150  return in_place_t();
151 }
152 
153 template< std::size_t K >
155 {
156  return in_place_t();
157 }
158 
159 // mimic templated typedef:
160 
161 #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
162 #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
163 #define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
164 
165 #define nonstd_lite_in_place( T) nonstd::in_place_type<T>
166 #define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
167 #define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
168 
169 } // namespace nonstd
170 
171 #endif // nsel_CPP17_OR_GREATER
172 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
173 
174 //
175 // Using std::expected:
176 //
177 
178 #if nsel_USES_STD_EXPECTED
179 
180 #include <expected>
181 
182 namespace nonstd {
183 
184  using std::expected;
185 // ...
186 }
187 
188 #else // nsel_USES_STD_EXPECTED
189 
190 #include <cassert>
191 #include <exception>
192 #include <functional>
193 #include <initializer_list>
194 #include <new>
195 #include <stdexcept>
196 #include <system_error>
197 #include <type_traits>
198 #include <utility>
199 
200 #if nsel_CPP11_OR_GREATER
201 # define nsel_constexpr constexpr
202 #else
203 # define nsel_constexpr /*constexpr*/
204 #endif
205 
206 #if nsel_CPP14_OR_GREATER
207 # define nsel_constexpr14 constexpr
208 #else
209 # define nsel_constexpr14 /*constexpr*/
210 #endif
211 
212 #if nsel_CPP17_OR_GREATER
213 # define nsel_inline17 inline
214 #else
215 # define nsel_inline17 /*inline*/
216 #endif
217 
218 // Method enabling
219 
220 #define nsel_REQUIRES_A(...) \
221  , typename std::enable_if<__VA_ARGS__, void*>::type = nullptr
222 
223 #define nsel_REQUIRES_0(...) \
224  template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
225 
226 #define nsel_REQUIRES_R(R, ...) \
227  typename std::enable_if<__VA_ARGS__, R>::type
228 
229 #define nsel_REQUIRES_T(...) \
230  , typename = typename std::enable_if< (__VA_ARGS__), nonstd::expected_lite::detail::enabler >::type
231 
232 // Compiler versions:
233 //
234 // MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
235 // MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
236 // MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
237 // MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
238 // MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
239 // MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
240 // MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
241 // MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
242 // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
243 // MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
244 
245 #if defined(_MSC_VER) && !defined(__clang__)
246 # define nsel_COMPILER_MSVC_VER (_MSC_VER )
247 # define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) )
248 #else
249 # define nsel_COMPILER_MSVC_VER 0
250 # define nsel_COMPILER_MSVC_VERSION 0
251 #endif
252 
253 #define nsel_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
254 
255 #if defined(__clang__)
256 # define nsel_COMPILER_CLANG_VERSION nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
257 #else
258 # define nsel_COMPILER_CLANG_VERSION 0
259 #endif
260 
261 #if defined(__GNUC__) && !defined(__clang__)
262 # define nsel_COMPILER_GNUC_VERSION nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
263 #else
264 # define nsel_COMPILER_GNUC_VERSION 0
265 #endif
266 
267 // half-open range [lo..hi):
268 //#define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
269 
270 // Presence of language and library features:
271 
272 #ifdef _HAS_CPP0X
273 # define nsel_HAS_CPP0X _HAS_CPP0X
274 #else
275 # define nsel_HAS_CPP0X 0
276 #endif
277 
278 //#define nsel_CPP11_140 (nsel_CPP11_OR_GREATER || nsel_COMPILER_MSVC_VER >= 1900)
279 
280 // Clang, GNUC, MSVC warning suppression macros:
281 
282 #ifdef __clang__
283 # pragma clang diagnostic push
284 #elif defined __GNUC__
285 # pragma GCC diagnostic push
286 #endif // __clang__
287 
288 #if nsel_COMPILER_MSVC_VERSION >= 140
289 # pragma warning( push )
290 # define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(disable: codes) )
291 #else
292 # define nsel_DISABLE_MSVC_WARNINGS(codes)
293 #endif
294 
295 #ifdef __clang__
296 # define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
297 #elif defined __GNUC__
298 # define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
299 #elif nsel_COMPILER_MSVC_VERSION >= 140
300 # define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) )
301 #else
302 # define nsel_RESTORE_WARNINGS()
303 #endif
304 
305 // Suppress the following MSVC (GSL) warnings:
306 // - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11)
307 
309 
310 //
311 // expected:
312 //
313 
314 namespace nonstd { namespace expected_lite {
315 
316 namespace std20 {
317 
318 // type traits C++20:
319 
320 template< typename T >
321 struct remove_cvref
322 {
323  typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
324 };
325 
326 } // namespace std20
327 
328 // forward declaration:
329 
330 template< typename T, typename E >
331 class expected;
332 
333 namespace detail {
334 
336 
337 enum class enabler{};
338 
340 
341 template< typename T, typename E >
342 union storage_t
343 {
344  friend class expected<T,E>;
345 
346 private:
347  using value_type = T;
348  using error_type = E;
349 
350  // no-op construction
351  storage_t() {}
352  ~storage_t() {}
353 
354  template<class ...Args>
355  void construct_value(Args&& ...args)
356  {
357  new(&m_value) value_type(std::forward<Args>(args)...);
358  }
359 
360  void destruct_value()
361  {
362  m_value.~value_type();
363  }
364 
365  void construct_error( error_type const & e )
366  {
367  new( &m_error ) error_type( e );
368  }
369 
370  void construct_error( error_type && e )
371  {
372  new( &m_error ) error_type( std::move( e ) );
373  }
374 
375  void destruct_error()
376  {
377  m_error.~error_type();
378  }
379 
380  constexpr value_type const & value() const &
381  {
382  return m_value;
383  }
384 
385  value_type & value() &
386  {
387  return m_value;
388  }
389 
390  constexpr value_type const && value() const &&
391  {
392  return std::move( m_value );
393  }
394 
395  nsel_constexpr14 value_type && value() &&
396  {
397  return std::move( m_value );
398  }
399 
400  value_type const * value_ptr() const
401  {
402  return &m_value;
403  }
404 
405  value_type * value_ptr()
406  {
407  return &m_value;
408  }
409 
410  error_type const & error() const
411  {
412  return m_error;
413  }
414 
415  error_type & error()
416  {
417  return m_error;
418  }
419 
420 private:
421  value_type m_value;
422  error_type m_error;
423 };
424 
426 
427 template< typename E >
428 union storage_t<void, E>
429 {
430  friend class expected<void,E>;
431 
432 private:
433  using value_type = void;
434  using error_type = E;
435 
436  // no-op construction
437  storage_t() {}
438  ~storage_t() {}
439 
440  void construct_error( error_type const & e )
441  {
442  new( &m_error ) error_type( e );
443  }
444 
445  void construct_error( error_type && e )
446  {
447  new( &m_error ) error_type( std::move( e ) );
448  }
449 
450  void destruct_error()
451  {
452  m_error.~error_type();
453  }
454 
455  error_type const & error() const
456  {
457  return m_error;
458  }
459 
460  error_type & error()
461  {
462  return m_error;
463  }
464 
465 private:
466  error_type m_error;
467 };
468 
469 } // namespace detail
470 
472 
473 #if nsel_P0323R <= 2
474 template< typename E = std::exception_ptr >
475 class unexpected_type
476 #else
477 template< typename E >
478 class unexpected_type
479 #endif // nsel_P0323R
480 {
481 public:
482  using error_type = E;
483 
484  unexpected_type() = delete;
485  constexpr unexpected_type( unexpected_type const &) = default;
486  constexpr unexpected_type( unexpected_type &&) = default;
487  nsel_constexpr14 unexpected_type& operator=( unexpected_type const &) = default;
488  nsel_constexpr14 unexpected_type& operator=( unexpected_type &&) = default;
489 
490  template< typename E2
492  std::is_constructible<E,E2&&>::value
493  )
494  >
495  constexpr explicit unexpected_type( E2 && error )
496  : m_error( std::forward<E2>( error ) )
497  {}
498 
499  template< typename E2 >
500  constexpr explicit unexpected_type( unexpected_type<E2> const & error
502  std::is_constructible<E,E2 const &>::value
503  && !std::is_convertible<E2 const &, E>::value /*=> explicit */ )
504  )
505  : m_error( error )
506  {}
507 
508  template< typename E2 >
509  constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> const & error
511  std::is_constructible<E,E2 const &>::value
512  && std::is_convertible<E2 const &, E>::value /*=> non-explicit */ )
513  )
514  : m_error( error )
515  {}
516 
517  template< typename E2 >
518  constexpr explicit unexpected_type( unexpected_type<E2> && error
520  std::is_constructible<E,E2&&>::value
521  && !std::is_convertible<E2&&, E>::value /*=> explicit */ )
522  )
523  : m_error( error )
524  {}
525 
526  template< typename E2 >
527  constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> && error
529  std::is_constructible<E,E2&&>::value
530  && std::is_convertible<E2&&, E>::value /*=> non-explicit */ )
531  )
532  : m_error( error )
533  {}
534 
535  nsel_constexpr14 E & value() & noexcept
536  {
537  return m_error;
538  }
539 
540  constexpr E const & value() const & noexcept
541  {
542  return m_error;
543  }
544 
545  nsel_constexpr14 E && value() && noexcept
546  {
547  return std::move( m_error );
548  }
549 
550  constexpr E const && value() const && noexcept
551  {
552  return std::move( m_error );
553  }
554 
555 // nsel_REQUIRES_A(
556 // std::is_move_constructible<E>::value
557 // && std::is_swappable<E>::value
558 // )
559 
560  void swap( unexpected_type & other ) noexcept (
562  std::is_nothrow_move_constructible<E>::value
563  && std::is_nothrow_swappable<E&>::value
564 #else
565  std::is_nothrow_move_constructible<E>::value
566  && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) )
567 #endif
568  )
569  {
570  using std::swap;
571  swap( m_error, other.m_error );
572  }
573 
574 private:
575  error_type m_error;
576 };
577 
579 
580 #if nsel_P0323R <= 2
581 
582 template<>
583 class unexpected_type< std::exception_ptr >
584 {
585 public:
586  using error_type = std::exception_ptr;
587 
588  unexpected_type() = delete;
589 
590  ~unexpected_type(){}
591 
592  explicit unexpected_type( std::exception_ptr const & error )
593  : m_error( error )
594  {}
595 
596  explicit unexpected_type(std::exception_ptr && error )
597  : m_error( std::move( error ) )
598  {}
599 
600  template< typename E >
601  explicit unexpected_type( E error )
602  : m_error( std::make_exception_ptr( error ) )
603  {}
604 
605  std::exception_ptr const & value() const
606  {
607  return m_error;
608  }
609 
610  std::exception_ptr & value()
611  {
612  return m_error;
613  }
614 
615 private:
616  std::exception_ptr m_error;
617 };
618 
619 #endif // nsel_P0323R
620 
622 
623 template< typename E >
624 constexpr bool operator==( unexpected_type<E> const & x, unexpected_type<E> const & y )
625 {
626  return x.value() == y.value();
627 }
628 
629 template< typename E >
630 constexpr bool operator!=( unexpected_type<E> const & x, unexpected_type<E> const & y )
631 {
632  return ! ( x == y );
633 }
634 
635 #if nsel_P0323R <= 2
636 
637 template< typename E >
638 constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y )
639 {
640  return x.value() < y.value();
641 }
642 
643 template< typename E >
644 constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y )
645 {
646  return ( y < x );
647 }
648 
649 template< typename E >
650 constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y )
651 {
652  return ! ( y < x );
653 }
654 
655 template< typename E >
656 constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y )
657 {
658  return ! ( x < y );
659 }
660 
662 
663 template< typename E >
664 void swap( unexpected_type<E> & x, unexpected_type<E> & y) noexcept ( noexcept ( x.swap(y) ) )
665 {
666  x.swap( y );
667 }
668 
669 // unexpected: relational operators for std::exception_ptr:
670 
671 inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
672 {
673  return false;
674 }
675 
676 inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
677 {
678  return false;
679 }
680 
681 inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
682 {
683  return ( x == y );
684 }
685 
686 inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
687 {
688  return ( x == y );
689 }
690 
691 #endif // nsel_P0323R
692 
693 // unexpected: traits
694 
695 #if nsel_P0323R <= 3
696 
697 template< typename E>
698 struct is_unexpected : std::false_type {};
699 
700 template< typename E>
701 struct is_unexpected< unexpected_type<E> > : std::true_type {};
702 
703 #endif // nsel_P0323R
704 
705 // unexpected: factory
706 
707 // keep make_unexpected() removed in p0323r2 for pre-C++17:
708 
709 template< typename E>
710 nsel_constexpr14 auto
711 make_unexpected( E && value ) -> unexpected_type< typename std::decay<E>::type >
712 {
713  return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
714 }
715 
716 #if nsel_P0323R <= 3
717 
718 /*nsel_constexpr14*/ auto inline
719 make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
720 {
721  return unexpected_type< std::exception_ptr >( std::current_exception() );
722 }
723 
724 #endif // nsel_P0323R
725 
727 
728 struct unexpect_t{};
729 using in_place_unexpected_t = unexpect_t;
730 
731 nsel_inline17 constexpr unexpect_t unexpect{};
732 nsel_inline17 constexpr unexpect_t in_place_unexpected{};
733 
735 
736 template< typename E >
737 class bad_expected_access;
738 
739 template <>
740 class bad_expected_access< void > : public std::exception
741 {
742 public:
743  explicit bad_expected_access()
744  : std::exception()
745  {}
746 };
747 
748 template< typename E >
749 class bad_expected_access : public bad_expected_access< void >
750 {
751 public:
752  using error_type = E;
753 
754  explicit bad_expected_access( error_type error )
755  : m_error( error )
756  {}
757 
758  virtual char const * what() const noexcept override
759  {
760  return "bad_expected_access";
761  }
762 
763  nsel_constexpr14 error_type & error() &
764  {
765  return m_error;
766  }
767 
768  constexpr error_type const & error() const &
769  {
770  return m_error;
771  }
772 
773  nsel_constexpr14 error_type && error() &&
774  {
775  return std::move( m_error );
776  }
777 
778  constexpr error_type const && error() const &&
779  {
780  return std::move( m_error );
781  }
782 
783 private:
784  error_type m_error;
785 };
786 
788 
789 template< typename Error >
790 struct error_traits
791 {
792  static void rethrow( Error const & e )
793  {
794  throw bad_expected_access<Error>{ e };
795  }
796 };
797 
798 template<>
799 struct error_traits< std::exception_ptr >
800 {
801  static void rethrow( std::exception_ptr const & e )
802  {
803  std::rethrow_exception( e );
804  }
805 };
806 
807 template<>
808 struct error_traits< std::error_code >
809 {
810  static void rethrow( std::error_code const & e )
811  {
812  throw std::system_error( e );
813  }
814 };
815 
816 } // namespace expected_lite
817 
818 // provide nonstd::unexpected_type:
819 
820 using expected_lite::unexpected_type;
821 
822 namespace expected_lite {
823 
825 
826 #if nsel_P0323R <= 2
827 template< typename T, typename E = std::exception_ptr >
828 class expected
829 #else
830 template< typename T, typename E >
831 class expected
832 #endif // nsel_P0323R
833 {
834 public:
835  using value_type = T;
836  using error_type = E;
837  using unexpected_type = nonstd::unexpected_type<E>;
838 
839  template< typename U >
840  struct rebind
841  {
842  using type = expected<U, error_type>;
843  };
844 
845  // x.x.4.1 constructors
846 
848  std::is_default_constructible<T>::value
849  )
850  nsel_constexpr14 expected() noexcept
851  (
852  std::is_nothrow_default_constructible<T>::value
853  )
854  : has_value_( true )
855  {
856  contained.construct_value( value_type() );
857  }
858 
859  nsel_constexpr14 expected( expected const & other
860 // nsel_REQUIRES_A(
861 // std::is_copy_constructible<T>::value
862 // && std::is_copy_constructible<E>::value
863 // )
864  )
865  : has_value_( other.has_value_ )
866  {
867  if ( has_value() ) contained.construct_value( other.contained.value() );
868  else contained.construct_error( other.contained.error() );
869  }
870 
871  nsel_constexpr14 expected( expected && other
872 // nsel_REQUIRES_A(
873 // std::is_move_constructible<T>::value
874 // && std::is_move_constructible<E>::value
875 // )
876  ) noexcept (
877  std::is_nothrow_move_constructible<T>::value
878  && std::is_nothrow_move_constructible<E>::value
879  )
880  : has_value_( other.has_value_ )
881  {
882  if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
883  else contained.construct_error( std::move( other.contained.error() ) );
884  }
885 
886  template< typename U, typename G >
887  nsel_constexpr14 explicit expected( expected<U, G> const & other
889  std::is_constructible<T, const U&>::value
890  && std::is_constructible<E, const G&>::value
891  && !std::is_constructible<T, expected<U, G>&>::value
892  && !std::is_constructible<T, expected<U, G>&&>::value
893  && !std::is_constructible<T, const expected<U, G>&>::value
894  && !std::is_constructible<T, const expected<U, G>&&>::value
895  && !std::is_convertible<expected<U, G>&, T>::value
896  && !std::is_convertible<expected<U, G>&&, T>::value
897  && !std::is_convertible<const expected<U, G>&, T>::value
898  && !std::is_convertible<const expected<U, G>&&, T>::value
899  && (!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) /*=> explicit */ )
900  )
901  : has_value_( other.has_value_ )
902  {
903  if ( has_value() ) contained.construct_value( other.contained.value() );
904  else contained.construct_error( other.contained.error() );
905  }
906 
907  template< typename U, typename G >
908  nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> const & other
910  std::is_constructible<T, const U&>::value
911  && std::is_constructible<E, const G&>::value
912  && !std::is_constructible<T, expected<U, G>&>::value
913  && !std::is_constructible<T, expected<U, G>&&>::value
914  && !std::is_constructible<T, const expected<U, G>&>::value
915  && !std::is_constructible<T, const expected<U, G>&&>::value
916  && !std::is_convertible<expected<U, G>&, T>::value
917  && !std::is_convertible<expected<U, G>&&, T>::value
918  && !std::is_convertible<const expected<U, G>&, T>::value
919  && !std::is_convertible<const expected<U, G>&&, T>::value
920  && !(!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) /*=> explicit */ )
921  )
922  : has_value_( other.has_value_ )
923  {
924  if ( has_value() ) contained.construct_value( other.contained.value() );
925  else contained.construct_error( other.contained.error() );
926  }
927 
928  template< typename U, typename G >
929  nsel_constexpr14 explicit expected( expected<U, G> && other
931  std::is_constructible<T, U>::value
932  && std::is_constructible<E, G>::value
933  && !std::is_constructible<T, expected<U, G>&>::value
934  && !std::is_constructible<T, expected<U, G>&&>::value
935  && !std::is_constructible<T, const expected<U, G>&>::value
936  && !std::is_constructible<T, const expected<U, G>&&>::value
937  && !std::is_convertible<expected<U, G>&, T>::value
938  && !std::is_convertible<expected<U, G>&&, T>::value
939  && !std::is_convertible<const expected<U, G>&, T>::value
940  && !std::is_convertible<const expected<U, G>&&, T>::value
941  && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> explicit */ )
942  )
943  : has_value_( other.has_value_ )
944  {
945  if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
946  else contained.construct_error( std::move( other.contained.error() ) );
947  }
948 
949  template< typename U, typename G >
950  nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> && other
952  std::is_constructible<T, U>::value
953  && std::is_constructible<E, G>::value
954  && !std::is_constructible<T, expected<U, G>&>::value
955  && !std::is_constructible<T, expected<U, G>&&>::value
956  && !std::is_constructible<T, const expected<U, G>&>::value
957  && !std::is_constructible<T, const expected<U, G>&&>::value
958  && !std::is_convertible<expected<U, G>&, T>::value
959  && !std::is_convertible<expected<U, G>&&, T>::value
960  && !std::is_convertible<const expected<U, G>&, T>::value
961  && !std::is_convertible<const expected<U, G>&&, T>::value
962  && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> non-explicit */ )
963  )
964  : has_value_( other.has_value_ )
965  {
966  if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
967  else contained.construct_error( std::move( other.contained.error() ) );
968  }
969 
970  nsel_constexpr14 expected( value_type const & value
971 // nsel_REQUIRES_A(
972 // std::is_copy_constructible<T>::value )
973  )
974  : has_value_( true )
975  {
976  contained.construct_value( value );
977  }
978 
979  template< typename U = T >
980  nsel_constexpr14 explicit expected( U && value
982  std::is_constructible<T,U&&>::value
983  && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
984  && !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value
985  && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
986  && !std::is_convertible<U&&,T>::value /*=> explicit */
987  )
988  ) noexcept
989  (
990  std::is_nothrow_move_constructible<U>::value &&
991  std::is_nothrow_move_constructible<E>::value
992  )
993  : has_value_( true )
994  {
995  contained.construct_value( std::forward<U>( value ) );
996  }
997 
998  template< typename U = T >
999  nsel_constexpr14 expected( U && value
1001  std::is_constructible<T,U&&>::value
1002  && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
1003  && !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value
1004  && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
1005  && std::is_convertible<U&&,T>::value /*=> non-explicit */
1006  )
1007  ) noexcept
1008  (
1009  std::is_nothrow_move_constructible<U>::value &&
1010  std::is_nothrow_move_constructible<E>::value
1011  )
1012  : has_value_( true )
1013  {
1014  contained.construct_value( std::forward<U>( value ) );
1015  }
1016 
1017  template< typename... Args
1019  std::is_constructible<T, Args&&...>::value
1020  )
1021  >
1022  nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), Args&&... args )
1023  : has_value_( true )
1024  {
1025  contained.construct_value( std::forward<Args>( args )... );
1026  }
1027 
1028  template< typename U, typename... Args
1030  std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
1031  )
1032  >
1033  nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
1034  : has_value_( true )
1035  {
1036  contained.construct_value( il, std::forward<Args>( args )... );
1037  }
1038 
1039  template< typename G = E >
1040  nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error
1042  !std::is_convertible<const G&, E>::value /*=> explicit */ )
1043  )
1044  : has_value_( false )
1045  {
1046  contained.construct_error( error.value() );
1047  }
1048 
1049  template< typename G = E >
1050  nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error
1052  std::is_convertible<const G&, E>::value /*=> non-explicit */ )
1053  )
1054  : has_value_( false )
1055  {
1056  contained.construct_error( error.value() );
1057  }
1058 
1059  template< typename G = E >
1060  nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error
1062  !std::is_convertible<G&&, E>::value /*=> explicit */ )
1063  )
1064  : has_value_( false )
1065  {
1066  contained.construct_error( std::move( error.value() ) );
1067  }
1068 
1069  template< typename G = E >
1070  nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error
1072  std::is_convertible<G&&, E>::value /*=> non-explicit */ )
1073  )
1074  : has_value_( false )
1075  {
1076  contained.construct_error( std::move( error.value() ) );
1077  }
1078 
1079  template< typename... Args
1081  std::is_constructible<E, Args&&...>::value
1082  )
1083  >
1084  nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
1085  : has_value_( false )
1086  {
1087  contained.construct_error( std::forward<Args>( args )... );
1088  }
1089 
1090  template< typename U, typename... Args
1092  std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
1093  )
1094  >
1095  nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
1096  : has_value_( false )
1097  {
1098  contained.construct_error( il, std::forward<Args>( args )... );
1099  }
1100 
1101  // x.x.4.2 destructor
1102 
1103  ~expected()
1104  {
1105  if ( has_value() ) contained.destruct_value();
1106  else contained.destruct_error();
1107  }
1108 
1109  // x.x.4.3 assignment
1110 
1111 // nsel_REQUIRES_A(
1112 // std::is_copy_constructible<T>::value &&
1113 // std::is_copy_assignable<T>::value &&
1114 // std::is_copy_constructible<E>::value &&
1115 // std::is_copy_assignable<E>::value )
1116 
1117  expected operator=( expected const & other )
1118  {
1119  expected( other ).swap( *this );
1120  return *this;
1121  }
1122 
1123 // nsel_REQUIRES_A(
1124 // std::is_move_constructible<T>::value &&
1125 // std::is_move_assignable<T>::value &&
1126 // std::is_move_constructible<E>::value &&
1127 // std::is_move_assignable<E>::value )
1128 
1129  expected & operator=( expected && other ) noexcept
1130  (
1131  std::is_nothrow_move_assignable<T>::value &&
1132  std::is_nothrow_move_constructible<T>::value&&
1133  std::is_nothrow_move_assignable<E>::value &&
1134  std::is_nothrow_move_constructible<E>::value )
1135  {
1136  expected( std::move( other ) ).swap( *this );
1137  return *this;
1138  }
1139 
1140  template< typename U
1142  std::is_constructible<T,U>::value &&
1143  std::is_assignable<T&, U>::value
1144  )
1145  >
1146  expected & operator=( U && value )
1147  {
1148  expected( std::forward<U>( value ) ).swap( *this );
1149  return *this;
1150  }
1151 
1152 // nsel_REQUIRES_A(
1153 // std::is_copy_constructible<E>::value &&
1154 // std::is_assignable<E&, E>::value )
1155 
1156  expected & operator=( unexpected_type const & uvalue )
1157  {
1158  expected( std::move( uvalue ) ).swap( *this );
1159  return *this;
1160  }
1161 
1162 // nsel_REQUIRES_A(
1163 // std::is_copy_constructible<E>::value &&
1164 // std::is_assignable<E&, E>::value )
1165 
1166  expected & operator=( unexpected_type && uvalue )
1167  {
1168  expected( std::move( uvalue ) ).swap( *this );
1169  return *this;
1170  }
1171 
1172  template< typename... Args
1174  std::is_constructible<T, Args&&...>::value
1175  )
1176  >
1177  void emplace( Args &&... args )
1178  {
1179  expected( nonstd_lite_in_place(T), std::forward<Args>(args)... ).swap( *this );
1180  }
1181 
1182  template< typename U, typename... Args
1184  std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
1185  )
1186  >
1187  void emplace( std::initializer_list<U> il, Args &&... args )
1188  {
1189  expected( nonstd_lite_in_place(T), il, std::forward<Args>(args)... ).swap( *this );
1190  }
1191 
1192  // x.x.4.4 swap
1193 
1194 // nsel_REQUIRES_A(
1195 // std::is_move_constructible<T>::value &&
1196 // std::is_move_constructible<E>::value )
1197 
1198  void swap( expected & other ) noexcept
1199  (
1201  std::is_nothrow_move_constructible<T>::value && std::is_nothrow_swappable<T&>::value &&
1202  std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value
1203 #else
1204  std::is_nothrow_move_constructible<T>::value && noexcept ( std::swap( std::declval<T&>(), std::declval<T&>() ) ) &&
1205  std::is_nothrow_move_constructible<E>::value && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) )
1206 #endif
1207  )
1208  {
1209  using std::swap;
1210 
1211  if ( bool(*this) && bool(other) ) { swap( contained.value(), other.contained.value() ); }
1212  else if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
1213  else if ( bool(*this) && ! bool(other) ) { error_type t( std::move( other.error() ) );
1214  other.contained.destruct_error();
1215  other.contained.construct_value( std::move( contained.value() ) );
1216  contained.destruct_value();
1217  contained.construct_error( std::move( t ) );
1218  swap( has_value_, other.has_value_ ); }
1219  else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
1220  }
1221 
1222  // x.x.4.5 observers
1223 
1224  constexpr value_type const * operator ->() const
1225  {
1226  return assert( has_value() ), contained.value_ptr();
1227  }
1228 
1229  value_type * operator ->()
1230  {
1231  return assert( has_value() ), contained.value_ptr();
1232  }
1233 
1234  constexpr value_type const & operator *() const &
1235  {
1236  return assert( has_value() ), contained.value();
1237  }
1238 
1239  value_type & operator *() &
1240  {
1241  return assert( has_value() ), contained.value();
1242  }
1243 
1244  constexpr value_type const && operator *() const &&
1245  {
1246  return assert( has_value() ), std::move( contained.value() );
1247  }
1248 
1249  nsel_constexpr14 value_type && operator *() &&
1250  {
1251  return assert( has_value() ), std::move( contained.value() );
1252  }
1253 
1254  constexpr explicit operator bool() const noexcept
1255  {
1256  return has_value();
1257  }
1258 
1259  constexpr bool has_value() const noexcept
1260  {
1261  return has_value_;
1262  }
1263 
1264  constexpr value_type const & value() const &
1265  {
1266  return has_value()
1267  ? ( contained.value() )
1268  : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
1269  }
1270 
1271  value_type & value() &
1272  {
1273  return has_value()
1274  ? ( contained.value() )
1275  : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
1276  }
1277 
1278  constexpr value_type const && value() const &&
1279  {
1280  return std::move( has_value()
1281  ? ( contained.value() )
1282  : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
1283  }
1284 
1285  nsel_constexpr14 value_type && value() &&
1286  {
1287  return std::move( has_value()
1288  ? ( contained.value() )
1289  : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
1290  }
1291 
1292  constexpr error_type const & error() const &
1293  {
1294  return assert( ! has_value() ), contained.error();
1295  }
1296 
1297  error_type & error() &
1298  {
1299  return assert( ! has_value() ), contained.error();
1300  }
1301 
1302  constexpr error_type const && error() const &&
1303  {
1304  return assert( ! has_value() ), std::move( contained.error() );
1305  }
1306 
1307  error_type && error() &&
1308  {
1309  return assert( ! has_value() ), std::move( contained.error() );
1310  }
1311 
1312  constexpr unexpected_type get_unexpected() const
1313  {
1314  return make_unexpected( contained.error() );
1315  }
1316 
1317  template< typename Ex >
1318  bool has_exception() const
1319  {
1320  using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type;
1321  return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
1322  }
1323 
1324  template< typename U
1326  std::is_copy_constructible<T>::value &&
1327  std::is_convertible<U&&, T>::value
1328  )
1329  >
1330  value_type value_or( U && v ) const &
1331  {
1332  return has_value()
1333  ? contained.value()
1334  : static_cast<T>( std::forward<U>( v ) );
1335  }
1336 
1337  template< typename U
1339  std::is_move_constructible<T>::value &&
1340  std::is_convertible<U&&, T>::value
1341  )
1342  >
1343  value_type value_or( U && v ) &&
1344  {
1345  return has_value()
1346  ? std::move( contained.value() )
1347  : static_cast<T>( std::forward<U>( v ) );
1348  }
1349 
1350  // unwrap()
1351 
1352 // template <class U, class E>
1353 // constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
1354 
1355 // template <class T, class E>
1356 // constexpr expected<T,E> expected<T,E>::unwrap() const&;
1357 
1358 // template <class U, class E>
1359 // expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
1360 
1361 // template <class T, class E>
1362 // template expected<T,E> expected<T,E>::unwrap() &&;
1363 
1364  // factories
1365 
1366 // template< typename Ex, typename F>
1367 // expected<T,E> catch_exception(F&& f);
1368 
1369 // template< typename F>
1370 // expected<decltype(func(declval<T>())),E> map(F&& func) ;
1371 
1372 // template< typename F>
1373 // 'see below' bind(F&& func);
1374 
1375 // template< typename F>
1376 // expected<T,E> catch_error(F&& f);
1377 
1378 // template< typename F>
1379 // 'see below' then(F&& func);
1380 
1381 private:
1382  bool has_value_;
1383  detail::storage_t<T,E> contained;
1384 };
1385 
1387 
1388 template< typename E >
1389 class expected<void, E>
1390 {
1391 public:
1392  using value_type = void;
1393  using error_type = E;
1394  using unexpected_type = nonstd::unexpected_type<E>;
1395 
1396  // x.x.4.1 constructors
1397 
1398  constexpr expected() noexcept
1399  : has_value_( true )
1400  {
1401  }
1402 
1403  nsel_constexpr14 expected( expected const & other )
1404  : has_value_( other.has_value_ )
1405  {
1406  if ( ! has_value() ) contained.construct_error( other.contained.error() );
1407  }
1408 
1410  std::is_move_constructible<E>::value
1411  )
1412  nsel_constexpr14 expected( expected && other ) noexcept
1413  (
1414  true // TBD - see also non-void specialization
1415  )
1416  : has_value_( other.has_value_ )
1417  {
1418  if ( ! has_value() ) contained.construct_error( std::move( other.contained.error() ) );
1419  }
1420 
1421  constexpr explicit expected( nonstd_lite_in_place_t(void) )
1422  : has_value_( true )
1423  {
1424  }
1425 
1426  template< typename G = E >
1427  nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error
1429  !std::is_convertible<const G&, E>::value /*=> explicit */
1430  )
1431  )
1432  : has_value_( false )
1433  {
1434  contained.construct_error( error.value() );
1435  }
1436 
1437  template< typename G = E >
1438  nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error
1440  std::is_convertible<const G&, E>::value /*=> non-explicit */
1441  )
1442  )
1443  : has_value_( false )
1444  {
1445  contained.construct_error( error.value() );
1446  }
1447 
1448  template< typename G = E >
1449  nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error
1451  !std::is_convertible<G&&, E>::value /*=> explicit */
1452  )
1453  )
1454  : has_value_( false )
1455  {
1456  contained.construct_error( std::move( error.value() ) );
1457  }
1458 
1459  template< typename G = E >
1460  nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error
1462  std::is_convertible<G&&, E>::value /*=> non-explicit */
1463  )
1464  )
1465  : has_value_( false )
1466  {
1467  contained.construct_error( std::move( error.value() ) );
1468  }
1469 
1470  template< typename... Args
1472  std::is_constructible<E, Args&&...>::value
1473  )
1474  >
1475  nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
1476  : has_value_( false )
1477  {
1478  contained.construct_error( std::forward<Args>( args )... );
1479  }
1480 
1481  template< typename U, typename... Args
1483  std::is_constructible<U, std::initializer_list<U>, Args&&...>::value
1484  )
1485  >
1486  nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
1487  : has_value_( false )
1488  {
1489  contained.construct_error( il, std::forward<Args>( args )... );
1490  }
1491 
1492 
1493  // destructor
1494 
1495  ~expected()
1496  {
1497  if ( ! has_value() ) contained.destruct_error();
1498  }
1499 
1500  // x.x.4.3 assignment
1501 
1502 // nsel_REQUIRES_A(
1503 // std::is_copy_constructible<E>::value &&
1504 // std::is_copy_assignable<E>::value )
1505 
1506  expected & operator=( expected const & other )
1507  {
1508  expected( other ).swap( *this );
1509  return *this;
1510  }
1511 
1512 // nsel_REQUIRES_A(
1513 // std::is_move_constructible<E>::value &&
1514 // std::is_move_assignable<E>::value )
1515 
1516  expected & operator=( expected && other ) noexcept
1517  (
1518  std::is_nothrow_move_assignable<E>::value &&
1519  std::is_nothrow_move_constructible<E>::value )
1520  {
1521  expected( std::move( other ) ).swap( *this );
1522  return *this;
1523  }
1524 
1525  void emplace()
1526  {}
1527 
1528  // x.x.4.4 swap
1529 
1530 // nsel_REQUIRES_A(
1531 // std::is_move_constructible<E>::value )
1532 
1533  void swap( expected & other ) noexcept
1534  (
1536  std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value
1537 #else
1538  std::is_nothrow_move_constructible<E>::value && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) )
1539 #endif
1540  )
1541  {
1542  using std::swap;
1543 
1544  if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
1545  else if ( bool(*this) && ! bool(other) ) { contained.construct_error( std::move( other.error() ) );
1546  swap( has_value_, other.has_value_ ); }
1547  else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
1548  }
1549 
1550  // x.x.4.5 observers
1551 
1552  constexpr explicit operator bool() const noexcept
1553  {
1554  return has_value();
1555  }
1556 
1557  constexpr bool has_value() const noexcept
1558  {
1559  return has_value_;
1560  }
1561 
1562  void value() const
1563  {}
1564 
1565  constexpr error_type const & error() const &
1566  {
1567  return assert( ! has_value() ), contained.error();
1568  }
1569 
1570  error_type & error() &
1571  {
1572  return assert( ! has_value() ), contained.error();
1573  }
1574 
1575  constexpr error_type const && error() const &&
1576  {
1577  return assert( ! has_value() ), std::move( contained.error() );
1578  }
1579 
1580  error_type && error() &&
1581  {
1582  return assert( ! has_value() ), std::move( contained.error() );
1583  }
1584 
1585  constexpr unexpected_type get_unexpected() const
1586  {
1587  return make_unexpected( contained.error() );
1588  }
1589 
1590  template< typename Ex >
1591  bool has_exception() const
1592  {
1593  return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value;
1594  }
1595 
1596 // template constexpr 'see below' unwrap() const&;
1597 //
1598 // template 'see below' unwrap() &&;
1599 
1600  // factories
1601 
1602 // template< typename Ex, typename F>
1603 // expected<void,E> catch_exception(F&& f);
1604 //
1605 // template< typename F>
1606 // expected<decltype(func()), E> map(F&& func) ;
1607 //
1608 // template< typename F>
1609 // 'see below' bind(F&& func) ;
1610 //
1611 // template< typename F>
1612 // expected<void,E> catch_error(F&& f);
1613 //
1614 // template< typename F>
1615 // 'see below' then(F&& func);
1616 
1617 private:
1618  bool has_value_;
1619  detail::storage_t<void,E> contained;
1620 };
1621 
1622 // expected: relational operators
1623 
1624 template< typename T, typename E >
1625 constexpr bool operator==( expected<T,E> const & x, expected<T,E> const & y )
1626 {
1627  return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
1628 }
1629 
1630 template< typename T, typename E >
1631 constexpr bool operator!=( expected<T,E> const & x, expected<T,E> const & y )
1632 {
1633  return !(x == y);
1634 }
1635 
1636 template< typename T, typename E >
1637 constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y )
1638 {
1639  return (!y) ? false : (!x) ? true : *x < *y;
1640 }
1641 
1642 template< typename T, typename E >
1643 constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y )
1644 {
1645  return (y < x);
1646 }
1647 
1648 template< typename T, typename E >
1649 constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y )
1650 {
1651  return !(y < x);
1652 }
1653 
1654 template< typename T, typename E >
1655 constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y )
1656 {
1657  return !(x < y);
1658 }
1659 
1660 // expected: comparison with unexpected_type
1661 
1662 template< typename T, typename E >
1663 constexpr bool operator==( expected<T,E> const & x, unexpected_type<E> const & u )
1664 {
1665  return (!x) ? x.get_unexpected() == u : false;
1666 }
1667 
1668 template< typename T, typename E >
1669 constexpr bool operator==( unexpected_type<E> const & u, expected<T,E> const & x )
1670 {
1671  return ( x == u );
1672 }
1673 
1674 template< typename T, typename E >
1675 constexpr bool operator!=( expected<T,E> const & x, unexpected_type<E> const & u )
1676 {
1677  return ! ( x == u );
1678 }
1679 
1680 template< typename T, typename E >
1681 constexpr bool operator!=( unexpected_type<E> const & u, expected<T,E> const & x )
1682 {
1683  return ! ( x == u );
1684 }
1685 
1686 template< typename T, typename E >
1687 constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u )
1688 {
1689  return (!x) ? ( x.get_unexpected() < u ) : false;
1690 }
1691 
1692 #if nsel_P0323R <= 2
1693 
1694 template< typename T, typename E >
1695 constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x )
1696 {
1697  return (!x) ? ( u < x.get_unexpected() ) : true ;
1698 }
1699 
1700 template< typename T, typename E >
1701 constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u )
1702 {
1703  return ( u < x );
1704 }
1705 
1706 template< typename T, typename E >
1707 constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x )
1708 {
1709  return ( x < u );
1710 }
1711 
1712 template< typename T, typename E >
1713 constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u )
1714 {
1715  return ! ( u < x );
1716 }
1717 
1718 template< typename T, typename E >
1719 constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x)
1720 {
1721  return ! ( x < u );
1722 }
1723 
1724 template< typename T, typename E >
1725 constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u )
1726 {
1727  return ! ( u > x );
1728 }
1729 
1730 template< typename T, typename E >
1731 constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x )
1732 {
1733  return ! ( x > u );
1734 }
1735 
1736 #endif // nsel_P0323R
1737 
1738 // expected: comparison with T
1739 
1740 template< typename T, typename E >
1741 constexpr bool operator==( expected<T,E> const & x, T const & v )
1742 {
1743  return bool(x) ? *x == v : false;
1744 }
1745 
1746 template< typename T, typename E >
1747 constexpr bool operator==(T const & v, expected<T,E> const & x )
1748 {
1749  return bool(x) ? v == *x : false;
1750 }
1751 
1752 template< typename T, typename E >
1753 constexpr bool operator!=( expected<T,E> const & x, T const & v )
1754 {
1755  return bool(x) ? *x != v : true;
1756 }
1757 
1758 template< typename T, typename E >
1759 constexpr bool operator!=( T const & v, expected<T,E> const & x )
1760 {
1761  return bool(x) ? v != *x : true;
1762 }
1763 
1764 template< typename T, typename E >
1765 constexpr bool operator<( expected<T,E> const & x, T const & v )
1766 {
1767  return bool(x) ? *x < v : true;
1768 }
1769 
1770 template< typename T, typename E >
1771 constexpr bool operator<( T const & v, expected<T,E> const & x )
1772 {
1773  return bool(x) ? v < *x : false;
1774 }
1775 
1776 template< typename T, typename E >
1777 constexpr bool operator>( T const & v, expected<T,E> const & x )
1778 {
1779  return bool(x) ? *x < v : false;
1780 }
1781 
1782 template< typename T, typename E >
1783 constexpr bool operator>( expected<T,E> const & x, T const & v )
1784 {
1785  return bool(x) ? v < *x : false;
1786 }
1787 
1788 template< typename T, typename E >
1789 constexpr bool operator<=( T const & v, expected<T,E> const & x )
1790 {
1791  return bool(x) ? ! ( *x < v ) : false;
1792 }
1793 
1794 template< typename T, typename E >
1795 constexpr bool operator<=( expected<T,E> const & x, T const & v )
1796 {
1797  return bool(x) ? ! ( v < *x ) : true;
1798 }
1799 
1800 template< typename T, typename E >
1801 constexpr bool operator>=( expected<T,E> const & x, T const & v )
1802 {
1803  return bool(x) ? ! ( *x < v ) : false;
1804 }
1805 
1806 template< typename T, typename E >
1807 constexpr bool operator>=( T const & v, expected<T,E> const & x )
1808 {
1809  return bool(x) ? ! ( v < *x ) : true;
1810 }
1811 
1813 
1814 template< typename T, typename E >
1815 void swap( expected<T,E> & x, expected<T,E> & y ) noexcept ( noexcept ( x.swap(y) ) )
1816 {
1817  x.swap( y );
1818 }
1819 
1820 #if nsel_P0323R <= 3
1821 
1822 template< typename T >
1823 constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
1824 {
1825  return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
1826 }
1827 
1828 // expected<void> specialization:
1829 
1830 auto inline make_expected() -> expected<void>
1831 {
1832  return expected<void>( in_place );
1833 }
1834 
1835 template< typename T >
1836 constexpr auto make_expected_from_current_exception() -> expected<T>
1837 {
1838  return expected<T>( make_unexpected_from_current_exception() );
1839 }
1840 
1841 template< typename T >
1842 auto make_expected_from_exception( std::exception_ptr v ) -> expected<T>
1843 {
1844  return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) );
1845 }
1846 
1847 template< typename T, typename E >
1848 constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
1849 {
1850  return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
1851 }
1852 
1853 template< typename F >
1854 /*nsel_constexpr14*/
1855 auto make_expected_from_call( F f,
1856  nsel_REQUIRES_A( ! std::is_same<typename std::result_of<F()>::type, void>::value )
1857 ) -> expected< typename std::result_of<F()>::type >
1858 {
1859  try
1860  {
1861  return make_expected( f() );
1862  }
1863  catch (...)
1864  {
1865  return make_unexpected_from_current_exception();
1866  }
1867 }
1868 
1869 template< typename F >
1870 /*nsel_constexpr14*/
1871 auto make_expected_from_call( F f,
1872  nsel_REQUIRES_A( std::is_same<typename std::result_of<F()>::type, void>::value )
1873 ) -> expected<void>
1874 {
1875  try
1876  {
1877  f();
1878  return make_expected();
1879  }
1880  catch (...)
1881  {
1882  return make_unexpected_from_current_exception();
1883  }
1884 }
1885 
1886 #endif // nsel_P0323R
1887 
1888 } // namespace expected_lite
1889 
1890 using namespace expected_lite;
1891 
1892 // using expected_lite::expected;
1893 // using ...
1894 
1895 } // namespace nonstd
1896 
1897 namespace std {
1898 
1899 // expected: hash support
1900 
1901 template< typename T, typename E >
1902 struct hash< nonstd::expected<T,E> >
1903 {
1904  using result_type = typename hash<T>::result_type;
1905  using argument_type = nonstd::expected<T,E>;
1906 
1907  constexpr result_type operator()(argument_type const & arg) const
1908  {
1909  return arg ? std::hash<T>{}(*arg) : result_type{};
1910  }
1911 };
1912 
1913 // TBD - ?? remove? see spec.
1914 template< typename T, typename E >
1915 struct hash< nonstd::expected<T&,E> >
1916 {
1917  using result_type = typename hash<T>::result_type;
1918  using argument_type = nonstd::expected<T&,E>;
1919 
1920  constexpr result_type operator()(argument_type const & arg) const
1921  {
1922  return arg ? std::hash<T>{}(*arg) : result_type{};
1923  }
1924 };
1925 
1926 // TBD - implement
1927 // bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true;
1928 // otherwise it evaluates to an unspecified value if E is exception_ptr or
1929 // a combination of hashing false and hash<E>()(e.error()).
1930 
1931 template< typename E >
1932 struct hash< nonstd::expected<void,E> >
1933 {
1934 };
1935 
1936 } // namespace std
1937 
1938 namespace nonstd {
1939 
1940 // void unexpected() is deprecated && removed in C++17
1941 
1942 #if nsel_CPP17_OR_GREATER && nsel_COMPILER_MSVC_VERSION > 141
1943 template< typename E >
1944 using unexpected = unexpected_type<E>;
1945 #endif
1946 
1947 } // namespace nonstd
1948 
1949 #undef nsel_REQUIRES
1950 #undef nsel_REQUIRES_0
1951 #undef nsel_REQUIRES_T
1952 
1954 
1955 #endif // nsel_USES_STD_EXPECTED
1956 
1957 #endif // NONSTD_EXPECTED_LITE_HPP
#define nsel_constexpr14
Definition: expected.hpp:209
nonstd::expected< T &, E > argument_type
Definition: expected.hpp:1918
nonstd::expected< T, E > argument_type
Definition: expected.hpp:1905
Definition: any.hpp:455
void swap(linb::any &lhs, linb::any &rhs) noexcept
Definition: any.hpp:457
in_place_t in_place(detail::in_place_index_tag< K >=detail::in_place_index_tag< K >())
Definition: expected.hpp:142
#define nsel_REQUIRES_0(...)
Definition: expected.hpp:223
bool operator>=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
#define nsel_DISABLE_MSVC_WARNINGS(codes)
Definition: expected.hpp:292
#define nonstd_lite_in_place(T)
Definition: expected.hpp:165
in_place_t in_place_index(detail::in_place_index_tag< K >=detail::in_place_index_tag< K >())
Definition: expected.hpp:154
typename hash< T >::result_type result_type
Definition: expected.hpp:1917
bool operator>(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
#define nsel_REQUIRES_T(...)
Definition: expected.hpp:229
#define nsel_inline17
Definition: expected.hpp:215
#define nsel_RESTORE_WARNINGS()
Definition: expected.hpp:302
constexpr result_type operator()(argument_type const &arg) const
Definition: expected.hpp:1907
bool operator==(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
void swap(message_t &a, message_t &b) ZMQ_NOTHROW
in_place_t in_place_type(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())
Definition: expected.hpp:148
bool operator!=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
#define nsel_CPP17_OR_GREATER
Definition: expected.hpp:69
constexpr result_type operator()(argument_type const &arg) const
Definition: expected.hpp:1920
#define nonstd_lite_in_place_t(T)
Definition: expected.hpp:161
#define nsel_REQUIRES_A(...)
Definition: expected.hpp:220
typename hash< T >::result_type result_type
Definition: expected.hpp:1904
in_place_t in_place(detail::in_place_type_tag< T >=detail::in_place_type_tag< T >())
Definition: expected.hpp:136


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:24