• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! \file test_expected.cpp
2 
3 // Copyright Pierre Talbot 2013.
4 // Copyright Vicente J. Botet Escriba 2013,2014.
5 
6 // Use, modification and distribution are subject to the
7 // Boost Software License, Version 1.0.
8 //(See accompanying file LICENSE_1_0.txt
9 // or copy at http://www.boost.org/LICENSE_1_0.txt)
10 
11 
12 // Notes by ned:
13 // Original is at https://github.com/viboes/std-make/blob/master/test/expected/expected_pass.cpp
14 // This edition modified to use result with throw_bad_result_access policy
15 // Quite a lot of the test suite I had to disable, not because our Expected implementation is
16 // incorrect, but because the reference test suite is testing an Expected quite far away from
17 // the latest WG21 proposal paper, and we're implementing that latest edition.
18 
19 #if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 7
20 
21 #include <utility>
22 
23 #include <boost/outcome/iostream_support.hpp>
24 #include <boost/outcome/std_result.hpp>
25 
26 #define QUICKCPPLIB_BOOST_UNIT_TEST_CUSTOM_MAIN_DEFINED
27 #include <boost/test/unit_test.hpp>
28 #include <boost/test/unit_test_monitor.hpp>
29 
30 #define JASEL_NORETURN
31 #ifndef BOOST_TEST
32 #define BOOST_TEST(expr) BOOST_CHECK(expr)
33 #endif
34 #ifndef BOOST_TEST_EQ
35 #define BOOST_TEST_EQ(a, b) BOOST_CHECK_EQUAL((a), (b))
36 #endif
37 #ifndef BOOST_TEST_THROWS
38 #define BOOST_TEST_THROWS(expr, ex) BOOST_CHECK_THROW((expr), ex)
39 #endif
40 #ifndef BOOST_CONSTEXPR
41 #define BOOST_CONSTEXPR constexpr
42 #endif
43 
44 #ifdef _MSC_VER
45 #pragma warning(disable : 4127)  // conditional expression is constant
46 #pragma warning(disable : 4244)  // conversion from int to short
47 #endif
48 
49 namespace stde
50 {
51 #if __cplusplus >= 201700 || _HAS_CXX17
52   using in_place_t = std::in_place_t;
53   using std::in_place;
54 #else
55   struct in_place_t
56   {
57     explicit in_place_t() = default;
58   };
59   constexpr in_place_t in_place{};
60 #endif
61 
62   //! [expected_implementation]
63   /* Here is a fairly conforming implementation of P0323R3 `expected<T, E>` using `checked<T, E>`.
64   It passes the reference test suite for P0323R3 at
65   https://github.com/viboes/std-make/blob/master/test/expected/expected_pass.cpp with modifications
66   only to move the test much closer to the P0323R3 Expected, as the reference test suite is for a
67   much older proposed Expected.
68 
69   Known differences from P0323R3 in this implementation:
70   - `T` and `E` cannot be the same type.
71   - No variant storage is implemented.
72   */
73 
74   namespace detail
75   {
76     template <class T, class E> using expected_result = BOOST_OUTCOME_V2_NAMESPACE::checked<T, E>;
77     template <class T, class E> struct enable_default_constructor : public expected_result<T, E>
78     {
79       using base = expected_result<T, E>;
80       using base::base;
enable_default_constructorstde::detail::enable_default_constructor81       constexpr enable_default_constructor()
82           : base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>}
83       {
84       }
85     };
86     template <class T, class E> using select_expected_base = std::conditional_t<std::is_default_constructible<T>::value, enable_default_constructor<T, E>, expected_result<T, E>>;
87   }  // namespace detail
88   template <class T, class E> class expected : public detail::select_expected_base<T, E>
89   {
90     static_assert(!std::is_same<T, E>::value, "T and E cannot be the same in this expected implementation");
91     using base = detail::select_expected_base<T, E>;
92 
93   public:
94     // Inherit base's constructors
95     using base::base;
96     expected() = default;
97 
98     // Expected takes in_place not in_place_type
99     template <class... Args>
expected(in_place_t,Args &&...args)100     constexpr explicit expected(in_place_t /*unused*/, Args &&... args)
101         : base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>, std::forward<Args>(args)...}
102     {
103     }
104 
105     // Expected always accepts a T even if ambiguous
106     BOOST_OUTCOME_TEMPLATE(class U)
BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED (std::is_constructible<T,U>::value))107     BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_constructible<T, U>::value))
108     constexpr expected(U &&v)  // NOLINT
109     : base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>, std::forward<U>(v)}
110     {
111     }
112 
113     // Expected has an emplace() modifier
emplace(Args &&...args)114     template <class... Args> void emplace(Args &&... args) { *static_cast<base *>(this) = base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>, std::forward<Args>(args)...}; }
115 
116     // Expected has a narrow operator* and operator->
operator *() const117     constexpr const T &operator*() const & { return base::assume_value(); }
operator *()118     constexpr T &operator*() & { return base::assume_value(); }
operator *() const119     constexpr const T &&operator*() const && { return base::assume_value(); }
operator *()120     constexpr T &&operator*() && { return base::assume_value(); }
operator ->() const121     constexpr const T *operator->() const { return &base::assume_value(); }
operator ->()122     constexpr T *operator->() { return &base::assume_value(); }
123 
124     // Expected has a narrow error() observer
error() const125     constexpr const E &error() const & { return base::assume_error(); }
error()126     constexpr E &error() & { return base::assume_error(); }
error() const127     constexpr const E &&error() const && { return base::assume_error(); }
error()128     constexpr E &error() && { return base::assume_error(); }
129   };
130   template <class E> class expected<void, E> : public BOOST_OUTCOME_V2_NAMESPACE::result<void, E, BOOST_OUTCOME_V2_NAMESPACE::policy::throw_bad_result_access<E, void>>
131   {
132     using base = BOOST_OUTCOME_V2_NAMESPACE::result<void, E, BOOST_OUTCOME_V2_NAMESPACE::policy::throw_bad_result_access<E, void>>;
133 
134   public:
135     // Inherit base constructors
136     using base::base;
137 
138     // Expected has a narrow operator* and operator->
operator *() const139     constexpr void operator*() const { base::assume_value(); }
operator ->() const140     constexpr void operator->() const { base::assume_value(); }
141   };
142   template <class E> using unexpected = BOOST_OUTCOME_V2_NAMESPACE::failure_type<E>;
make_unexpected(E && arg)143   template <class E> unexpected<E> make_unexpected(E &&arg) { return BOOST_OUTCOME_V2_NAMESPACE::failure<E>(std::forward<E>(arg)); }
make_unexpected(Args &&...args)144   template <class E, class... Args> unexpected<E> make_unexpected(Args &&... args) { return BOOST_OUTCOME_V2_NAMESPACE::failure<E>(std::forward<Args>(args)...); }
145   template <class E> using bad_expected_access = BOOST_OUTCOME_V2_NAMESPACE::bad_result_access_with<E>;
146   //! [expected_implementation]
147 
148   // Not actually part of the Expected proposal, but needed to pass the test
149   template <typename T> using exception_or = expected<T, std::exception_ptr>;
150 }  // namespace stde
151 
152 template <class T> using expected_sc = stde::expected<T, std::error_code>;
153 
154 struct NoDefaultConstructible
155 {
156   NoDefaultConstructible() = delete;
NoDefaultConstructibleNoDefaultConstructible157   NoDefaultConstructible(int /*unused*/) {}  // NOLINT
158 };
159 
160 struct NoCopyConstructible
161 {
162   NoCopyConstructible() = default;
163   NoCopyConstructible(NoCopyConstructible const &) = delete;
164   NoCopyConstructible(NoCopyConstructible &&) noexcept = default;
165 };
166 struct NoMoveConstructible
167 {
168   NoMoveConstructible() = default;
169   NoMoveConstructible(NoMoveConstructible const &) noexcept = default;
170   NoMoveConstructible(NoMoveConstructible &&) = delete;
171   NoMoveConstructible &operator=(NoMoveConstructible const &) noexcept = default;
172   NoMoveConstructible &operator=(NoMoveConstructible &&) = delete;
173 };
174 
175 enum State
176 {
177   sDefaultConstructed,
178   sValueCopyConstructed,
179   sValueMoveConstructed,
180   sCopyConstructed,
181   sMoveConstructed,
182   sMoveAssigned,
183   sCopyAssigned,
184   sValueCopyAssigned,
185   sValueMoveAssigned,
186   sMovedFrom,
187   sValueConstructed
188 };
189 
190 struct OracleVal
191 {
192   State s{sValueConstructed};
193   int i;
OracleValOracleVal194   constexpr OracleVal(int i_ = 0)  // NOLINT
195   : i(i_)
196   {
197   }
198 };
199 
200 struct Oracle
201 {
202   State s{sDefaultConstructed};
203   OracleVal val;
204 
205   Oracle() = default;
OracleOracle206   Oracle(const OracleVal &v)  // NOLINT
207   : s(sValueCopyConstructed),
208     val(v)
209   {
210   }
OracleOracle211   Oracle(OracleVal &&v) noexcept : s(sValueMoveConstructed), val(v) { v.s = sMovedFrom; }  // NOLINT
OracleOracle212   Oracle(const Oracle &o)
213       : s(sCopyConstructed)
214       , val(o.val)
215   {
216   }
OracleOracle217   Oracle(Oracle &&o) noexcept : s(sMoveConstructed), val(std::move(o.val)) { o.s = sMovedFrom; }  // NOLINT
218 
operator =Oracle219   Oracle &operator=(const OracleVal &v)
220   {
221     s = sValueCopyConstructed;
222     val = v;
223     return *this;
224   }
operator =Oracle225   Oracle &operator=(OracleVal &&v) noexcept
226   {
227     s = sValueMoveConstructed;
228     val = std::move(v);  // NOLINT
229     v.s = sMovedFrom;
230     return *this;
231   }
operator =Oracle232   Oracle &operator=(const Oracle &o)
233   {
234     s = sCopyConstructed;
235     val = o.val;
236     return *this;
237   }
operator =Oracle238   Oracle &operator=(Oracle &&o) noexcept
239   {
240     s = sMoveConstructed;
241     val = std::move(o.val);  // NOLINT
242     o.s = sMovedFrom;
243     return *this;
244   }
245 };
246 
247 struct Guard
248 {
249   std::string val;
250   Guard() = default;
GuardGuard251   explicit Guard(std::string s, int /*unused*/ = 0)
252       : val(std::move(s))
253   {
254   }
255   Guard(const Guard &) = delete;
256   Guard(Guard &&) = delete;
257   void operator=(const Guard &) = delete;
258   void operator=(Guard &&) = delete;
259 };
260 
261 struct ExplicitStr
262 {
263   std::string s;
ExplicitStrExplicitStr264   explicit ExplicitStr(const char *chp)
265       : s(chp)
266   {
267   }
268 };
269 
270 struct Date
271 {
272   int i;
273   Date() = delete;
DateDate274   Date(int i_) noexcept : i{i_} {}  // NOLINT
DateDate275   Date(Date &&d) noexcept : i(d.i) { d.i = 0; }
276   Date(const Date &) = delete;
277   Date &operator=(const Date &) = delete;
operator =Date278   Date &operator=(Date &&d) noexcept
279   {
280     i = d.i;
281     d.i = 0;
282     return *this;
283   }
284 };
285 
286 struct TExcept
287 {
288   int i;
289   TExcept() = delete;
TExceptTExcept290   TExcept(int i_)  // NOLINT
291   : i{i_}
292   {
293   }
TExceptTExcept294   TExcept(TExcept &&d)
295       : i(d.i)
296   {
297     d.i = 0;
298   }
299   TExcept(const TExcept &) = delete;
300   TExcept &operator=(const TExcept &) = delete;
operator =TExcept301   TExcept &operator=(TExcept &&d)
302   {
303     i = d.i;
304     d.i = 0;
305     return *this;
306   }
307 };
308 
309 template <class T> struct MoveAware
310 {
311   T val;
312   bool moved;
MoveAwareMoveAware313   MoveAware(T val_)  // NOLINT
314   : val(val_),
315     moved(false)
316   {
317   }
318   MoveAware(MoveAware const &) = delete;
MoveAwareMoveAware319   MoveAware(MoveAware &&rhs)
320       : val(rhs.val)
321       , moved(rhs.moved)
322   {
323     rhs.moved = true;
324   }
325   MoveAware &operator=(MoveAware const &) = delete;
operator =MoveAware326   MoveAware &operator=(MoveAware &&rhs)
327   {
328     val = (rhs.val);
329     moved = (rhs.moved);
330     rhs.moved = true;
331     return *this;
332   }
333 };
334 
335 struct OverloadedAddressOf
336 {
337   OverloadedAddressOf() = default;
operator &OverloadedAddressOf338   OverloadedAddressOf *operator&() const { return nullptr; }
339 };
340 
341 // using namespace boost;
342 // using namespace boost::functional;
343 
344 class test_exception : public std::exception
345 {
346 };
347 
throwing_fun()348 int throwing_fun()
349 {
350   throw test_exception();
351 }
nothrowing_fun()352 int nothrowing_fun()
353 {
354   return 4;
355 }
356 
void_throwing_fun()357 JASEL_NORETURN void void_throwing_fun()
358 {
359   throw test_exception();
360 }
do_nothing_fun()361 void do_nothing_fun()
362 {
363 }
364 
except_default_constructor()365 void except_default_constructor()
366 {
367   // From value constructor.
368   expected_sc<int> e{};
369   try
370   {
371     int i = e.value();
372     (void) i;
373     BOOST_TEST(true);
374   }
375   catch(...)
376   {
377     BOOST_TEST(false);
378   };
379   BOOST_TEST(e.has_value());
380   BOOST_TEST(e);
381   BOOST_TEST(static_cast<bool>(e));
382 }
383 
384 
except_default_constructor_error_code()385 void except_default_constructor_error_code()
386 {
387   // From value constructor.
388   stde::expected<int, std::error_code> e;
389   BOOST_TEST(e.has_value());
390   BOOST_TEST(e);
391   BOOST_TEST(static_cast<bool>(e));
392 }
393 
except_default_constructor_constexpr()394 void except_default_constructor_constexpr()
395 {
396   // From value constructor.
397   BOOST_CONSTEXPR stde::expected<int, long> e;
398   BOOST_TEST(e.has_value());
399 }
400 
expected_from_value()401 void expected_from_value()
402 {
403   // using T = int;
404   using E = std::error_code;
405 
406   // static_assert(noexcept(stde::adl::swap_impl(std::declval<T &>(), std::declval<T &>())), "");
407   static_assert(std::is_nothrow_copy_constructible<E>::value, "");
408   // static_assert(noexcept(stde::adl::swap_impl(std::declval<E &>(), std::declval<E &>())), "");
409 
410   static_assert(std::is_nothrow_copy_constructible<expected_sc<int>>::value, "");
411   static_assert(std::is_nothrow_copy_assignable<expected_sc<int>>::value, "");
412   static_assert(std::is_nothrow_move_constructible<expected_sc<int>>::value, "");
413   static_assert(std::is_nothrow_move_assignable<expected_sc<int>>::value, "");
414 
415   // From value constructor.
416   expected_sc<int> e(5);
417   // BOOST_REQUIRE_NO_THROW(e.value());
418   BOOST_TEST_EQ(e.value(), 5);
419   BOOST_TEST_EQ(*e, 5);
420   BOOST_TEST(e.has_value());
421   BOOST_TEST(static_cast<bool>(e));
422 }
423 
expected_from_value2()424 void expected_from_value2()
425 {
426   // From value constructor.
427   expected_sc<int> e(5);
428   e = {};
429   BOOST_TEST(e.has_value());
430   BOOST_TEST_EQ(e.value(), 0);
431 }
432 
expected_from_cnv_value()433 void expected_from_cnv_value()
434 {
435   OracleVal v;
436   expected_sc<Oracle> e(v);
437   // BOOST_REQUIRE_NO_THROW(e.value());
438   BOOST_TEST(!!e);
439   BOOST_TEST(e.has_value());
440   BOOST_TEST(bool(e));
441   BOOST_TEST_EQ(e.value().s, sValueCopyConstructed);
442   BOOST_TEST_EQ(v.s, sValueConstructed);
443 
444   expected_sc<Oracle> e2(std::move(v));  // NOLINT
445   // BOOST_REQUIRE_NO_THROW(e2.value());
446   BOOST_TEST(!!e2);
447   BOOST_TEST(e2.has_value());
448   BOOST_TEST(bool(e2));
449   BOOST_TEST_EQ(e2.value().s, sValueMoveConstructed);
450   BOOST_TEST_EQ(v.s, sMovedFrom);
451 }
452 
453 struct NDCE  // no default constructor
454 {            // (no default date exists)
NDCENDCE455   explicit NDCE(int /*unused*/) {}
456 };
457 
except_constructor_NDCE()458 void except_constructor_NDCE()
459 {
460   expected_sc<NDCE> e{NDCE{1}};
461   BOOST_TEST(e.has_value());
462 }
463 struct NDC                // no default constructor
464 {                         // (no default date exists)
NDCNDC465   NDC(int /*unused*/) {}  // NOLINT
466 };
467 
except_constructor_NDC()468 void except_constructor_NDC()
469 {
470   static_assert(std::is_nothrow_copy_constructible<expected_sc<NDC>>::value, "");
471   static_assert(std::is_nothrow_copy_assignable<expected_sc<NDC>>::value, "");
472   static_assert(std::is_nothrow_move_constructible<expected_sc<NDC>>::value, "");
473   static_assert(std::is_nothrow_move_assignable<expected_sc<NDC>>::value, "");
474   expected_sc<NDC> e{1};
475   BOOST_TEST(e.has_value());
476 }
477 
except_constructor_Date()478 void except_constructor_Date()
479 {
480   static_assert(std::is_nothrow_move_constructible<expected_sc<Date>>::value, "");
481   static_assert(std::is_nothrow_move_assignable<expected_sc<Date>>::value, "");
482   expected_sc<Date> e{Date{1}};
483   BOOST_TEST(e.has_value());
484 }
485 
except_constructor_TExcept()486 void except_constructor_TExcept()
487 {
488   static_assert(!std::is_nothrow_move_constructible<expected_sc<TExcept>>::value, "");
489   static_assert(!std::is_nothrow_move_assignable<expected_sc<TExcept>>::value, "");
490   expected_sc<TExcept> e{TExcept{1}};
491   BOOST_TEST(e.has_value());
492 }
493 
expected_from_in_place_value()494 void expected_from_in_place_value()
495 {
496   OracleVal v;
497   expected_sc<Oracle> e{stde::in_place, v};
498   // BOOST_REQUIRE_NO_THROW(e.value());
499   BOOST_TEST(!!e);
500   BOOST_TEST(e.has_value());
501   BOOST_TEST(bool(e));
502   BOOST_TEST_EQ(e.value().s, sValueCopyConstructed);
503   BOOST_TEST_EQ(v.s, sValueConstructed);
504 
505   expected_sc<Oracle> e2{stde::in_place, std::move(v)};  // NOLINT
506   // BOOST_REQUIRE_NO_THROW(e2.value());
507   BOOST_TEST(!!e2);
508   BOOST_TEST(e2.has_value());
509   BOOST_TEST(bool(e2));
510   BOOST_TEST_EQ(e2.value().s, sValueMoveConstructed);
511   BOOST_TEST_EQ(v.s, sMovedFrom);
512 }
513 
514 #if 0
515 void expected_from_exception()
516 {
517   // From stde::unexpected constructor.
518   stde::exception_or<int> e(stde::make_unexpected(test_exception()));
519   BOOST_TEST_THROWS(e.value(), test_exception);
520   BOOST_TEST_EQ(e.has_value(), false);
521   BOOST_TEST_EQ(static_cast<bool>(e), false);
522 }
523 #endif
524 
expected_from_copy_value()525 void expected_from_copy_value()
526 {
527   // From copy constructor.
528   expected_sc<int> ef(5);
529   expected_sc<int> e(ef);
530   // BOOST_REQUIRE_NO_THROW(e.value());
531   BOOST_TEST_EQ(e.value(), 5);
532   BOOST_TEST_EQ(*e, 5);
533   BOOST_TEST(e.has_value());
534   BOOST_TEST(static_cast<bool>(e));
535 }
536 
537 #if 0
538 void expected_from_copy_exception()
539 {
540   // From stde::unexpected constructor.
541   stde::exception_or<int> ef(stde::make_unexpected(test_exception()));
542   stde::exception_or<int> e(ef);
543   BOOST_TEST_THROWS(e.value(), test_exception);
544   BOOST_TEST_EQ(e.has_value(), false);
545   BOOST_TEST_EQ(static_cast<bool>(e), false);
546 }
547 #endif
548 
expected_from_in_place()549 void expected_from_in_place()
550 {
551   // From stde::in_place constructor.
552   expected_sc<std::string> e(stde::in_place, "stde::in_place");
553   // BOOST_REQUIRE_NO_THROW(e.value());
554   BOOST_TEST_EQ(e.value(), "stde::in_place");
555   BOOST_TEST_EQ(*e, "stde::in_place");
556   BOOST_TEST(e.has_value());
557   BOOST_TEST(static_cast<bool>(e));
558 }
559 
560 #if 0
561 void expected_from_exception_ptr()
562 {
563   // From exception_ptr constructor.
564   stde::exception_or<int> e(stde::make_unexpected(std::make_exception_ptr(test_exception())));
565   BOOST_TEST_THROWS(e.value(), test_exception);
566   BOOST_TEST_EQ(e.has_value(), false);
567   BOOST_TEST_EQ(static_cast<bool>(e), false);
568 }
569 #endif
570 
expected_from_moved_value()571 void expected_from_moved_value()
572 {
573   // From move value constructor.
574   std::string value = "my value";
575   expected_sc<std::string> e = std::move(value);
576   // BOOST_REQUIRE_NO_THROW(e.value());
577   BOOST_TEST_EQ(e.value(), "my value");
578   BOOST_TEST_EQ(*e, "my value");
579   BOOST_TEST(e.has_value());
580   BOOST_TEST(static_cast<bool>(e));
581 }
582 
expected_from_catch_block()583 void expected_from_catch_block()
584 {
585   // From catch block
586   try
587   {
588     throw test_exception();
589   }
590   catch(...)
591   {
592     stde::exception_or<int> e(stde::make_unexpected(std::current_exception()));
593 
594     BOOST_TEST_THROWS(e.value(), std::exception);
595     BOOST_TEST_EQ(e.has_value(), false);
596     BOOST_TEST_EQ(static_cast<bool>(e), false);
597   }
598 }
599 
600 
make_expected_E_from_value()601 void make_expected_E_from_value()
602 {
603   // auto e = stde::make_expected<std::string>( 5 );
604   // BOOST_TEST_EQ(e.has_value(), false);
605 }
make_expected_const_from_value()606 void make_expected_const_from_value()
607 {
608 #if defined __clang__ && __clang_major__ >= 4 && __cplusplus > 201402L
609   const int i = 0;
610   auto e = expected_sc<const int>(i);
611   (void) e;
612 // static_assert(std::is_same<decltype(e), stde::success<const int>>::value, "");
613 #endif
614 }
make_expected_from_U_value()615 void make_expected_from_U_value()
616 {
617   expected_sc<int> e = expected_sc<int>(short(5));
618   static_assert(std::is_same<decltype(e), expected_sc<int>>{}, "");
619   BOOST_TEST_EQ(e.has_value(), true);
620 }
make_expected_from_U_value2()621 void make_expected_from_U_value2()
622 {
623   expected_sc<std::string> e = expected_sc<std::string>("aa");
624   static_assert(std::is_same<decltype(e), expected_sc<std::string>>{}, "");
625   BOOST_TEST_EQ(e.has_value(), true);
626 }
627 
expected_from_value_error_condition()628 void expected_from_value_error_condition()
629 {
630   // From value constructor.
631   stde::expected<int, std::error_condition> e(5);
632   // BOOST_REQUIRE_NO_THROW(e.value());
633   BOOST_TEST_EQ(e.value(), 5);
634   BOOST_TEST_EQ(*e, 5);
635   BOOST_TEST(e.has_value());
636   BOOST_TEST(static_cast<bool>(e));
637 }
638 
expected_from_error_error_condition()639 void expected_from_error_error_condition()
640 {
641   // From stde::unexpected constructor.
642   stde::expected<int, std::error_condition> e(stde::make_unexpected<std::error_condition>(std::make_error_condition(std::errc::invalid_argument)));
643   auto error_from_except_check = [](const stde::bad_expected_access<std::error_condition> &except) { return std::errc(except.error().value()) == std::errc::invalid_argument; };
644   try
645   {
646     (void) e.value();
647   }
648   catch(stde::bad_expected_access<std::error_condition> &ex)
649   {
650     BOOST_TEST(error_from_except_check(ex));
651   }
652   BOOST_TEST_EQ(e.has_value(), false);
653   BOOST_TEST_EQ(static_cast<bool>(e), false);
654 }
655 
656 
expected_from_error_convertible()657 void expected_from_error_convertible()
658 {
659   {
660     stde::expected<int, short> e1 = stde::make_unexpected<short>(1);
661     stde::expected<int, long> e2(e1);
662     BOOST_TEST_EQ(e2.has_value(), false);
663     BOOST_TEST_EQ(static_cast<bool>(e2), false);
664     BOOST_TEST_EQ(e2.error(), 1);
665   }
666   {
667     stde::expected<void, short> e1 = stde::make_unexpected<short>(1);
668     stde::expected<void, int> e2(e1);
669     BOOST_TEST_EQ(e2.has_value(), false);
670     BOOST_TEST_EQ(static_cast<bool>(e2), false);
671     BOOST_TEST_EQ(e2.error(), 1);
672   }
673 }
674 
except_valid_constexpr_int()675 void except_valid_constexpr_int()
676 {
677   // From value constructor.
678   BOOST_CONSTEXPR stde::expected<int, long> e;
679   BOOST_CONSTEXPR bool b = e.has_value();
680   BOOST_TEST(b);
681 }
except_value_constexpr_int()682 void except_value_constexpr_int()
683 {
684   // From value constructor.
685   BOOST_CONSTEXPR stde::expected<int, long> e(1);
686   BOOST_CONSTEXPR int x = e.value();
687   BOOST_TEST_EQ(x, 1);
688 }
689 
expected_from_value3()690 void expected_from_value3()
691 {
692   expected_sc<int> e(5);
693   BOOST_TEST_EQ(e.value(), 5);
694 
695   // From value assignment.
696   e = 8;
697   // BOOST_REQUIRE_NO_THROW(e.value());
698   BOOST_TEST_EQ(e.value(), 8);
699   BOOST_TEST_EQ(*e, 8);
700   BOOST_TEST(e.has_value());
701   BOOST_TEST(static_cast<bool>(e));
702 }
703 
expected_from_copy_expected()704 void expected_from_copy_expected()
705 {
706   expected_sc<int> e(5);
707   expected_sc<int> e2(8);
708 
709   // From value assignment.
710   e = e2;
711   // BOOST_REQUIRE_NO_THROW(e.value());
712   BOOST_TEST_EQ(e.value(), 8);
713   BOOST_TEST_EQ(*e, 8);
714   BOOST_TEST(e.has_value());
715   BOOST_TEST(static_cast<bool>(e));
716 }
717 
expected_from_moved_expected()718 void expected_from_moved_expected()
719 {
720   expected_sc<std::string> e("e");
721   expected_sc<std::string> e2("e2");
722 
723   // From value assignment.
724   e = std::move(e2);
725   // BOOST_REQUIRE_NO_THROW(e.value());
726   BOOST_TEST_EQ(e.value(), "e2");
727   BOOST_TEST_EQ(*e, "e2");
728   BOOST_TEST(e.has_value());
729   BOOST_TEST(static_cast<bool>(e));
730 
731 // BOOST_REQUIRE_NO_THROW(e2.value());
732 #ifndef __GLIBBOOST_OUTCOME_C__
733   BOOST_TEST_EQ(e2.value(), "");
734   BOOST_TEST_EQ(*e2, "");
735 #endif
736   BOOST_TEST(e2.has_value());
737   BOOST_TEST(static_cast<bool>(e2));
738 }
739 
expected_from_in_place2()740 void expected_from_in_place2()
741 {
742   // From stde::in_place constructor.
743   expected_sc<std::string> e(stde::in_place, "stde::in_place");
744   BOOST_TEST_EQ(e.value(), "stde::in_place");
745 
746   // From emplace method.
747   e.emplace("emplace method");
748   // BOOST_REQUIRE_NO_THROW(e.value());
749   BOOST_TEST_EQ(e.value(), "emplace method");
750   BOOST_TEST_EQ(*e, "emplace method");
751   BOOST_TEST(e.has_value());
752   BOOST_TEST(static_cast<bool>(e));
753 }
754 
expected_from_move_value()755 void expected_from_move_value()
756 {
757   expected_sc<std::string> e("v");
758 
759   std::string value = "my value";
760   // From assignment operator.
761   e = std::move(value);
762   // BOOST_REQUIRE_NO_THROW(e.value());
763   BOOST_TEST_EQ(e.value(), "my value");
764   BOOST_TEST_EQ(*e, "my value");
765   BOOST_TEST(e.has_value());
766   BOOST_TEST(static_cast<bool>(e));
767 }
768 
769 
expected_from_in_place3()770 void expected_from_in_place3()
771 {
772   // From stde::in_place factory.
773   // auto e = stde::make_expected<std::string>("stde::in_place");
774   auto e = expected_sc<std::string>("stde::in_place");
775   // BOOST_REQUIRE_NO_THROW(e.value());
776   BOOST_TEST_EQ(e.value(), "stde::in_place");
777   BOOST_TEST_EQ(*e, "stde::in_place");
778   BOOST_TEST(e.has_value());
779   BOOST_TEST(static_cast<bool>(e));
780 }
expected_from_in_place_error()781 void expected_from_in_place_error()
782 {
783   // From stde::in_place factory.
784   auto e = stde::expected<std::string, std::error_condition>("stde::in_place");
785   // BOOST_REQUIRE_NO_THROW(e.value());
786   BOOST_TEST_EQ(e.value(), "stde::in_place");
787   BOOST_TEST_EQ(*e, "stde::in_place");
788   BOOST_TEST(e.has_value());
789   BOOST_TEST(static_cast<bool>(e));
790 }
791 
expected_from_exception_catch()792 void expected_from_exception_catch()
793 {
794   // From catch block
795   try
796   {
797     throw test_exception();
798   }
799   catch(...)
800   {
801     stde::exception_or<int> e = stde::make_unexpected(std::current_exception());
802 
803     BOOST_TEST_THROWS(e.value(), std::exception);
804     BOOST_TEST_EQ(e.has_value(), false);
805     BOOST_TEST_EQ(static_cast<bool>(e), false);
806   }
807 }
808 
809 #if 0
810 void expected_from_error()
811 {
812   // From stde::unexpected constructor.
813   auto e = stde::make_expected_from_error<int>(std::make_error_condition(std::errc::invalid_argument));
814   auto error_from_except_check = [](const stde::bad_expected_access<std::error_condition> &except) { return std::errc(except.error().value()) == std::errc::invalid_argument; };
815   try
816   {
817     (void) e.value();
818   }
819   catch(stde::bad_expected_access<std::error_condition> &ex)
820   {
821     BOOST_TEST(error_from_except_check(ex));
822   }
823   BOOST_TEST_EQ(e.has_value(), false);
824   BOOST_TEST_EQ(static_cast<bool>(e), false);
825 }
826 
827 void expected_from_error_U()
828 {
829   // From stde::unexpected constructor.
830   auto e = stde::make_expected_from_error<int, short>(42);
831   static_assert(std::is_same<decltype(e), stde::expected<int, short>>{}, "");
832   BOOST_TEST_EQ(e.has_value(), false);
833   BOOST_TEST_EQ(static_cast<bool>(e), false);
834 }
835 
836 void expected_from_exception2()
837 {
838   // From stde::unexpected constructor.
839   auto e = stde::make_expected_from_exception<int>(test_exception());
840   // auto e = expected_sc<int>(stde::unexpected<>(test_exception()));
841   BOOST_TEST_THROWS(e.value(),  test_exception );
842   BOOST_TEST_EQ(e.has_value(), false);
843   BOOST_TEST_EQ(static_cast<bool>(e), false);
844 }
845 
846 void expected_from_exception_ptr2()
847 {
848   // From exception_ptr constructor.
849   auto e = stde::exception_or<int>(stde::make_unexpected(test_exception()));
850   BOOST_TEST_THROWS(e.value(),  test_exception );
851   BOOST_TEST_EQ(e.has_value(), false);
852   BOOST_TEST_EQ(static_cast<bool>(e), false);
853 }
854 
855 void make_expected_from_call_fun()
856 {
857   try
858   {
859     stde::make_expected_from_call(throwing_fun);
860     BOOST_TEST(true);
861   }
862   catch(...)
863   {
864     BOOST_TEST(false);
865   }
866   stde::exception_or<int> e = stde::make_expected_from_call(throwing_fun);
867   BOOST_TEST_THROWS(e.value(),  std::exception );
868   BOOST_TEST_EQ(e.has_value(), false);
869   BOOST_TEST_EQ(static_cast<bool>(e), false);
870 
871   e = stde::make_expected_from_call(nothrowing_fun);
872   try
873   {
874     (void) e.value();
875     BOOST_TEST(true);
876   }
877   catch(...)
878   {
879     BOOST_TEST(false);
880   }
881   BOOST_TEST_EQ(e.value(), 4);
882   BOOST_TEST_EQ(*e, 4);
883   BOOST_TEST_EQ(e.has_value(), true);
884   BOOST_TEST_EQ(static_cast<bool>(e), true);
885 
886 #if 0
887   BOOST_TEST_THROWS(stde::make_expected_from_call<std::error_condition>(throwing_fun), test_exception);
888 
889   BOOST_TEST_NO_THROW(stde::make_expected_from_call<std::error_condition>(nothrowing_fun));
890   stde::expected<int, std::error_condition> e2 = stde::make_expected_from_call<std::error_condition>(nothrowing_fun);
891   BOOST_TEST_NO_THROW(e2.value());
892   BOOST_TEST_EQ(e2.value(), 4);
893   BOOST_TEST_EQ(*e2, 4);
894   BOOST_TEST_EQ(e2.has_value(), true);
895   BOOST_TEST_EQ(static_cast<bool>(e2), true);
896 #endif
897 }
898 
899 void make_expected_from_call_void_fun()
900 {
901 #if 0
902   BOOST_TEST_NO_THROW(stde::make_expected_from_call(void_throwing_fun));
903   expected_sc<void> e = stde::make_expected_from_call(void_throwing_fun);
904   BOOST_TEST_THROWS(e.value(), std::exception);
905   BOOST_TEST_EQ(e.has_value(), false);
906   BOOST_TEST_EQ(static_cast<bool>(e), false);
907 
908   e = stde::make_expected_from_call(do_nothing_fun);
909   BOOST_TEST_NO_THROW(e.value());
910   BOOST_TEST_EQ(e.has_value(), true);
911   BOOST_TEST_EQ(static_cast<bool>(e), true);
912 
913   BOOST_TEST_THROWS(stde::make_expected_from_call<std::error_condition>(void_throwing_fun), test_exception);
914 
915   try {
916     stde::make_expected_from_call<std::error_condition>(do_nothing_fun);
917     BOOST_TEST(true);
918   }
919   catch (...)
920   {
921     BOOST_TEST(false);
922   }
923   stde::expected<void, std::error_condition> e2 = stde::make_expected_from_call<std::error_condition>(do_nothing_fun);
924   try {
925     (void)e2.value();
926     BOOST_TEST(true);
927   }
928   catch (...)
929   {
930     BOOST_TEST(false);
931   }
932   //BOOST_TEST_NO_THROW(e2.value());
933   BOOST_TEST_EQ(e2.has_value(), true);
934   BOOST_TEST_EQ(static_cast<bool>(e2), true);
935 #endif
936 }
937 #endif
938 
expected_swap_value()939 void expected_swap_value()
940 {
941   // From value constructor.
942   expected_sc<int> e(5);
943   expected_sc<int> e2(8);
944 
945   e.swap(e2);
946 
947   BOOST_TEST_EQ(e.value(), 8);
948   BOOST_TEST_EQ(e2.value(), 5);
949 
950   e2.swap(e);
951 
952   BOOST_TEST_EQ(e.value(), 5);
953   BOOST_TEST_EQ(e2.value(), 8);
954 }
955 
956 #if 0
957 void expected_swap_exception()
958 {
959   // From value constructor.
960   stde::exception_or<int> e = stde::make_unexpected(std::invalid_argument("e"));
961   stde::exception_or<int> e2 = stde::make_unexpected(std::invalid_argument("e2"));
962 
963   e.swap(e2);
964 
965   auto equal_to_e = [](const std::invalid_argument &except) { return std::string(except.what()) == "e"; };
966   auto equal_to_e2 = [](const std::invalid_argument &except) { return std::string(except.what()) == "e2"; };
967 
968   try
969   {
970     (void) e.value();
971     BOOST_TEST(true);
972   }
973   catch(std::invalid_argument &ex)
974   {
975     BOOST_TEST(equal_to_e2(ex));
976   }
977   try
978   {
979     (void) e2.value();
980     BOOST_TEST(true);
981   }
982   catch(std::invalid_argument &ex)
983   {
984     BOOST_TEST(equal_to_e(ex));
985   }
986 
987   e2.swap(e);
988 
989   try
990   {
991     (void) e.value();
992     BOOST_TEST(true);
993   }
994   catch(std::invalid_argument &ex)
995   {
996     BOOST_TEST(equal_to_e(ex));
997   }
998   try
999   {
1000     (void) e2.value();
1001     BOOST_TEST(true);
1002   }
1003   catch(std::invalid_argument &ex)
1004   {
1005     BOOST_TEST(equal_to_e2(ex));
1006   }
1007 }
1008 #endif
1009 
expected_swap_function_value()1010 void expected_swap_function_value()
1011 {
1012   // From value constructor.
1013   expected_sc<int> e(5);
1014   expected_sc<int> e2(8);
1015 
1016   swap(e, e2);
1017 
1018   BOOST_TEST_EQ(e.value(), 8);
1019   BOOST_TEST_EQ(e2.value(), 5);
1020 
1021   swap(e, e2);
1022 
1023   BOOST_TEST_EQ(e.value(), 5);
1024   BOOST_TEST_EQ(e2.value(), 8);
1025 }
1026 
1027 
1028 #ifdef QUICKCPPLIB_BOOST_UNIT_TEST_HPP
main()1029 int main()
1030 #else
1031 BOOST_AUTO_TEST_CASE(expected_pass)
1032 #endif
1033 {
1034 
1035   static_assert(!std::is_default_constructible<NoDefaultConstructible>::value, "");
1036   static_assert(!std::is_default_constructible<expected_sc<NoDefaultConstructible>>::value, "");
1037 
1038   static_assert(!std::is_copy_constructible<NoCopyConstructible>::value, "");
1039   static_assert(!std::is_constructible<expected_sc<NoCopyConstructible>, NoCopyConstructible const &>::value, "");
1040   static_assert(!std::is_constructible<stde::exception_or<NoCopyConstructible>, stde::exception_or<NoCopyConstructible> const &>::value, "");
1041   static_assert(!std::is_copy_constructible<stde::exception_or<NoCopyConstructible>>::value, "");
1042 
1043 #if 0
1044   // fixme
1045   {
1046     NoMoveConstructible nmc;
1047     // NoMoveConstructible nmc2 = std::move(nmc); // FAILS as expected
1048 
1049     expected_sc<NoMoveConstructible> x{std::move(nmc)};  // DOESN'T FAIL as copy is selected instead
1050     (void) x;
1051   }
1052 // fixme
1053 #if defined __clang__ && __clang_major__ >= 4 && __cplusplus > 201402L
1054   {
1055     NoMoveConstructible nmc;
1056     // NoMoveConstructible nmc2 = std::move(nmc); // FAILS as expected
1057 
1058     expected_sc<NoMoveConstructible> x = std::move(nmc);  // DOESN'T FAIL as copy is selected instead
1059     (void) x;
1060   }
1061 #endif
1062 #endif
1063 
1064   static_assert(!std::is_move_constructible<NoMoveConstructible>::value, "");
1065   static_assert(!std::is_constructible<expected_sc<NoMoveConstructible>, NoMoveConstructible &&>::value, "");
1066   static_assert(std::is_move_constructible<expected_sc<NoMoveConstructible>>::value, "");
1067 
1068   except_default_constructor();
1069   except_default_constructor_error_code();
1070   except_default_constructor_constexpr();
1071   expected_from_value();
1072   expected_from_value2();
1073   expected_from_cnv_value();
1074   except_constructor_NDCE();
1075   except_constructor_NDC();
1076   except_constructor_Date();
1077   expected_from_in_place_value();
1078   // expected_from_exception();
1079   expected_from_copy_value();
1080   // expected_from_copy_exception();
1081   expected_from_in_place();
1082   // expected_from_exception_ptr();
1083   expected_from_moved_value();
1084   expected_from_catch_block();
1085   make_expected_E_from_value();
1086   make_expected_const_from_value();
1087   make_expected_from_U_value2();
1088   expected_from_value_error_condition();
1089   expected_from_error_error_condition();
1090   expected_from_error_convertible();
1091   except_valid_constexpr_int();
1092   except_value_constexpr_int();
1093   expected_from_value3();
1094   expected_from_copy_expected();
1095   expected_from_moved_expected();
1096   expected_from_in_place2();
1097   expected_from_move_value();
1098   expected_from_in_place3();
1099   expected_from_in_place_error();
1100   expected_from_exception_catch();
1101   // expected_from_error();
1102   // expected_from_error_U();
1103   // expected_from_exception2();
1104   // expected_from_exception_ptr2();
1105   // make_expected_from_call_fun();
1106   // make_expected_from_call_void_fun();
1107   expected_swap_value();
1108   // expected_swap_exception();
1109   expected_swap_function_value();
1110 
1111 #ifdef QUICKCPPLIB_BOOST_UNIT_TEST_HPP
1112   return QUICKCPPLIB_NAMESPACE::unit_test::current_test_case()->fails != 0;
1113 #endif
1114 }
1115 
1116 #if 0
1117 ///////////////////////////////////////////////////////////////////////////////////////////////
1118 ///////////////////////////////////////////////////////////////////////////////////////////////
1119 ///////////////////////////////////////////////////////////////////////////////////////////////
1120 ///////////////////////////////////////////////////////////////////////////////////////////////
1121 
1122 
1123 //void expected_from_error_catch_exception)
1124 //{
1125 //  // From catch block
1126 //  try
1127 //  {
1128 //    throw test_exception();
1129 //  }
1130 //  catch(...)
1131 //  {
1132 //    auto throw_lambda = [](){ return stde::make_expected_from_error<int,std::error_condition>();};
1133 //
1134 //    //BOOST_TEST_THROWS(throw_lambda(), test_exception);
1135 //  }
1136 //}
1137 
1138 
1139 
1140 ////////////////////////////////////
1141 BOOST_AUTO_TEST_SUITE(expected_map)
1142 
1143 void expected_map()
1144 {
1145   auto fun = [](bool b) -> expected_sc<int>
1146   {
1147     if (b)
1148       return stde::make_expected(5);
1149     else
1150       return stde::make_unexpected(test_exception());
1151   };
1152 
1153   auto add_five = [](int sum) -> int
1154   {
1155     return sum + 5;
1156   };
1157 
1158   auto launch_except = [](int sum) -> int
1159   {
1160     throw test_exception();
1161   };
1162 
1163   expected_sc<int> e = fun(true).map(add_five);
1164   BOOST_TEST_NO_THROW(e.value());
1165   BOOST_TEST_EQ(*e, 10);
1166 
1167   e = fun(true).map(add_five).map(add_five);
1168   BOOST_TEST_NO_THROW(e.value());
1169   BOOST_TEST_EQ(*e, 15);
1170 
1171   e = fun(false).map(add_five).map(add_five);
1172   BOOST_TEST_THROWS(e.value(), test_exception);
1173 
1174   BOOST_TEST_THROWS(fun(true).map(launch_except), test_exception);
1175 
1176 }
1177 
1178 void expected_void_map()
1179 {
1180   auto fun = [](bool b)
1181   {
1182     if (b)
1183       return stde::make_expected();
1184     else
1185       return expected_sc<void>(stde::make_unexpected(test_exception()));
1186   };
1187 
1188   auto launch_except = []() -> void
1189   {
1190     throw test_exception();
1191   };
1192 
1193   auto do_nothing = []() {};
1194 
1195   expected_sc<void> e = fun(true).map(do_nothing);
1196   BOOST_TEST_NO_THROW(e.value());
1197 
1198   e = fun(false).map(do_nothing);
1199   BOOST_TEST_THROWS(e.value(), test_exception);
1200 
1201   BOOST_TEST_THROWS(fun(true).map(launch_except), test_exception);
1202 
1203 }
1204 
1205 BOOST_AUTO_TEST_SUITE_END()
1206 
1207 ////////////////////////////////////
1208 BOOST_AUTO_TEST_SUITE(expected_bind)
1209 
1210 void expected_bind()
1211 {
1212   auto fun = [](bool b) -> expected_sc<int>
1213   {
1214     if (b)
1215       return stde::make_expected(5);
1216     else
1217       return stde::make_unexpected(test_exception());
1218   };
1219 
1220   auto add_five = [](int sum) -> expected_sc<int>
1221   {
1222     return stde::make_expected(sum + 5);
1223   };
1224 
1225   auto launch_except = [](int sum) -> expected_sc<int>
1226   {
1227     throw test_exception();
1228   };
1229 
1230   expected_sc<int> e = fun(true).bind(add_five);
1231   BOOST_TEST_NO_THROW(e.value());
1232   BOOST_TEST_EQ(*e, 10);
1233 
1234   e = fun(true).bind(add_five).bind(add_five);
1235   BOOST_TEST_NO_THROW(e.value());
1236   BOOST_TEST_EQ(*e, 15);
1237 
1238   e = fun(false).bind(add_five).bind(add_five);
1239   BOOST_TEST_THROWS(e.value(), test_exception);
1240 
1241   BOOST_TEST_THROWS(fun(true).bind(launch_except), test_exception);
1242 
1243 }
1244 
1245 void expected_void_bind()
1246 {
1247   auto fun = [](bool b)
1248   {
1249     if (b)
1250       return stde::make_expected();
1251     else
1252       return expected_sc<void>(stde::make_unexpected(test_exception()));
1253   };
1254 
1255   auto launch_except = []() -> expected_sc<void>
1256   {
1257     throw test_exception();
1258   };
1259 
1260   auto do_nothing = []() {
1261     return stde::make_expected();
1262   };
1263 
1264   expected_sc<void> e = fun(true).bind(do_nothing);
1265   BOOST_TEST_NO_THROW(e.value());
1266 
1267   e = fun(false).bind(do_nothing);
1268   BOOST_TEST_THROWS(e.value(), test_exception);
1269 
1270   BOOST_TEST_THROWS(fun(true).bind(launch_except), test_exception);
1271 
1272 }
1273 
1274 BOOST_AUTO_TEST_SUITE_END()
1275 
1276 
1277 ////////////////////////////////////
1278 BOOST_AUTO_TEST_SUITE(expected_then)
1279 
1280 void expected_non_void_then()
1281 {
1282   auto fun = [](bool b) -> expected_sc<int>
1283   {
1284     if (b)
1285       return stde::make_expected(5);
1286     else
1287       return stde::make_unexpected(test_exception());
1288   };
1289 
1290 
1291   auto add_five = [](int sum) -> int
1292   {
1293     return sum + 5;
1294   };
1295   auto six = []() -> int
1296   {
1297     return 6;
1298   };
1299 
1300   auto pair = [](int a) -> bool
1301   {
1302     return (a % 2) == 0;
1303   };
1304 
1305   auto launch_except = [](int sum) -> int
1306   {
1307     throw test_exception();
1308   };
1309 
1310   auto then_launch_except = [](expected<int>) -> int
1311   {
1312     throw test_exception();
1313   };
1314 
1315   expected_sc<int> e = fun(true).then(if_valued(add_five));
1316   BOOST_TEST_NO_THROW(e.value());
1317   BOOST_TEST_EQ(*e, 10);
1318 
1319   e = fun(true).then(if_valued(ident(six)));
1320   BOOST_TEST_NO_THROW(e.value());
1321   BOOST_TEST_EQ(*e, 6);
1322 
1323   e = fun(false).then(if_unexpected(ident(six)));
1324   BOOST_TEST_NO_THROW(e.value());
1325   BOOST_TEST_EQ(*e, 6);
1326 
1327   expected_sc<bool> e1 = fun(true).then(if_valued(pair));
1328   BOOST_TEST_NO_THROW(e1.value());
1329   BOOST_TEST_EQ(*e1, false);
1330 
1331 
1332 
1333   e = fun(true).then(if_valued(add_five)).then(if_valued(add_five));
1334   BOOST_TEST_NO_THROW(e.value());
1335   BOOST_TEST_EQ(*e, 15);
1336 
1337   e = fun(false).then(if_valued(add_five)).then(if_valued(add_five));
1338   BOOST_TEST_THROWS(e.value(), test_exception);
1339 
1340   BOOST_TEST_THROWS(fun(true).then(if_valued(launch_except)), test_exception);
1341 
1342   e = fun(false).then(catch_all(then_launch_except));
1343   BOOST_TEST_THROWS(e.value(), test_exception);
1344 
1345 }
1346 
1347 void expected_void_then()
1348 {
1349   auto fun = [](bool b) -> expected_sc<void>
1350   {
1351     if (b)
1352       return stde::make_expected();
1353     else
1354       return stde::make_unexpected(test_exception());
1355   };
1356 
1357   auto launch_except = []()
1358   {
1359     throw test_exception();
1360   };
1361 
1362   auto do_nothing = []() {};
1363 
1364   BOOST_TEST(true);
1365   expected_sc<void> e = fun(true).then(if_valued(do_nothing));
1366   BOOST_TEST_NO_THROW(e.value());
1367 
1368   e = fun(false).then(if_valued(do_nothing));
1369   BOOST_TEST_THROWS(e.value(), test_exception);
1370 
1371   BOOST_TEST_THROWS(fun(true).then(if_valued(launch_except)), test_exception);
1372 
1373 }
1374 
1375 BOOST_AUTO_TEST_SUITE_END()
1376 
1377 BOOST_AUTO_TEST_SUITE(expected_recover)
1378 
1379 void expected_recover()
1380 {
1381   auto fun = [](bool b)
1382   {
1383     if (b)
1384       return expected_sc<int>(5);
1385     else
1386       return expected_sc<int>(stde::make_unexpected(test_exception()));
1387   };
1388 
1389   auto add_five = [](int sum) -> expected_sc<int>
1390   {
1391     return stde::make_expected(sum + 5);
1392   };
1393 
1394   auto recover_error = [](std::exception_ptr p)
1395   {
1396     return stde::make_expected(0);
1397   };
1398 
1399   auto recover_error_silent_failure = [](std::exception_ptr p)
1400   {
1401     return expected_sc<int>(stde::make_unexpected(p));
1402   };
1403 
1404   auto recover_error_failure = [](std::exception_ptr p) -> expected_sc<int>
1405   {
1406     return expected_sc<int>(stde::make_unexpected(test_exception()));
1407   };
1408 
1409   auto recover_error_throws = [](std::exception_ptr p) -> expected_sc<int>
1410   {
1411     throw test_exception();
1412   };
1413 
1414   BOOST_TEST_EQ(fun(false).catch_error(recover_error).has_value(), true);
1415   BOOST_TEST_EQ(fun(false).catch_error(recover_error).value(), 0);
1416   BOOST_TEST_EQ(fun(true).catch_error(recover_error).value(), 5);
1417   BOOST_TEST_EQ(fun(false).catch_error(recover_error_silent_failure).has_value(), false);
1418   BOOST_TEST_EQ(fun(false).catch_error(recover_error_failure).has_value(), false);
1419 
1420   BOOST_TEST_EQ(fun(true).bind(add_five).value(), 10);
1421   BOOST_TEST_EQ(fun(true).bind(add_five).catch_error(recover_error).value(), 10);
1422   BOOST_TEST_EQ(fun(true).bind(add_five).catch_error(recover_error_silent_failure).value(), 10);
1423   BOOST_TEST_EQ(fun(true).bind(add_five).catch_error(recover_error_failure).value(), 10);
1424 
1425   BOOST_TEST_EQ(fun(false).catch_error(recover_error).bind(add_five).value(), 5);
1426   BOOST_TEST_EQ(fun(false).catch_error(recover_error).bind(add_five).bind(add_five).value(), 10);
1427   BOOST_TEST_EQ(fun(false).catch_error(recover_error_failure).bind(add_five).has_value(), false);
1428   BOOST_TEST_EQ(fun(false).bind(add_five).catch_error(recover_error_failure).bind(add_five).has_value(), false);
1429   BOOST_TEST_EQ(fun(false).bind(add_five).catch_error(recover_error_silent_failure).bind(add_five).has_value(), false);
1430 
1431   BOOST_TEST_THROWS(fun(false).catch_error(recover_error_throws), test_exception);
1432 
1433 }
1434 
1435 void expected_void_recover()
1436 {
1437   auto fun = [](bool b)
1438   {
1439     if (b)
1440       return stde::make_expected();
1441     else
1442       return expected_sc<void>(boost::stde::make_unexpected(test_exception()));
1443   };
1444 
1445   auto do_nothing = []() {
1446     return stde::make_expected();
1447   };
1448 
1449   auto recover_error = [](std::exception_ptr p)
1450   {
1451     return stde::make_expected();
1452   };
1453 
1454   auto recover_error_silent_failure = [](std::exception_ptr p)
1455   {
1456     return expected_sc<void>(boost::stde::make_unexpected(p));
1457   };
1458 
1459   auto recover_error_failure = [](std::exception_ptr p) -> expected_sc<void>
1460   {
1461     throw test_exception();
1462   };
1463 
1464   // The catch_error doesn't alter the stde::expected if it's valid.
1465   BOOST_TEST_EQ(fun(true).catch_error(recover_error_failure).has_value(), true);
1466 
1467   // Simple catch_error tests.
1468   BOOST_TEST_EQ(fun(false).catch_error(recover_error).has_value(), true);
1469   BOOST_TEST_THROWS(fun(false).catch_error(recover_error_failure), test_exception);
1470   BOOST_TEST_EQ(fun(false).catch_error(recover_error_silent_failure).has_value(), false);
1471 
1472   // With a bind between.
1473   BOOST_TEST_THROWS(fun(false).bind(do_nothing).catch_error(recover_error_failure), test_exception);
1474 
1475 }
1476 BOOST_AUTO_TEST_SUITE_END()
1477 
1478 BOOST_AUTO_TEST_SUITE(proposal)
1479 
1480 void proposal_concept()
1481 {
1482   using namespace std;
1483 
1484   {
1485     stde::expected<int, string> ei = 0;
1486     stde::expected<int, string> ej = 1;
1487     stde::expected<int, string> ek = stde::make_unexpected(string());
1488 
1489     ei = 1;
1490     ej = stde::make_unexpected(string());;
1491     ek = 0;
1492 
1493     ei = stde::make_unexpected(string());;
1494     ej = 0;
1495     ek = 1;
1496   }
1497 }
1498 void proposal_init()
1499 {
1500   using namespace std;
1501   {
1502     string s{ "STR" };
1503 
1504     stde::expected<string, int> ep{ stde::make_unexpected(-1) };              // unexpected value, requires Movable<E>
1505     stde::expected<string, int> eq = { stde::make_unexpected(-1) };           // unexpected value, requires Movable<E>
1506 
1507     expected_sc<string> es{ s };                    // requires Copyable<T>
1508     expected_sc<string> et = s;                   // requires Copyable<T>
1509     expected_sc<string> ev = string{ "STR" };       // requires Movable<T>
1510 
1511     expected_sc<string> ew;                       // unexpected value
1512     expected_sc<string> ex{};                     // unexpected value
1513     expected_sc<string> ey = {};                  // unexpected value
1514     expected_sc<string> ez = expected_sc<string>{};  // unexpected value
1515   }
1516 
1517   {
1518     stde::expected<Guard, int> eg;                        // unexpected value
1519     stde::expected<Guard, int> eh{};                      // unexpected value
1520     stde::expected<Guard, int> ei{ stde::in_place };               // calls Guard{} in place
1521     stde::expected<Guard, int> ej{ stde::in_place, "arg" };        // calls Guard{"arg"} in place
1522   }
1523 
1524   {
1525     stde::expected<int, string> ei{ unexpect };               // unexpected value, calls string{} in place
1526     stde::expected<int, string> ej{ unexpect, "arg" };        // unexpected value, calls string{"arg"} in place
1527   }
1528 }
1529 void proposal_make_unexpected_fact()
1530 {
1531   using namespace std;
1532   {
1533     stde::expected<string, int> opt1 = stde::make_unexpected(1);
1534     stde::expected<string, int> opt2 = { unexpect, 1 };
1535 
1536     opt1 = stde::make_unexpected(1);
1537     opt2 = { unexpect, 1 };
1538   }
1539 }
1540 void proposal_error_exception_ts()
1541 {
1542   using namespace std;
1543   {
1544     stde::expected<int, error_exception<std::error_code, std::system_error> > e =
1545       stde::make_unexpected(make_error_code(errc::invalid_argument));
1546 #if !defined BOOST_MSVC || BOOST_MSVC >= 1900
1547     BOOST_TEST(e.error() == make_error_code(errc::invalid_argument));
1548 #else
1549     // VS2013 doesn't match operator==(boost::error_exception<std::error_code,std::system_error>, std::error_code)
1550     BOOST_TEST(e.error() == (error_exception<std::error_code, std::system_error>(make_error_code(errc::invalid_argument))));
1551 #endif
1552     try {
1553       e.value();
1554       BOOST_TEST(false);
1555     }
1556     catch (std::system_error const& ex) {
1557 
1558     }
1559     catch (...) {
1560       BOOST_TEST(false);
1561     }
1562     stde::expected<int, error_exception<std::error_code, std::system_error> > e2 = stde::make_unexpected(e.error());
1563 #if !defined BOOST_MSVC || BOOST_MSVC >= 1900
1564     BOOST_TEST(e2.error() == make_error_code(errc::invalid_argument));
1565 #else
1566     // VS2013 doesn't match operator==(boost::error_exception<std::error_code,std::system_error>, std::error_code)
1567     BOOST_TEST(e2.error() == (error_exception<std::error_code, std::system_error>(make_error_code(errc::invalid_argument))));
1568 #endif
1569     try {
1570       e2.value();
1571       BOOST_TEST(false);
1572     }
1573     catch (std::system_error const& ex) {
1574 
1575     }
1576     catch (...) {
1577       BOOST_TEST(false);
1578     }
1579 
1580   }
1581 }
1582 void proposal_ensured_read_ts()
1583 {
1584   using namespace std;
1585   {
1586     ensured_read<int> e = make_ensured_read(1);
1587     BOOST_TEST(e == 1);
1588   }
1589   {
1590     ensured_read<int> e = make_ensured_read(1);
1591     stde::unexpected<ensured_read<int>> ue1 = stde::make_unexpected(std::move(e));
1592     BOOST_TEST(ue1.value() == 1);
1593   }
1594   //  {
1595   //    stde::make_unexpected(make_ensured_read(1));
1596   //    // calls to terminate.
1597   //  }
1598   //  {
1599   //    stde::expected<int, ensured_read<int> > e = stde::make_unexpected(make_ensured_read(1));
1600   //    // calls to terminate.
1601   //  }
1602   {
1603     stde::expected<int, ensured_read<int> > e{ 1 };
1604     BOOST_TEST(e.value() == 1);
1605   }
1606   {
1607     stde::expected<int, ensured_read<int> > e = stde::make_unexpected(make_ensured_read(1));
1608     BOOST_TEST(e.error() == 1);
1609   }
1610   {
1611     stde::expected<int, ensured_read<int> > e{ unexpect, 1 };
1612     BOOST_TEST(e.error() == 1);
1613   }
1614   {
1615     ensured_read<std::exception_ptr> e = make_ensured_read(std::make_exception_ptr(1));
1616     BOOST_TEST_THROWS(std::rethrow_exception(e.value()), int);
1617   }
1618   {
1619     stde::expected<int, ensured_read<std::exception_ptr> > e = stde::make_unexpected(make_ensured_read(std::make_exception_ptr(1)));
1620     BOOST_TEST_THROWS(std::rethrow_exception(e.error().value()), int);
1621   }
1622 }
1623 void proposal_relational_operators()
1624 {
1625   using namespace std;
1626   {
1627     stde::expected<unsigned, int> e0{ 0 };
1628     stde::expected<unsigned, int> e1{ 1 };
1629     stde::expected<unsigned, int> eN{ unexpect, -1 };
1630 
1631     BOOST_TEST(eN < e0);
1632     BOOST_TEST(e0 < e1);
1633     BOOST_TEST(!(e0 < eN));
1634     BOOST_TEST(eN <= e0);
1635     BOOST_TEST(e0 <= e1);
1636 
1637     BOOST_TEST(e0 > eN);
1638     BOOST_TEST(e1 > e0);
1639     BOOST_TEST(e0 >= eN);
1640     BOOST_TEST(e1 >= e0);
1641 
1642     BOOST_TEST(!(eN  < eN));
1643     BOOST_TEST(!(e1 < e1));
1644     BOOST_TEST(eN <= eN);
1645     BOOST_TEST(e1 <= e1);
1646 
1647     BOOST_TEST(eN != e0);
1648     BOOST_TEST(e0 != e1);
1649     BOOST_TEST(eN == eN);
1650     BOOST_TEST(e0 == e0);
1651 
1652     //////
1653 
1654     BOOST_TEST(eN == stde::make_unexpected(-1));
1655     BOOST_TEST(e0 != stde::make_unexpected(1));
1656     BOOST_TEST(eN != 1u);
1657     BOOST_TEST(e1 == 1u);
1658 
1659     BOOST_TEST(eN < 1u);
1660     BOOST_TEST(eN <= 1u);
1661     BOOST_TEST(1u > eN);
1662     BOOST_TEST(!(1u < eN));
1663     BOOST_TEST(1u >= eN);
1664     BOOST_TEST(stde::make_unexpected(1) < e0);
1665     BOOST_TEST(stde::make_unexpected(1) <= e0);
1666     BOOST_TEST(!(stde::make_unexpected(1) > e0));
1667     BOOST_TEST(!(stde::make_unexpected(1) >= e0));
1668 
1669 
1670     BOOST_TEST(!(e0 < stde::make_unexpected(1)));
1671     BOOST_TEST(!(e0 <= stde::make_unexpected(1)));
1672     BOOST_TEST(e0 > stde::make_unexpected(1));
1673     BOOST_TEST(e0 >= stde::make_unexpected(1));
1674   }
1675   {
1676     stde::expected<void, int> e0{ boost::expect };
1677     stde::expected<void, int> eN{ unexpect, -1 };
1678 
1679     BOOST_TEST(!(e0 < e0));
1680     BOOST_TEST(eN < e0);
1681     BOOST_TEST(!(e0 < eN));
1682     BOOST_TEST(!(eN < eN));
1683     BOOST_TEST(e0 <= e0);
1684     BOOST_TEST(eN <= e0);
1685     BOOST_TEST(!(e0 <= eN));
1686     BOOST_TEST(eN <= eN);
1687 
1688     BOOST_TEST(!(e0 > e0));
1689     BOOST_TEST(e0 > eN);
1690     BOOST_TEST(!(eN > e0));
1691     BOOST_TEST(!(eN > eN));
1692     BOOST_TEST(e0 >= e0);
1693     BOOST_TEST(e0 >= eN);
1694     BOOST_TEST(!(eN >= e0));
1695     BOOST_TEST(eN >= eN);
1696 
1697     BOOST_TEST(!(e0 != e0));
1698     BOOST_TEST(eN != e0);
1699     BOOST_TEST(e0 != eN);
1700     BOOST_TEST(!(eN != eN));
1701     BOOST_TEST(e0 == e0);
1702     BOOST_TEST(!(eN == e0));
1703     BOOST_TEST(!(e0 == eN));
1704     BOOST_TEST(eN == eN);
1705 
1706     //////
1707 
1708     BOOST_TEST(eN == stde::make_unexpected(-1));
1709     BOOST_TEST(e0 != stde::make_unexpected(1));
1710 
1711     BOOST_TEST(stde::make_unexpected(1) < e0);
1712     BOOST_TEST(stde::make_unexpected(1) <= e0);
1713     BOOST_TEST(!(stde::make_unexpected(1) > e0));
1714     BOOST_TEST(!(stde::make_unexpected(1) >= e0));
1715 
1716     BOOST_TEST(!(stde::make_unexpected(1) < eN));
1717     BOOST_TEST(!(stde::make_unexpected(1) <= eN));
1718     BOOST_TEST(stde::make_unexpected(1) > eN);
1719     BOOST_TEST(stde::make_unexpected(1) >= eN);
1720 
1721     BOOST_TEST(!(eN < stde::make_unexpected(-1)));
1722     BOOST_TEST(eN <= stde::make_unexpected(-1));
1723     BOOST_TEST(!(eN > stde::make_unexpected(-1)));
1724     BOOST_TEST(eN >= stde::make_unexpected(-1));
1725   }
1726 }
1727 void proposal_dereference_operators()
1728 {
1729   using namespace std;
1730   {
1731     const string s{ "STR" };
1732 
1733     expected_sc<string> e0{ s };
1734     const expected_sc<string> e1{ s };
1735     BOOST_TEST(*e0.operator->() == s);
1736     BOOST_TEST(*e1.operator->() == s);
1737 
1738     // Test with class which has operator&() overloaded
1739     const OverloadedAddressOf o{};
1740     BOOST_TEST(&o == nullptr);
1741 
1742     expected_sc<OverloadedAddressOf> e2{ o };
1743     const expected_sc<OverloadedAddressOf> e3{ o };
1744     BOOST_TEST(e2.operator->() != nullptr);
1745     BOOST_TEST(e3.operator->() != nullptr);
1746   }
1747 }
1748 BOOST_AUTO_TEST_SUITE_END()
1749 
1750 BOOST_AUTO_TEST_SUITE(movesem)
1751 //////////////////////////////
1752 void movesem_moved_from_state()
1753 {
1754   // first, test mock:
1755   MoveAware<int> i{ 1 }, j{ 2 };
1756   BOOST_TEST(i.val == 1);
1757   BOOST_TEST(!i.moved);
1758   BOOST_TEST(j.val == 2);
1759   BOOST_TEST(!j.moved);
1760 
1761   MoveAware<int> k = std::move(i);
1762   BOOST_TEST(k.val == 1);
1763   BOOST_TEST(!k.moved);
1764   BOOST_TEST(i.val == 1);
1765   BOOST_TEST(i.moved);
1766 
1767   k = std::move(j);
1768   BOOST_TEST(k.val == 2);
1769   BOOST_TEST(!k.moved);
1770   BOOST_TEST(j.val == 2);
1771   BOOST_TEST(j.moved);
1772 
1773   // now, test stde::expected
1774   expected_sc<MoveAware<int>> oi{ 1 }, oj{ 2 };
1775   BOOST_TEST(oi);
1776   BOOST_TEST(!oi->moved);
1777   BOOST_TEST(oj);
1778   BOOST_TEST(!oj->moved);
1779 
1780   expected_sc<MoveAware<int>> ok{ std::move(oi) };
1781   BOOST_TEST(ok);
1782   BOOST_TEST(!ok->moved);
1783   BOOST_TEST(oi);
1784   BOOST_TEST(oi->moved);
1785 
1786   ok = std::move(oj);
1787   BOOST_TEST(ok);
1788   BOOST_TEST(!ok->moved);
1789   BOOST_TEST(oj);
1790   BOOST_TEST(oj->moved);
1791 
1792 }
1793 void movesem_move_only_value()
1794 {
1795   const auto make_int = []() {
1796     std::unique_ptr<int> value{ new int };
1797     *value = 100;
1798     return value;
1799   };
1800   const auto return_void = [](std::unique_ptr<int> value) {
1801     BOOST_TEST(value != nullptr);
1802     BOOST_TEST(*value == 100);
1803   };
1804   const auto return_expected = [](std::unique_ptr<int> value) {
1805     BOOST_TEST(value != nullptr);
1806     BOOST_TEST(*value == 100);
1807     return expected_sc<void>{boost::expect};
1808   };
1809   const auto return_int = [](std::unique_ptr<int> value) {
1810     BOOST_TEST(value != nullptr);
1811     BOOST_TEST(*value == 100);
1812     return 200;
1813   };
1814 
1815   BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.map(return_void));
1816   BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.map(return_expected));
1817   BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.map(return_int));
1818 }
1819 void movesem_move_only_value2()
1820 {
1821   const auto make_int = []() {
1822     std::unique_ptr<int> value{ new int };
1823     *value = 100;
1824     return value;
1825   };
1826   const auto return_expected_void = [](std::unique_ptr<int> value) {
1827     BOOST_TEST(value != nullptr);
1828     BOOST_TEST(*value == 100);
1829     return stde::make_expected();
1830   };
1831   const auto return_expected = [](std::unique_ptr<int> value) {
1832     BOOST_TEST(value != nullptr);
1833     BOOST_TEST(*value == 100);
1834     return expected_sc<void>{boost::expect};
1835   };
1836   BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.bind(return_expected_void));
1837   BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.bind(return_expected));
1838 }
1839 void movesem_copy_move_ctor_optional_int()
1840 {
1841   expected_sc<int> oi;
1842   expected_sc<int> oj = oi;
1843 
1844   BOOST_TEST(oj);
1845   BOOST_TEST(oj == oi);
1846   BOOST_TEST(bool(oj));
1847 
1848   oi = 1;
1849   expected_sc<int> ok = oi;
1850   BOOST_TEST(!!ok);
1851   BOOST_TEST(bool(ok));
1852   BOOST_TEST(ok == oi);
1853   BOOST_TEST(ok != oj);
1854   BOOST_TEST(*ok == 1);
1855 
1856   expected_sc<int> ol = std::move(oi);
1857   BOOST_TEST(!!ol);
1858   BOOST_TEST(bool(ol));
1859   BOOST_TEST(ol == oi);
1860   BOOST_TEST(ol != oj);
1861   BOOST_TEST(*ol == 1);
1862 }
1863 void movesem_expected_expected()
1864 {
1865   expected_sc<stde::expected<int, int>> oi1 = stde::make_unexpected(-1);
1866   BOOST_TEST(!oi1);
1867 
1868   {
1869     expected_sc<expected_sc<int>> oi2{ stde::expect };
1870     BOOST_TEST(bool(oi2));
1871     BOOST_TEST((*oi2));
1872     //std::cout << typeid(**oi2).name() << std::endl;
1873   }
1874 
1875   {
1876     expected_sc<stde::expected<int, int>> oi2{ stde::expect, stde::make_unexpected(-1) };
1877     BOOST_TEST(bool(oi2));
1878     BOOST_TEST(!*oi2);
1879   }
1880 
1881   {
1882     stde::expected<stde::expected<int>> oi2{ stde::expected<int>{} };
1883     BOOST_TEST(bool(oi2));
1884     BOOST_TEST(*oi2);
1885   }
1886 
1887   stde::expected<int> oi;
1888   auto ooi = stde::make_expected(oi);
1889   static_assert(std::is_same<expected<expected<int>>, decltype(ooi)>::value, "");
1890 
1891 }
1892 BOOST_AUTO_TEST_SUITE_END()
1893 
1894 void process() {}
1895 void process(int) {}
1896 void processNil() {}
1897 
1898 BOOST_AUTO_TEST_SUITE(Examples)
1899 //////////////////////////////
1900 
1901 void example1()
1902 {
1903   stde::expected<int> oi; // create disengaged object
1904   stde::expected<int> oj = { unexpect }; // alternative syntax
1905   oi = oj; // assign disengaged object
1906   stde::expected<int> ok = oj; // ok is disengaged
1907 
1908   if (oi) BOOST_TEST(false); // 'if oi is engaged...'
1909   if (!oi) BOOST_TEST(true); // 'if oi is disengaged...'
1910 
1911   BOOST_TEST(oi == ok); // two disengaged optionals compare equal
1912 
1913                         ///////////////////////////////////////////////////////////////////////////
1914   stde::expected<int> ol{ 1 }; // ol is engaged; its contained value is 1
1915   ok = 2; // ok becomes engaged; its contained value is 2
1916   oj = ol; // oj becomes engaged; its contained value is 1
1917 
1918   BOOST_TEST(oi != ol); // disengaged != engaged
1919   BOOST_TEST(ok != ol); // different contained values
1920   BOOST_TEST(oj == ol); // same contained value
1921                         //BOOST_TEST(oi < ol); // disengaged < engaged
1922                         //BOOST_TEST(ol < ok); // less by contained value
1923 
1924                         /////////////////////////////////////////////////////////////////////////////
1925   stde::expected<int> om{ 1 }; // om is engaged; its contained value is 1
1926   stde::expected<int> on = om; // on is engaged; its contained value is 1
1927   om = 2; // om is engaged; its contained value is 2
1928   BOOST_TEST(on != om); // on still contains 3. They are not pointers
1929 
1930                         /////////////////////////////////////////////////////////////////////////////
1931   int i = *ol; // i obtains the value contained in ol
1932   BOOST_TEST(i == 1);
1933   *ol = 9; // the object contained in ol becomes 9
1934   BOOST_TEST(*ol == 9);
1935   BOOST_TEST(ol == stde::make_expected(9));
1936 
1937   ///////////////////////////////////
1938   int p = 1;
1939   stde::expected<int> op = p;
1940   BOOST_TEST(*op == 1);
1941   p = 2;
1942   BOOST_TEST(*op == 1); // value contained in op is separated from p
1943 
1944                         ////////////////////////////////
1945   if (ol)
1946     process(*ol); // use contained value if present
1947   else
1948     process(); // proceed without contained value
1949 
1950   if (!om)
1951     processNil();
1952   else
1953     process(*om);
1954 
1955   /////////////////////////////////////////
1956   process(ol.value_or(0)); // use 0 if ol is disengaged
1957 
1958                            ////////////////////////////////////////////
1959   ok = { unexpect }; // if ok was engaged calls T's dtor
1960   oj = {}; // assigns a temporary disengaged stde::expected
1961 }
1962 //////////////////////////////////////////////////
1963 void ValueOr()
1964 {
1965   stde::expected<int> oi = 1;
1966   int i = oi.value_or(0);
1967   BOOST_TEST(i == 1);
1968 
1969   oi = { unexpect };
1970   BOOST_TEST(oi.value_or(3) == 3);
1971 
1972   stde::expected<std::string> os{ "AAA" };
1973   BOOST_TEST(os.value_or("BBB") == "AAA");
1974   os = {};
1975   BOOST_TEST(os);
1976   BOOST_TEST(os.value() == "");
1977 
1978   BOOST_TEST(os.value_or(std::string("BBB")) == "");
1979   {
1980     constexpr stde::expected<int> e = 1;
1981     static_assert(e.has_value(), "");
1982     static_assert(*e == 1, "");
1983     static_assert(e.value() == 1, "");
1984   }
1985   {
1986     constexpr std::error_code ec = std::make_error_code(std::errc(1));
1987     constexpr stde::expected<int> e = stde::make_unexpected(ec);
1988     static_assert(!e.has_value(), "");
1989     static_assert(e.error() == ec, "");
1990   }
1991   {
1992     constexpr stde::expected<OracleVal> e = 1;
1993     static_assert(e.has_value(), "");
1994     static_assert(*e == 1, "");
1995     static_assert(e.value() == 1, "");
1996   }
1997   {
1998     constexpr std::error_code ec = std::make_error_code(std::errc(1));
1999     constexpr stde::expected<OracleVal> e = stde::make_unexpected(ec);
2000     static_assert(!e.has_value(), "");
2001     static_assert(e.error() == ec, "");
2002   }
2003 }
2004 
2005 //////////////////////////////////////////////////
2006 BOOST_AUTO_TEST_SUITE_END()
2007 
2008 #endif
2009 
2010 #else
main(void)2011 int main(void)
2012 {
2013   return 0;
2014 }
2015 #endif
2016