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