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