expected.hpp
Go to the documentation of this file.
00001 // This version targets C++11 and later.
00002 //
00003 // Copyright (C) 2016-2018 Martin Moene.
00004 //
00005 // Distributed under the Boost Software License, Version 1.0.
00006 // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00007 //
00008 // expected lite is based on:
00009 //   A proposal to add a utility class to represent expected monad
00010 //   by Vicente J. Botet Escriba and Pierre Talbot. http:://wg21.link/p0323
00011 
00012 #ifndef NONSTD_EXPECTED_LITE_HPP
00013 #define NONSTD_EXPECTED_LITE_HPP
00014 
00015 #define expected_lite_MAJOR  0
00016 #define expected_lite_MINOR  2
00017 #define expected_lite_PATCH  0
00018 
00019 #define expected_lite_VERSION  expected_STRINGIFY(expected_lite_MAJOR) "." expected_STRINGIFY(expected_lite_MINOR) "." expected_STRINGIFY(expected_lite_PATCH)
00020 
00021 #define expected_STRINGIFY(  x )  expected_STRINGIFY_( x )
00022 #define expected_STRINGIFY_( x )  #x
00023 
00024 // expected-lite configuration:
00025 
00026 #define nsel_EXPECTED_DEFAULT  0
00027 #define nsel_EXPECTED_NONSTD   1
00028 #define nsel_EXPECTED_STD      2
00029 
00030 #if !defined( nsel_CONFIG_SELECT_EXPECTED )
00031 # define nsel_CONFIG_SELECT_EXPECTED  ( nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD )
00032 #endif
00033 
00034 // Proposal revisions:
00035 //
00036 // DXXXXR0: --
00037 // N4015  : -2 (2014-05-26)
00038 // N4109  : -1 (2014-06-29)
00039 // P0323R0:  0 (2016-05-28)
00040 // P0323R1:  1 (2016-10-12)
00041 // -------:
00042 // P0323R2:  2 (2017-06-15)
00043 // P0323R3:  3 (2017-10-15)
00044 // P0323R4:  4 (2017-11-26)
00045 // P0323R5:  5 (2018-02-08) *
00046 // P0323R6:  6 (2018-04-02)
00047 // P0323R7:  7 (2018-06-22)
00048 //
00049 // expected-lite uses 2 and higher
00050 
00051 #ifndef  nsel_P0323R
00052 # define nsel_P0323R  5
00053 #endif
00054 
00055 // C++ language version detection (C++20 is speculative):
00056 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
00057 
00058 #ifndef   nsel_CPLUSPLUS
00059 # if defined(_MSVC_LANG ) && !defined(__clang__)
00060 #  define nsel_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
00061 # else
00062 #  define nsel_CPLUSPLUS  __cplusplus
00063 # endif
00064 #endif
00065 
00066 #define nsel_CPP98_OR_GREATER  ( nsel_CPLUSPLUS >= 199711L )
00067 #define nsel_CPP11_OR_GREATER  ( nsel_CPLUSPLUS >= 201103L )
00068 #define nsel_CPP14_OR_GREATER  ( nsel_CPLUSPLUS >= 201402L )
00069 #define nsel_CPP17_OR_GREATER  ( nsel_CPLUSPLUS >= 201703L )
00070 #define nsel_CPP20_OR_GREATER  ( nsel_CPLUSPLUS >= 202000L )
00071 
00072 // Use C++20 std::expected if available and requested:
00073 
00074 #if nsel_CPP20_OR_GREATER && defined(__has_include )
00075 # if __has_include( <expected> )
00076 #  define nsel_HAVE_STD_EXPECTED  1
00077 # else
00078 #  define nsel_HAVE_STD_EXPECTED  0
00079 # endif
00080 #else
00081 # define  nsel_HAVE_STD_EXPECTED  0
00082 #endif
00083 
00084 #define  nsel_USES_STD_EXPECTED  ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) )
00085 
00086 //
00087 // in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
00088 //
00089 
00090 #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
00091 #define nonstd_lite_HAVE_IN_PLACE_TYPES  1
00092 
00093 // C++17 std::in_place in <utility>:
00094 
00095 #if nsel_CPP17_OR_GREATER
00096 
00097 #include <utility>
00098 
00099 namespace nonstd {
00100 
00101 using std::in_place;
00102 using std::in_place_type;
00103 using std::in_place_index;
00104 using std::in_place_t;
00105 using std::in_place_type_t;
00106 using std::in_place_index_t;
00107 
00108 #define nonstd_lite_in_place_t(      T)  std::in_place_t
00109 #define nonstd_lite_in_place_type_t( T)  std::in_place_type_t<T>
00110 #define nonstd_lite_in_place_index_t(K)  std::in_place_index_t<K>
00111 
00112 #define nonstd_lite_in_place(      T)    std::in_place_t{}
00113 #define nonstd_lite_in_place_type( T)    std::in_place_type_t<T>{}
00114 #define nonstd_lite_in_place_index(K)    std::in_place_index_t<K>{}
00115 
00116 } // namespace nonstd
00117 
00118 #else // nsel_CPP17_OR_GREATER
00119 
00120 #include <cstddef>
00121 
00122 namespace nonstd {
00123 namespace detail {
00124 
00125 template< class T >
00126 struct in_place_type_tag {};
00127 
00128 template< std::size_t K >
00129 struct in_place_index_tag {};
00130 
00131 } // namespace detail
00132 
00133 struct in_place_t {};
00134 
00135 template< class T >
00136 inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
00137 {
00138     return in_place_t();
00139 }
00140 
00141 template< std::size_t K >
00142 inline in_place_t in_place( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
00143 {
00144     return in_place_t();
00145 }
00146 
00147 template< class T >
00148 inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
00149 {
00150     return in_place_t();
00151 }
00152 
00153 template< std::size_t K >
00154 inline in_place_t in_place_index( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
00155 {
00156     return in_place_t();
00157 }
00158 
00159 // mimic templated typedef:
00160 
00161 #define nonstd_lite_in_place_t(      T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
00162 #define nonstd_lite_in_place_type_t( T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
00163 #define nonstd_lite_in_place_index_t(K)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
00164 
00165 #define nonstd_lite_in_place(      T)    nonstd::in_place_type<T>
00166 #define nonstd_lite_in_place_type( T)    nonstd::in_place_type<T>
00167 #define nonstd_lite_in_place_index(K)    nonstd::in_place_index<K>
00168 
00169 } // namespace nonstd
00170 
00171 #endif // nsel_CPP17_OR_GREATER
00172 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
00173 
00174 //
00175 // Using std::expected:
00176 //
00177 
00178 #if nsel_USES_STD_EXPECTED
00179 
00180 #include <expected>
00181 
00182 namespace nonstd {
00183 
00184     using std::expected;
00185 //  ...
00186 }
00187 
00188 #else // nsel_USES_STD_EXPECTED
00189 
00190 #include <cassert>
00191 #include <exception>
00192 #include <functional>
00193 #include <initializer_list>
00194 #include <new>
00195 #include <stdexcept>
00196 #include <system_error>
00197 #include <type_traits>
00198 #include <utility>
00199 
00200 #if nsel_CPP11_OR_GREATER
00201 # define nsel_constexpr  constexpr
00202 #else
00203 # define nsel_constexpr  /*constexpr*/
00204 #endif
00205 
00206 #if nsel_CPP14_OR_GREATER
00207 # define nsel_constexpr14 constexpr
00208 #else
00209 # define nsel_constexpr14 /*constexpr*/
00210 #endif
00211 
00212 #if nsel_CPP17_OR_GREATER
00213 # define nsel_inline17 inline
00214 #else
00215 # define nsel_inline17 /*inline*/
00216 #endif
00217 
00218 // Method enabling
00219 
00220 #define nsel_REQUIRES_A(...) \
00221     , typename std::enable_if<__VA_ARGS__, void*>::type = nullptr
00222 
00223 #define nsel_REQUIRES_0(...) \
00224     template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
00225 
00226 #define nsel_REQUIRES_R(R, ...) \
00227     typename std::enable_if<__VA_ARGS__, R>::type
00228 
00229 #define nsel_REQUIRES_T(...) \
00230     , typename = typename std::enable_if< (__VA_ARGS__), nonstd::expected_lite::detail::enabler >::type
00231 
00232 // Compiler versions:
00233 //
00234 // MSVC++ 6.0  _MSC_VER == 1200 (Visual Studio 6.0)
00235 // MSVC++ 7.0  _MSC_VER == 1300 (Visual Studio .NET 2002)
00236 // MSVC++ 7.1  _MSC_VER == 1310 (Visual Studio .NET 2003)
00237 // MSVC++ 8.0  _MSC_VER == 1400 (Visual Studio 2005)
00238 // MSVC++ 9.0  _MSC_VER == 1500 (Visual Studio 2008)
00239 // MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
00240 // MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
00241 // MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
00242 // MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
00243 // MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
00244 
00245 #if defined(_MSC_VER) && !defined(__clang__)
00246 # define nsel_COMPILER_MSVC_VER      (_MSC_VER )
00247 # define nsel_COMPILER_MSVC_VERSION  (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) )
00248 #else
00249 # define nsel_COMPILER_MSVC_VER      0
00250 # define nsel_COMPILER_MSVC_VERSION  0
00251 #endif
00252 
00253 #define nsel_COMPILER_VERSION( major, minor, patch )  ( 10 * ( 10 * (major) + (minor) ) + (patch) )
00254 
00255 #if defined(__clang__)
00256 # define nsel_COMPILER_CLANG_VERSION  nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
00257 #else
00258 # define nsel_COMPILER_CLANG_VERSION  0
00259 #endif
00260 
00261 #if defined(__GNUC__) && !defined(__clang__)
00262 # define nsel_COMPILER_GNUC_VERSION  nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
00263 #else
00264 # define nsel_COMPILER_GNUC_VERSION  0
00265 #endif
00266 
00267 // half-open range [lo..hi):
00268 //#define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
00269 
00270 // Presence of language and library features:
00271 
00272 #ifdef _HAS_CPP0X
00273 # define nsel_HAS_CPP0X  _HAS_CPP0X
00274 #else
00275 # define nsel_HAS_CPP0X  0
00276 #endif
00277 
00278 //#define nsel_CPP11_140  (nsel_CPP11_OR_GREATER || nsel_COMPILER_MSVC_VER >= 1900)
00279 
00280 // Clang, GNUC, MSVC warning suppression macros:
00281 
00282 #ifdef __clang__
00283 # pragma clang diagnostic push
00284 #elif defined  __GNUC__
00285 # pragma  GCC  diagnostic push
00286 #endif // __clang__
00287 
00288 #if nsel_COMPILER_MSVC_VERSION >= 140
00289 # pragma warning( push )
00290 # define nsel_DISABLE_MSVC_WARNINGS(codes)  __pragma( warning(disable: codes) )
00291 #else
00292 # define nsel_DISABLE_MSVC_WARNINGS(codes)
00293 #endif
00294 
00295 #ifdef __clang__
00296 # define nsel_RESTORE_WARNINGS()  _Pragma("clang diagnostic pop")
00297 #elif defined __GNUC__
00298 # define nsel_RESTORE_WARNINGS()  _Pragma("GCC diagnostic pop")
00299 #elif nsel_COMPILER_MSVC_VERSION >= 140
00300 # define nsel_RESTORE_WARNINGS()  __pragma( warning( pop ) )
00301 #else
00302 # define nsel_RESTORE_WARNINGS()
00303 #endif
00304 
00305 // Suppress the following MSVC (GSL) warnings:
00306 // - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11)
00307 
00308 nsel_DISABLE_MSVC_WARNINGS( 26409 )
00309 
00310 //
00311 // expected:
00312 //
00313 
00314 namespace nonstd { namespace expected_lite {
00315 
00316 namespace std20 {
00317 
00318 // type traits C++20:
00319 
00320 template< typename T >
00321 struct remove_cvref
00322 {
00323     typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
00324 };
00325 
00326 } // namespace std20
00327 
00328 // forward declaration:
00329 
00330 template< typename T, typename E >
00331 class expected;
00332 
00333 namespace detail {
00334 
00336 
00337 enum class enabler{};
00338 
00340 
00341 template< typename T, typename E >
00342 union storage_t
00343 {
00344     friend class expected<T,E>;
00345 
00346 private:
00347     using value_type = T;
00348     using error_type = E;
00349 
00350     // no-op construction
00351     storage_t() {}
00352     ~storage_t() {}
00353 
00354     template<class ...Args>
00355     void construct_value(Args&& ...args)
00356     {
00357         new(&m_value) value_type(std::forward<Args>(args)...);
00358     }
00359 
00360     void destruct_value()
00361     {
00362         m_value.~value_type();
00363     }
00364 
00365     void construct_error( error_type const & e )
00366     {
00367         new( &m_error ) error_type( e );
00368     }
00369 
00370     void construct_error( error_type && e )
00371     {
00372         new( &m_error ) error_type( std::move( e ) );
00373     }
00374 
00375     void destruct_error()
00376     {
00377         m_error.~error_type();
00378     }
00379 
00380     constexpr value_type const & value() const &
00381     {
00382         return m_value;
00383     }
00384 
00385     value_type & value() &
00386     {
00387         return m_value;
00388     }
00389 
00390     constexpr value_type const && value() const &&
00391     {
00392         return std::move( m_value );
00393     }
00394 
00395     nsel_constexpr14 value_type && value() &&
00396     {
00397         return std::move( m_value );
00398     }
00399 
00400     value_type const * value_ptr() const
00401     {
00402         return &m_value;
00403     }
00404 
00405     value_type * value_ptr()
00406     {
00407         return &m_value;
00408     }
00409 
00410     error_type const & error() const
00411     {
00412         return m_error;
00413     }
00414 
00415     error_type & error()
00416     {
00417         return m_error;
00418     }
00419 
00420 private:
00421     value_type m_value;
00422     error_type m_error;
00423 };
00424 
00426 
00427 template< typename E >
00428 union storage_t<void, E>
00429 {
00430     friend class expected<void,E>;
00431 
00432 private:
00433     using value_type = void;
00434     using error_type = E;
00435 
00436     // no-op construction
00437     storage_t() {}
00438     ~storage_t() {}
00439 
00440     void construct_error( error_type const & e )
00441     {
00442         new( &m_error ) error_type( e );
00443     }
00444 
00445     void construct_error( error_type && e )
00446     {
00447         new( &m_error ) error_type( std::move( e ) );
00448     }
00449 
00450     void destruct_error()
00451     {
00452         m_error.~error_type();
00453     }
00454 
00455     error_type const & error() const
00456     {
00457         return m_error;
00458     }
00459 
00460     error_type & error()
00461     {
00462         return m_error;
00463     }
00464 
00465 private:
00466     error_type m_error;
00467 };
00468 
00469 } // namespace detail
00470 
00472 
00473 #if nsel_P0323R <= 2
00474 template< typename E = std::exception_ptr >
00475 class unexpected_type
00476 #else
00477 template< typename E >
00478 class unexpected_type
00479 #endif // nsel_P0323R
00480 {
00481 public:
00482     using error_type = E;
00483 
00484     unexpected_type() = delete;
00485     constexpr unexpected_type( unexpected_type const &) = default;
00486     constexpr unexpected_type( unexpected_type &&) = default;
00487     nsel_constexpr14 unexpected_type& operator=( unexpected_type const &) = default;
00488     nsel_constexpr14 unexpected_type& operator=( unexpected_type &&) = default;
00489 
00490     template< typename E2
00491         nsel_REQUIRES_T(
00492             std::is_constructible<E,E2&&>::value
00493         )
00494     >
00495     constexpr explicit unexpected_type( E2 && error )
00496     : m_error( std::forward<E2>( error ) )
00497     {}
00498 
00499     template< typename E2 >
00500     constexpr explicit unexpected_type( unexpected_type<E2> const & error
00501         nsel_REQUIRES_A(
00502             std::is_constructible<E,E2 const &>::value
00503             && !std::is_convertible<E2 const &, E>::value /*=> explicit */ )
00504         )
00505     : m_error( error )
00506     {}
00507 
00508     template< typename E2 >
00509     constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> const & error
00510         nsel_REQUIRES_A(
00511             std::is_constructible<E,E2 const &>::value
00512             && std::is_convertible<E2 const &, E>::value /*=> non-explicit */ )
00513         )
00514     : m_error( error )
00515     {}
00516 
00517     template< typename E2 >
00518     constexpr explicit unexpected_type( unexpected_type<E2> && error
00519         nsel_REQUIRES_A(
00520             std::is_constructible<E,E2&&>::value
00521             && !std::is_convertible<E2&&, E>::value /*=> explicit */ )
00522         )
00523     : m_error( error )
00524     {}
00525 
00526     template< typename E2 >
00527     constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> && error
00528         nsel_REQUIRES_A(
00529             std::is_constructible<E,E2&&>::value
00530             && std::is_convertible<E2&&, E>::value /*=> non-explicit */ )
00531         )
00532     : m_error( error )
00533     {}
00534 
00535     nsel_constexpr14 E & value() & noexcept
00536     {
00537         return m_error;
00538     }
00539 
00540     constexpr E const & value() const & noexcept
00541     {
00542         return m_error;
00543     }
00544 
00545     nsel_constexpr14 E && value() && noexcept
00546     {
00547         return std::move( m_error );
00548     }
00549 
00550     constexpr E const && value() const && noexcept
00551     {
00552         return std::move( m_error );
00553     }
00554 
00555 //      nsel_REQUIRES_A(
00556 //        std::is_move_constructible<E>::value
00557 //        && std::is_swappable<E>::value
00558 //      )
00559 
00560     void swap( unexpected_type & other ) noexcept (
00561 #if nsel_CPP17_OR_GREATER
00562         std::is_nothrow_move_constructible<E>::value
00563         && std::is_nothrow_swappable<E&>::value
00564 #else
00565         std::is_nothrow_move_constructible<E>::value
00566         && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) )
00567 #endif
00568     )
00569     {
00570         using std::swap;
00571         swap( m_error, other.m_error );
00572     }
00573 
00574 private:
00575     error_type m_error;
00576 };
00577 
00579 
00580 #if nsel_P0323R <= 2
00581 
00582 template<>
00583 class unexpected_type< std::exception_ptr >
00584 {
00585 public:
00586     using error_type = std::exception_ptr;
00587 
00588     unexpected_type() = delete;
00589 
00590     ~unexpected_type(){}
00591 
00592     explicit unexpected_type( std::exception_ptr const & error )
00593     : m_error( error )
00594     {}
00595 
00596     explicit unexpected_type(std::exception_ptr && error )
00597     : m_error( std::move( error ) )
00598     {}
00599 
00600     template< typename E >
00601     explicit unexpected_type( E error )
00602     : m_error( std::make_exception_ptr( error ) )
00603     {}
00604 
00605     std::exception_ptr const & value() const
00606     {
00607         return m_error;
00608     }
00609 
00610     std::exception_ptr & value()
00611     {
00612         return m_error;
00613     }
00614 
00615 private:
00616     std::exception_ptr m_error;
00617 };
00618 
00619 #endif // nsel_P0323R
00620 
00622 
00623 template< typename E >
00624 constexpr bool operator==( unexpected_type<E> const & x, unexpected_type<E> const & y )
00625 {
00626     return x.value() == y.value();
00627 }
00628 
00629 template< typename E >
00630 constexpr bool operator!=( unexpected_type<E> const & x, unexpected_type<E> const & y )
00631 {
00632     return ! ( x == y );
00633 }
00634 
00635 #if nsel_P0323R <= 2
00636 
00637 template< typename E >
00638 constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y )
00639 {
00640     return x.value() < y.value();
00641 }
00642 
00643 template< typename E >
00644 constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y )
00645 {
00646     return ( y < x );
00647 }
00648 
00649 template< typename E >
00650 constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y )
00651 {
00652     return ! ( y < x  );
00653 }
00654 
00655 template< typename E >
00656 constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y )
00657 {
00658     return ! ( x < y );
00659 }
00660 
00662 
00663 template< typename E >
00664 void swap( unexpected_type<E> & x, unexpected_type<E> & y) noexcept ( noexcept ( x.swap(y) ) )
00665 {
00666     x.swap( y );
00667 }
00668 
00669 // unexpected: relational operators for std::exception_ptr:
00670 
00671 inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
00672 {
00673     return false;
00674 }
00675 
00676 inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
00677 {
00678     return false;
00679 }
00680 
00681 inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
00682 {
00683     return ( x == y );
00684 }
00685 
00686 inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
00687 {
00688     return ( x == y );
00689 }
00690 
00691 #endif // nsel_P0323R
00692 
00693 // unexpected: traits
00694 
00695 #if nsel_P0323R <= 3
00696 
00697 template< typename E>
00698 struct is_unexpected : std::false_type {};
00699 
00700 template< typename E>
00701 struct is_unexpected< unexpected_type<E> > : std::true_type {};
00702 
00703 #endif // nsel_P0323R
00704 
00705 // unexpected: factory
00706 
00707 // keep make_unexpected() removed in p0323r2 for pre-C++17:
00708 
00709 template< typename E>
00710 nsel_constexpr14 auto
00711 make_unexpected( E && value ) -> unexpected_type< typename std::decay<E>::type >
00712 {
00713     return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
00714 }
00715 
00716 #if nsel_P0323R <= 3
00717 
00718 /*nsel_constexpr14*/ auto inline
00719 make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
00720 {
00721     return unexpected_type< std::exception_ptr >( std::current_exception() );
00722 }
00723 
00724 #endif // nsel_P0323R
00725 
00727 
00728 struct unexpect_t{};
00729 using in_place_unexpected_t = unexpect_t;
00730 
00731 nsel_inline17 constexpr unexpect_t unexpect{};
00732 nsel_inline17 constexpr unexpect_t in_place_unexpected{};
00733 
00735 
00736 template< typename E >
00737 class bad_expected_access;
00738 
00739 template <>
00740 class bad_expected_access< void > : public std::exception
00741 {
00742 public:
00743     explicit bad_expected_access()
00744     : std::exception()
00745     {}
00746 };
00747 
00748 template< typename E >
00749 class bad_expected_access : public bad_expected_access< void >
00750 {
00751 public:
00752     using error_type = E;
00753 
00754     explicit bad_expected_access( error_type error )
00755     : m_error( error )
00756     {}
00757 
00758     virtual char const * what() const noexcept override
00759     {
00760         return "bad_expected_access";
00761     }
00762 
00763     nsel_constexpr14 error_type & error() &
00764     {
00765         return m_error;
00766     }
00767 
00768     constexpr error_type const & error() const &
00769     {
00770         return m_error;
00771     }
00772 
00773     nsel_constexpr14 error_type && error() &&
00774     {
00775         return std::move( m_error );
00776     }
00777 
00778     constexpr error_type const && error() const &&
00779     {
00780         return std::move( m_error );
00781     }
00782 
00783 private:
00784     error_type m_error;
00785 };
00786 
00788 
00789 template< typename Error >
00790 struct error_traits
00791 {
00792     static void rethrow( Error const & e )
00793     {
00794         throw bad_expected_access<Error>{ e };
00795     }
00796 };
00797 
00798 template<>
00799 struct error_traits< std::exception_ptr >
00800 {
00801     static void rethrow( std::exception_ptr const & e )
00802     {
00803         std::rethrow_exception( e );
00804     }
00805 };
00806 
00807 template<>
00808 struct error_traits< std::error_code >
00809 {
00810     static void rethrow( std::error_code const & e )
00811     {
00812         throw std::system_error( e );
00813     }
00814 };
00815 
00816 } // namespace expected_lite
00817 
00818 // provide nonstd::unexpected_type:
00819 
00820 using expected_lite::unexpected_type;
00821 
00822 namespace expected_lite {
00823 
00825 
00826 #if nsel_P0323R <= 2
00827 template< typename T, typename E = std::exception_ptr >
00828 class expected
00829 #else
00830 template< typename T, typename E >
00831 class expected
00832 #endif // nsel_P0323R
00833 {
00834 public:
00835     using value_type = T;
00836     using error_type = E;
00837     using unexpected_type = nonstd::unexpected_type<E>;
00838 
00839     template< typename U >
00840     struct rebind
00841     {
00842         using type = expected<U, error_type>;
00843     };
00844 
00845     // x.x.4.1 constructors
00846 
00847     nsel_REQUIRES_0(
00848         std::is_default_constructible<T>::value
00849     )
00850     nsel_constexpr14 expected() noexcept
00851     (
00852         std::is_nothrow_default_constructible<T>::value
00853     )
00854     : has_value_( true )
00855     {
00856         contained.construct_value( value_type() );
00857     }
00858 
00859     nsel_constexpr14 expected( expected const & other
00860 //      nsel_REQUIRES_A(
00861 //          std::is_copy_constructible<T>::value
00862 //          && std::is_copy_constructible<E>::value
00863 //      )
00864     )
00865     : has_value_( other.has_value_ )
00866     {
00867         if ( has_value() ) contained.construct_value( other.contained.value() );
00868         else               contained.construct_error( other.contained.error() );
00869     }
00870 
00871     nsel_constexpr14 expected( expected && other
00872 //      nsel_REQUIRES_A(
00873 //          std::is_move_constructible<T>::value
00874 //          && std::is_move_constructible<E>::value
00875 //      )
00876     ) noexcept (
00877         std::is_nothrow_move_constructible<T>::value
00878         && std::is_nothrow_move_constructible<E>::value
00879     )
00880     : has_value_( other.has_value_ )
00881     {
00882         if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
00883         else               contained.construct_error( std::move( other.contained.error() ) );
00884     }
00885 
00886     template< typename U, typename G >
00887     nsel_constexpr14 explicit expected( expected<U, G> const & other
00888         nsel_REQUIRES_A(
00889             std::is_constructible<T, const U&>::value
00890             && std::is_constructible<E, const G&>::value
00891             && !std::is_constructible<T, expected<U, G>&>::value
00892             && !std::is_constructible<T, expected<U, G>&&>::value
00893             && !std::is_constructible<T, const expected<U, G>&>::value
00894             && !std::is_constructible<T, const expected<U, G>&&>::value
00895             && !std::is_convertible<expected<U, G>&, T>::value
00896             && !std::is_convertible<expected<U, G>&&, T>::value
00897             && !std::is_convertible<const expected<U, G>&, T>::value
00898             && !std::is_convertible<const expected<U, G>&&, T>::value
00899             && (!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) /*=> explicit */ )
00900         )
00901     : has_value_( other.has_value_ )
00902     {
00903         if ( has_value() ) contained.construct_value( other.contained.value() );
00904         else               contained.construct_error( other.contained.error() );
00905     }
00906 
00907     template< typename U, typename G >
00908     nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> const & other
00909         nsel_REQUIRES_A(
00910             std::is_constructible<T, const U&>::value
00911             && std::is_constructible<E, const G&>::value
00912             && !std::is_constructible<T, expected<U, G>&>::value
00913             && !std::is_constructible<T, expected<U, G>&&>::value
00914             && !std::is_constructible<T, const expected<U, G>&>::value
00915             && !std::is_constructible<T, const expected<U, G>&&>::value
00916             && !std::is_convertible<expected<U, G>&, T>::value
00917             && !std::is_convertible<expected<U, G>&&, T>::value
00918             && !std::is_convertible<const expected<U, G>&, T>::value
00919             && !std::is_convertible<const expected<U, G>&&, T>::value
00920             && !(!std::is_convertible<U const&, T>::value || !std::is_convertible<const G&, E>::value ) /*=> explicit */ )
00921         )
00922     : has_value_( other.has_value_ )
00923     {
00924         if ( has_value() ) contained.construct_value( other.contained.value() );
00925         else               contained.construct_error( other.contained.error() );
00926     }
00927 
00928     template< typename U, typename G >
00929     nsel_constexpr14 explicit expected( expected<U, G> && other
00930         nsel_REQUIRES_A(
00931             std::is_constructible<T, U>::value
00932             && std::is_constructible<E, G>::value
00933             && !std::is_constructible<T, expected<U, G>&>::value
00934             && !std::is_constructible<T, expected<U, G>&&>::value
00935             && !std::is_constructible<T, const expected<U, G>&>::value
00936             && !std::is_constructible<T, const expected<U, G>&&>::value
00937             && !std::is_convertible<expected<U, G>&, T>::value
00938             && !std::is_convertible<expected<U, G>&&, T>::value
00939             && !std::is_convertible<const expected<U, G>&, T>::value
00940             && !std::is_convertible<const expected<U, G>&&, T>::value
00941             && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> explicit */ )
00942         )
00943     : has_value_( other.has_value_ )
00944     {
00945         if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
00946         else               contained.construct_error( std::move( other.contained.error() ) );
00947     }
00948 
00949     template< typename U, typename G >
00950     nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> && other
00951         nsel_REQUIRES_A(
00952             std::is_constructible<T, U>::value
00953             && std::is_constructible<E, G>::value
00954             && !std::is_constructible<T, expected<U, G>&>::value
00955             && !std::is_constructible<T, expected<U, G>&&>::value
00956             && !std::is_constructible<T, const expected<U, G>&>::value
00957             && !std::is_constructible<T, const expected<U, G>&&>::value
00958             && !std::is_convertible<expected<U, G>&, T>::value
00959             && !std::is_convertible<expected<U, G>&&, T>::value
00960             && !std::is_convertible<const expected<U, G>&, T>::value
00961             && !std::is_convertible<const expected<U, G>&&, T>::value
00962             && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> non-explicit */ )
00963         )
00964     : has_value_( other.has_value_ )
00965     {
00966         if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
00967         else               contained.construct_error( std::move( other.contained.error() ) );
00968     }
00969 
00970     nsel_constexpr14 expected( value_type const & value
00971 //        nsel_REQUIRES_A(
00972 //            std::is_copy_constructible<T>::value )
00973     )
00974     : has_value_( true )
00975     {
00976         contained.construct_value( value );
00977     }
00978 
00979     template< typename U = T >
00980     nsel_constexpr14 explicit expected( U && value
00981         nsel_REQUIRES_A(
00982             std::is_constructible<T,U&&>::value
00983             && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
00984             && !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value
00985             && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
00986             && !std::is_convertible<U&&,T>::value /*=> explicit */
00987         )
00988     ) noexcept
00989     (
00990         std::is_nothrow_move_constructible<U>::value &&
00991         std::is_nothrow_move_constructible<E>::value
00992     )
00993     : has_value_( true )
00994     {
00995         contained.construct_value( std::forward<U>( value ) );
00996     }
00997 
00998     template< typename U = T >
00999     nsel_constexpr14 expected( U && value
01000         nsel_REQUIRES_A(
01001             std::is_constructible<T,U&&>::value
01002             && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
01003             && !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value
01004             && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
01005             &&  std::is_convertible<U&&,T>::value /*=> non-explicit */
01006         )
01007     ) noexcept
01008     (
01009         std::is_nothrow_move_constructible<U>::value &&
01010         std::is_nothrow_move_constructible<E>::value
01011     )
01012     : has_value_( true )
01013     {
01014         contained.construct_value( std::forward<U>( value ) );
01015     }
01016 
01017     template< typename... Args
01018         nsel_REQUIRES_T(
01019             std::is_constructible<T, Args&&...>::value
01020         )
01021     >
01022     nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), Args&&... args )
01023     : has_value_( true )
01024     {
01025         contained.construct_value( std::forward<Args>( args )... );
01026     }
01027 
01028     template< typename U, typename... Args
01029         nsel_REQUIRES_T(
01030             std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
01031         )
01032     >
01033     nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
01034     : has_value_( true )
01035     {
01036         contained.construct_value( il, std::forward<Args>( args )... );
01037     }
01038 
01039     template< typename G = E >
01040     nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error
01041         nsel_REQUIRES_A(
01042             !std::is_convertible<const G&, E>::value /*=> explicit */ )
01043         )
01044     : has_value_( false )
01045     {
01046         contained.construct_error( error.value() );
01047     }
01048 
01049     template< typename G = E >
01050     nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error
01051         nsel_REQUIRES_A(
01052             std::is_convertible<const G&, E>::value /*=> non-explicit */ )
01053         )
01054     : has_value_( false )
01055     {
01056         contained.construct_error( error.value() );
01057     }
01058 
01059     template< typename G = E >
01060     nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error
01061         nsel_REQUIRES_A(
01062             !std::is_convertible<G&&, E>::value /*=> explicit */ )
01063         )
01064     : has_value_( false )
01065     {
01066         contained.construct_error( std::move( error.value() ) );
01067     }
01068 
01069     template< typename G = E >
01070     nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error
01071         nsel_REQUIRES_A(
01072             std::is_convertible<G&&, E>::value /*=> non-explicit */ )
01073         )
01074     : has_value_( false )
01075     {
01076         contained.construct_error( std::move( error.value() ) );
01077     }
01078 
01079     template< typename... Args
01080         nsel_REQUIRES_T(
01081             std::is_constructible<E, Args&&...>::value
01082         )
01083     >
01084     nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
01085     : has_value_( false )
01086     {
01087         contained.construct_error( std::forward<Args>( args )... );
01088     }
01089 
01090     template< typename U, typename... Args
01091         nsel_REQUIRES_T(
01092             std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
01093         )
01094     >
01095     nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
01096     : has_value_( false )
01097     {
01098         contained.construct_error( il, std::forward<Args>( args )... );
01099     }
01100 
01101     // x.x.4.2 destructor
01102 
01103     ~expected()
01104     {
01105         if ( has_value() ) contained.destruct_value();
01106         else               contained.destruct_error();
01107     }
01108 
01109     // x.x.4.3 assignment
01110 
01111 //    nsel_REQUIRES_A(
01112 //        std::is_copy_constructible<T>::value &&
01113 //        std::is_copy_assignable<T>::value &&
01114 //        std::is_copy_constructible<E>::value &&
01115 //        std::is_copy_assignable<E>::value )
01116 
01117     expected operator=( expected const & other )
01118     {
01119         expected( other ).swap( *this );
01120         return *this;
01121     }
01122 
01123 //    nsel_REQUIRES_A(
01124 //        std::is_move_constructible<T>::value &&
01125 //        std::is_move_assignable<T>::value &&
01126 //        std::is_move_constructible<E>::value &&
01127 //        std::is_move_assignable<E>::value )
01128 
01129     expected & operator=( expected && other ) noexcept
01130     (
01131         std::is_nothrow_move_assignable<T>::value &&
01132         std::is_nothrow_move_constructible<T>::value&&
01133         std::is_nothrow_move_assignable<E>::value &&
01134         std::is_nothrow_move_constructible<E>::value )
01135     {
01136         expected( std::move( other ) ).swap( *this );
01137         return *this;
01138     }
01139 
01140     template< typename U
01141         nsel_REQUIRES_T(
01142             std::is_constructible<T,U>::value &&
01143             std::is_assignable<T&, U>::value
01144         )
01145     >
01146     expected & operator=( U && value )
01147     {
01148         expected( std::forward<U>( value ) ).swap( *this );
01149         return *this;
01150     }
01151 
01152 //    nsel_REQUIRES_A(
01153 //        std::is_copy_constructible<E>::value &&
01154 //        std::is_assignable<E&, E>::value )
01155 
01156     expected & operator=( unexpected_type const & uvalue )
01157     {
01158         expected( std::move( uvalue ) ).swap( *this );
01159         return *this;
01160     }
01161 
01162 //    nsel_REQUIRES_A(
01163 //        std::is_copy_constructible<E>::value &&
01164 //        std::is_assignable<E&, E>::value )
01165 
01166     expected & operator=( unexpected_type && uvalue )
01167     {
01168         expected( std::move( uvalue ) ).swap( *this );
01169         return *this;
01170     }
01171 
01172     template< typename... Args
01173         nsel_REQUIRES_T(
01174             std::is_constructible<T, Args&&...>::value
01175         )
01176     >
01177     void emplace( Args &&... args )
01178     {
01179         expected( nonstd_lite_in_place(T), std::forward<Args>(args)... ).swap( *this );
01180     }
01181 
01182     template< typename U, typename... Args
01183         nsel_REQUIRES_T(
01184             std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
01185         )
01186     >
01187     void emplace( std::initializer_list<U> il, Args &&... args )
01188     {
01189         expected( nonstd_lite_in_place(T), il, std::forward<Args>(args)... ).swap( *this );
01190     }
01191 
01192     // x.x.4.4 swap
01193 
01194 //    nsel_REQUIRES_A(
01195 //        std::is_move_constructible<T>::value &&
01196 //        std::is_move_constructible<E>::value )
01197 
01198     void swap( expected & other ) noexcept
01199     (
01200 #if nsel_CPP17_OR_GREATER
01201         std::is_nothrow_move_constructible<T>::value && std::is_nothrow_swappable<T&>::value &&
01202         std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value
01203 #else
01204         std::is_nothrow_move_constructible<T>::value && noexcept ( std::swap( std::declval<T&>(), std::declval<T&>() ) ) &&
01205         std::is_nothrow_move_constructible<E>::value && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) )
01206 #endif
01207     )
01208     {
01209         using std::swap;
01210 
01211         if      (   bool(*this) &&   bool(other) ) { swap( contained.value(), other.contained.value() ); }
01212         else if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
01213         else if (   bool(*this) && ! bool(other) ) { error_type t( std::move( other.error() ) );
01214                                                    other.contained.destruct_error();
01215                                                    other.contained.construct_value( std::move( contained.value() ) );
01216                                                    contained.destruct_value();
01217                                                    contained.construct_error( std::move( t ) );
01218                                                    swap( has_value_, other.has_value_ ); }
01219         else if ( ! bool(*this) &&   bool(other) ) { other.swap( *this ); }
01220     }
01221 
01222     // x.x.4.5 observers
01223 
01224     constexpr value_type const * operator ->() const
01225     {
01226         return assert( has_value() ), contained.value_ptr();
01227     }
01228 
01229     value_type * operator ->()
01230     {
01231         return assert( has_value() ), contained.value_ptr();
01232     }
01233 
01234     constexpr value_type const & operator *() const &
01235     {
01236         return assert( has_value() ), contained.value();
01237     }
01238 
01239     value_type & operator *() &
01240     {
01241         return assert( has_value() ), contained.value();
01242     }
01243 
01244     constexpr value_type const && operator *() const &&
01245     {
01246         return assert( has_value() ), std::move( contained.value() );
01247     }
01248 
01249     nsel_constexpr14 value_type && operator *() &&
01250     {
01251         return assert( has_value() ), std::move( contained.value() );
01252     }
01253 
01254     constexpr explicit operator bool() const noexcept
01255     {
01256         return has_value();
01257     }
01258 
01259     constexpr bool has_value() const noexcept
01260     {
01261         return has_value_;
01262     }
01263 
01264     constexpr value_type const & value() const &
01265     {
01266         return has_value()
01267             ? ( contained.value() )
01268             : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
01269     }
01270 
01271     value_type & value() &
01272     {
01273         return has_value()
01274             ? ( contained.value() )
01275             : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
01276     }
01277 
01278     constexpr value_type const && value() const &&
01279     {
01280         return std::move( has_value()
01281             ? ( contained.value() )
01282             : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
01283     }
01284 
01285     nsel_constexpr14 value_type && value() &&
01286     {
01287         return std::move( has_value()
01288             ? ( contained.value() )
01289             : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
01290     }
01291 
01292     constexpr error_type const & error() const &
01293     {
01294         return assert( ! has_value() ), contained.error();
01295     }
01296 
01297     error_type & error() &
01298     {
01299         return assert( ! has_value() ), contained.error();
01300     }
01301 
01302     constexpr error_type const && error() const &&
01303     {
01304         return assert( ! has_value() ), std::move( contained.error() );
01305     }
01306 
01307     error_type && error() &&
01308     {
01309         return assert( ! has_value() ), std::move( contained.error() );
01310     }
01311 
01312     constexpr unexpected_type get_unexpected() const
01313     {
01314         return make_unexpected( contained.error() );
01315     }
01316 
01317     template< typename Ex >
01318     bool has_exception() const
01319     {
01320         using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type;
01321         return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
01322     }
01323 
01324     template< typename U
01325         nsel_REQUIRES_T(
01326             std::is_copy_constructible<T>::value &&
01327             std::is_convertible<U&&, T>::value
01328         )
01329     >
01330     value_type value_or( U && v ) const &
01331     {
01332         return has_value()
01333             ? contained.value()
01334             : static_cast<T>( std::forward<U>( v ) );
01335     }
01336 
01337     template< typename U
01338         nsel_REQUIRES_T(
01339             std::is_move_constructible<T>::value &&
01340             std::is_convertible<U&&, T>::value
01341         )
01342     >
01343     value_type value_or( U && v ) &&
01344     {
01345         return has_value()
01346             ? std::move( contained.value() )
01347             : static_cast<T>( std::forward<U>( v ) );
01348     }
01349 
01350     // unwrap()
01351 
01352 //  template <class U, class E>
01353 //  constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
01354 
01355 //  template <class T, class E>
01356 //  constexpr expected<T,E> expected<T,E>::unwrap() const&;
01357 
01358 //  template <class U, class E>
01359 //  expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
01360 
01361 //  template <class T, class E>
01362 //  template expected<T,E> expected<T,E>::unwrap() &&;
01363 
01364     // factories
01365 
01366 //  template< typename Ex, typename F>
01367 //  expected<T,E> catch_exception(F&& f);
01368 
01369 //  template< typename F>
01370 //  expected<decltype(func(declval<T>())),E> map(F&& func) ;
01371 
01372 //  template< typename F>
01373 //  'see below' bind(F&& func);
01374 
01375 //  template< typename F>
01376 //  expected<T,E> catch_error(F&& f);
01377 
01378 //  template< typename F>
01379 //  'see below' then(F&& func);
01380 
01381 private:
01382     bool has_value_;
01383     detail::storage_t<T,E> contained;
01384 };
01385 
01387 
01388 template< typename E >
01389 class expected<void, E>
01390 {
01391 public:
01392     using value_type = void;
01393     using error_type = E;
01394     using unexpected_type = nonstd::unexpected_type<E>;
01395 
01396     // x.x.4.1 constructors
01397 
01398     constexpr expected() noexcept
01399     : has_value_( true )
01400     {
01401     }
01402 
01403     nsel_constexpr14 expected( expected const & other )
01404     : has_value_( other.has_value_ )
01405     {
01406         if ( ! has_value() ) contained.construct_error( other.contained.error() );
01407     }
01408 
01409     nsel_REQUIRES_0(
01410         std::is_move_constructible<E>::value
01411     )
01412     nsel_constexpr14 expected( expected && other ) noexcept
01413     (
01414         true    // TBD - see also non-void specialization
01415     )
01416     : has_value_( other.has_value_ )
01417     {
01418         if ( ! has_value() ) contained.construct_error( std::move( other.contained.error() ) );
01419     }
01420 
01421     constexpr explicit expected( nonstd_lite_in_place_t(void) )
01422     : has_value_( true )
01423     {
01424     }
01425 
01426     template< typename G = E >
01427     nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error
01428         nsel_REQUIRES_A(
01429             !std::is_convertible<const G&, E>::value /*=> explicit */
01430         )
01431     )
01432     : has_value_( false )
01433     {
01434         contained.construct_error( error.value() );
01435     }
01436 
01437     template< typename G = E >
01438     nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error
01439         nsel_REQUIRES_A(
01440             std::is_convertible<const G&, E>::value /*=> non-explicit */
01441         )
01442     )
01443     : has_value_( false )
01444     {
01445         contained.construct_error( error.value() );
01446     }
01447 
01448     template< typename G = E >
01449     nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error
01450         nsel_REQUIRES_A(
01451             !std::is_convertible<G&&, E>::value /*=> explicit */
01452         )
01453     )
01454     : has_value_( false )
01455     {
01456         contained.construct_error( std::move( error.value() ) );
01457     }
01458 
01459     template< typename G = E >
01460     nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error
01461         nsel_REQUIRES_A(
01462             std::is_convertible<G&&, E>::value /*=> non-explicit */
01463         )
01464     )
01465     : has_value_( false )
01466     {
01467         contained.construct_error( std::move( error.value() ) );
01468     }
01469 
01470     template< typename... Args
01471         nsel_REQUIRES_T(
01472             std::is_constructible<E, Args&&...>::value
01473         )
01474     >
01475     nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
01476     : has_value_( false )
01477     {
01478         contained.construct_error( std::forward<Args>( args )... );
01479     }
01480 
01481     template< typename U, typename... Args
01482         nsel_REQUIRES_T(
01483             std::is_constructible<U, std::initializer_list<U>, Args&&...>::value
01484         )
01485     >
01486     nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
01487     : has_value_( false )
01488     {
01489         contained.construct_error( il, std::forward<Args>( args )... );
01490     }
01491 
01492 
01493     // destructor
01494 
01495     ~expected()
01496     {
01497         if ( ! has_value() ) contained.destruct_error();
01498     }
01499 
01500     // x.x.4.3 assignment
01501 
01502 //    nsel_REQUIRES_A(
01503 //        std::is_copy_constructible<E>::value &&
01504 //        std::is_copy_assignable<E>::value )
01505 
01506     expected & operator=( expected const & other )
01507     {
01508         expected( other ).swap( *this );
01509         return *this;
01510     }
01511 
01512 //    nsel_REQUIRES_A(
01513 //        std::is_move_constructible<E>::value &&
01514 //        std::is_move_assignable<E>::value )
01515 
01516     expected & operator=( expected && other ) noexcept
01517     (
01518         std::is_nothrow_move_assignable<E>::value &&
01519         std::is_nothrow_move_constructible<E>::value )
01520     {
01521         expected( std::move( other ) ).swap( *this );
01522         return *this;
01523     }
01524 
01525     void emplace()
01526     {}
01527 
01528     // x.x.4.4 swap
01529 
01530 //    nsel_REQUIRES_A(
01531 //        std::is_move_constructible<E>::value )
01532 
01533     void swap( expected & other ) noexcept
01534     (
01535 #if nsel_CPP17_OR_GREATER
01536         std::is_nothrow_move_constructible<E>::value && std::is_nothrow_swappable<E&>::value
01537 #else
01538         std::is_nothrow_move_constructible<E>::value && noexcept ( std::swap( std::declval<E&>(), std::declval<E&>() ) )
01539 #endif
01540     )
01541     {
01542         using std::swap;
01543 
01544         if      ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
01545         else if (   bool(*this) && ! bool(other) ) { contained.construct_error( std::move( other.error() ) );
01546                                                    swap( has_value_, other.has_value_ ); }
01547         else if ( ! bool(*this) &&   bool(other) ) { other.swap( *this ); }
01548     }
01549 
01550     // x.x.4.5 observers
01551 
01552     constexpr explicit operator bool() const noexcept
01553     {
01554         return has_value();
01555     }
01556 
01557     constexpr bool has_value() const noexcept
01558     {
01559         return has_value_;
01560     }
01561 
01562     void value() const
01563     {}
01564 
01565     constexpr error_type const & error() const &
01566     {
01567         return assert( ! has_value() ), contained.error();
01568     }
01569 
01570     error_type & error() &
01571     {
01572         return assert( ! has_value() ), contained.error();
01573     }
01574 
01575     constexpr error_type const && error() const &&
01576     {
01577         return assert( ! has_value() ), std::move( contained.error() );
01578     }
01579 
01580     error_type && error() &&
01581     {
01582         return assert( ! has_value() ), std::move( contained.error() );
01583     }
01584 
01585     constexpr unexpected_type get_unexpected() const
01586     {
01587         return make_unexpected( contained.error() );
01588     }
01589 
01590     template< typename Ex >
01591     bool has_exception() const
01592     {
01593         return ! has_value() && std::is_base_of< Ex, decltype( get_unexpected().value() ) >::value;
01594     }
01595 
01596 //  template constexpr 'see below' unwrap() const&;
01597 //
01598 //  template 'see below' unwrap() &&;
01599 
01600     // factories
01601 
01602 //  template< typename Ex, typename F>
01603 //  expected<void,E> catch_exception(F&& f);
01604 //
01605 //  template< typename F>
01606 //  expected<decltype(func()), E> map(F&& func) ;
01607 //
01608 //  template< typename F>
01609 //  'see below' bind(F&& func) ;
01610 //
01611 //  template< typename F>
01612 //  expected<void,E> catch_error(F&& f);
01613 //
01614 //  template< typename F>
01615 //  'see below' then(F&& func);
01616 
01617 private:
01618     bool has_value_;
01619     detail::storage_t<void,E> contained;
01620 };
01621 
01622 // expected: relational operators
01623 
01624 template< typename T, typename E >
01625 constexpr bool operator==( expected<T,E> const & x, expected<T,E> const & y )
01626 {
01627     return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
01628 }
01629 
01630 template< typename T, typename E >
01631 constexpr bool operator!=( expected<T,E> const & x, expected<T,E> const & y )
01632 {
01633     return !(x == y);
01634 }
01635 
01636 template< typename T, typename E >
01637 constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y )
01638 {
01639     return (!y) ? false : (!x) ? true : *x < *y;
01640 }
01641 
01642 template< typename T, typename E >
01643 constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y )
01644 {
01645     return (y < x);
01646 }
01647 
01648 template< typename T, typename E >
01649 constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y )
01650 {
01651     return !(y < x);
01652 }
01653 
01654 template< typename T, typename E >
01655 constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y )
01656 {
01657     return !(x < y);
01658 }
01659 
01660 // expected: comparison with unexpected_type
01661 
01662 template< typename T, typename E >
01663 constexpr bool operator==( expected<T,E> const & x, unexpected_type<E> const & u )
01664 {
01665     return (!x) ? x.get_unexpected() == u : false;
01666 }
01667 
01668 template< typename T, typename E >
01669 constexpr bool operator==( unexpected_type<E> const & u, expected<T,E> const & x )
01670 {
01671     return ( x == u );
01672 }
01673 
01674 template< typename T, typename E >
01675 constexpr bool operator!=( expected<T,E> const & x, unexpected_type<E> const & u )
01676 {
01677     return ! ( x == u );
01678 }
01679 
01680 template< typename T, typename E >
01681 constexpr bool operator!=( unexpected_type<E> const & u, expected<T,E> const & x )
01682 {
01683     return ! ( x == u );
01684 }
01685 
01686 template< typename T, typename E >
01687 constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u )
01688 {
01689     return (!x) ? ( x.get_unexpected() < u ) : false;
01690 }
01691 
01692 #if nsel_P0323R <= 2
01693 
01694 template< typename T, typename E >
01695 constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x )
01696 {
01697   return (!x) ? ( u < x.get_unexpected() ) : true ;
01698 }
01699 
01700 template< typename T, typename E >
01701 constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u )
01702 {
01703     return ( u < x );
01704 }
01705 
01706 template< typename T, typename E >
01707 constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x )
01708 {
01709     return ( x < u );
01710 }
01711 
01712 template< typename T, typename E >
01713 constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u )
01714 {
01715     return ! ( u < x );
01716 }
01717 
01718 template< typename T, typename E >
01719 constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x)
01720 {
01721     return ! ( x < u );
01722 }
01723 
01724 template< typename T, typename E >
01725 constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u  )
01726 {
01727     return ! ( u > x );
01728 }
01729 
01730 template< typename T, typename E >
01731 constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x )
01732 {
01733     return ! ( x > u );
01734 }
01735 
01736 #endif // nsel_P0323R
01737 
01738 // expected: comparison with T
01739 
01740 template< typename T, typename E >
01741 constexpr bool operator==( expected<T,E> const & x, T const & v )
01742 {
01743     return bool(x) ? *x == v : false;
01744 }
01745 
01746 template< typename T, typename E >
01747 constexpr bool operator==(T const & v, expected<T,E> const & x )
01748 {
01749     return bool(x) ? v == *x : false;
01750 }
01751 
01752 template< typename T, typename E >
01753 constexpr bool operator!=( expected<T,E> const & x, T const & v )
01754 {
01755     return bool(x) ? *x != v : true;
01756 }
01757 
01758 template< typename T, typename E >
01759 constexpr bool operator!=( T const & v, expected<T,E> const & x )
01760 {
01761     return bool(x) ? v != *x : true;
01762 }
01763 
01764 template< typename T, typename E >
01765 constexpr bool operator<( expected<T,E> const & x, T const & v )
01766 {
01767     return bool(x) ? *x < v : true;
01768 }
01769 
01770 template< typename T, typename E >
01771 constexpr bool operator<( T const & v, expected<T,E> const & x )
01772 {
01773     return bool(x) ? v < *x : false;
01774 }
01775 
01776 template< typename T, typename E >
01777 constexpr bool operator>( T const & v, expected<T,E> const & x )
01778 {
01779     return bool(x) ? *x < v : false;
01780 }
01781 
01782 template< typename T, typename E >
01783 constexpr bool operator>( expected<T,E> const & x, T const & v )
01784 {
01785     return bool(x) ? v < *x : false;
01786 }
01787 
01788 template< typename T, typename E >
01789 constexpr bool operator<=( T const & v, expected<T,E> const & x )
01790 {
01791     return bool(x) ? ! ( *x < v ) : false;
01792 }
01793 
01794 template< typename T, typename E >
01795 constexpr bool operator<=( expected<T,E> const & x, T const & v )
01796 {
01797     return bool(x) ? ! ( v < *x ) : true;
01798 }
01799 
01800 template< typename T, typename E >
01801 constexpr bool operator>=( expected<T,E> const & x, T const & v )
01802 {
01803     return bool(x) ? ! ( *x < v ) : false;
01804 }
01805 
01806 template< typename T, typename E >
01807 constexpr bool operator>=( T const & v, expected<T,E> const & x )
01808 {
01809     return bool(x) ? ! ( v < *x ) : true;
01810 }
01811 
01813 
01814 template< typename T, typename E >
01815 void swap( expected<T,E> & x, expected<T,E> & y ) noexcept ( noexcept ( x.swap(y) ) )
01816 {
01817     x.swap( y );
01818 }
01819 
01820 #if nsel_P0323R <= 3
01821 
01822 template< typename T >
01823 constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
01824 {
01825     return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
01826 }
01827 
01828 // expected<void> specialization:
01829 
01830 auto inline make_expected() -> expected<void>
01831 {
01832     return expected<void>( in_place );
01833 }
01834 
01835 template< typename T >
01836 constexpr auto make_expected_from_current_exception() -> expected<T>
01837 {
01838     return expected<T>( make_unexpected_from_current_exception() );
01839 }
01840 
01841 template< typename T >
01842 auto make_expected_from_exception( std::exception_ptr v ) -> expected<T>
01843 {
01844     return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) );
01845 }
01846 
01847 template< typename T, typename E >
01848 constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
01849 {
01850     return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
01851 }
01852 
01853 template< typename F >
01854 /*nsel_constexpr14*/
01855 auto make_expected_from_call( F f,
01856     nsel_REQUIRES_A( ! std::is_same<typename std::result_of<F()>::type, void>::value )
01857 ) -> expected< typename std::result_of<F()>::type >
01858 {
01859     try
01860     {
01861         return make_expected( f() );
01862     }
01863     catch (...)
01864     {
01865         return make_unexpected_from_current_exception();
01866     }
01867 }
01868 
01869 template< typename F >
01870 /*nsel_constexpr14*/
01871 auto make_expected_from_call( F f,
01872     nsel_REQUIRES_A( std::is_same<typename std::result_of<F()>::type, void>::value )
01873 ) -> expected<void>
01874 {
01875     try
01876     {
01877         f();
01878         return make_expected();
01879     }
01880     catch (...)
01881     {
01882         return make_unexpected_from_current_exception();
01883     }
01884 }
01885 
01886 #endif // nsel_P0323R
01887 
01888 } // namespace expected_lite
01889 
01890 using namespace expected_lite;
01891 
01892 // using expected_lite::expected;
01893 // using ...
01894 
01895 } // namespace nonstd
01896 
01897 namespace std {
01898 
01899 // expected: hash support
01900 
01901 template< typename T, typename E >
01902 struct hash< nonstd::expected<T,E> >
01903 {
01904     using result_type = typename hash<T>::result_type;
01905     using argument_type = nonstd::expected<T,E>;
01906 
01907     constexpr result_type operator()(argument_type const & arg) const
01908     {
01909         return arg ? std::hash<T>{}(*arg) : result_type{};
01910     }
01911 };
01912 
01913 // TBD - ?? remove? see spec.
01914 template< typename T, typename E >
01915 struct hash< nonstd::expected<T&,E> >
01916 {
01917     using result_type = typename hash<T>::result_type;
01918     using argument_type = nonstd::expected<T&,E>;
01919 
01920     constexpr result_type operator()(argument_type const & arg) const
01921     {
01922         return arg ? std::hash<T>{}(*arg) : result_type{};
01923     }
01924 };
01925 
01926 // TBD - implement
01927 // bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true;
01928 // otherwise it evaluates to an unspecified value if E is exception_ptr or
01929 // a combination of hashing false and hash<E>()(e.error()).
01930 
01931 template< typename E >
01932 struct hash< nonstd::expected<void,E> >
01933 {
01934 };
01935 
01936 } // namespace std
01937 
01938 namespace nonstd {
01939 
01940 // void unexpected() is deprecated && removed in C++17
01941 
01942 #if nsel_CPP17_OR_GREATER && nsel_COMPILER_MSVC_VERSION > 141
01943 template< typename E >
01944 using unexpected = unexpected_type<E>;
01945 #endif
01946 
01947 } // namespace nonstd
01948 
01949 #undef nsel_REQUIRES
01950 #undef nsel_REQUIRES_0
01951 #undef nsel_REQUIRES_T
01952 
01953 nsel_RESTORE_WARNINGS()
01954 
01955 #endif // nsel_USES_STD_EXPECTED
01956 
01957 #endif // NONSTD_EXPECTED_LITE_HPP


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Jun 8 2019 20:17:15