You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2537 lines
69 KiB

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