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


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Mon Jul 3 2023 02:50:14