summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/outcome/test/expected-pass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/outcome/test/expected-pass.cpp')
-rw-r--r--src/boost/libs/outcome/test/expected-pass.cpp2015
1 files changed, 2015 insertions, 0 deletions
diff --git a/src/boost/libs/outcome/test/expected-pass.cpp b/src/boost/libs/outcome/test/expected-pass.cpp
new file mode 100644
index 000000000..5c63b9118
--- /dev/null
+++ b/src/boost/libs/outcome/test/expected-pass.cpp
@@ -0,0 +1,2015 @@
+//! \file test_expected.cpp
+
+// Copyright Pierre Talbot 2013.
+// Copyright Vicente J. Botet Escriba 2013,2014.
+
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0.
+//(See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+// Notes by ned:
+// Original is at https://github.com/viboes/std-make/blob/master/test/expected/expected_pass.cpp
+// This edition modified to use result with throw_bad_result_access policy
+// Quite a lot of the test suite I had to disable, not because our Expected implementation is
+// incorrect, but because the reference test suite is testing an Expected quite far away from
+// the latest WG21 proposal paper, and we're implementing that latest edition.
+
+#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 7
+
+#include <utility>
+
+#include <boost/outcome/iostream_support.hpp>
+#include <boost/outcome/std_result.hpp>
+
+#define QUICKCPPLIB_BOOST_UNIT_TEST_CUSTOM_MAIN_DEFINED
+#include <boost/test/unit_test.hpp>
+#include <boost/test/unit_test_monitor.hpp>
+
+#define JASEL_NORETURN
+#ifndef BOOST_TEST
+#define BOOST_TEST(expr) BOOST_CHECK(expr)
+#endif
+#ifndef BOOST_TEST_EQ
+#define BOOST_TEST_EQ(a, b) BOOST_CHECK_EQUAL((a), (b))
+#endif
+#ifndef BOOST_TEST_THROWS
+#define BOOST_TEST_THROWS(expr, ex) BOOST_CHECK_THROW((expr), ex)
+#endif
+#ifndef BOOST_CONSTEXPR
+#define BOOST_CONSTEXPR constexpr
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4244) // conversion from int to short
+#endif
+
+namespace stde
+{
+#if __cplusplus >= 201700 || _HAS_CXX17
+ using in_place_t = std::in_place_t;
+ using std::in_place;
+#else
+ struct in_place_t
+ {
+ explicit in_place_t() = default;
+ };
+ constexpr in_place_t in_place{};
+#endif
+
+ //! [expected_implementation]
+ /* Here is a fairly conforming implementation of P0323R3 `expected<T, E>` using `checked<T, E>`.
+ It passes the reference test suite for P0323R3 at
+ https://github.com/viboes/std-make/blob/master/test/expected/expected_pass.cpp with modifications
+ only to move the test much closer to the P0323R3 Expected, as the reference test suite is for a
+ much older proposed Expected.
+
+ Known differences from P0323R3 in this implementation:
+ - `T` and `E` cannot be the same type.
+ - No variant storage is implemented.
+ */
+
+ namespace detail
+ {
+ template <class T, class E> using expected_result = BOOST_OUTCOME_V2_NAMESPACE::checked<T, E>;
+ template <class T, class E> struct enable_default_constructor : public expected_result<T, E>
+ {
+ using base = expected_result<T, E>;
+ using base::base;
+ constexpr enable_default_constructor()
+ : base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>}
+ {
+ }
+ };
+ 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>>;
+ } // namespace detail
+ template <class T, class E> class expected : public detail::select_expected_base<T, E>
+ {
+ static_assert(!std::is_same<T, E>::value, "T and E cannot be the same in this expected implementation");
+ using base = detail::select_expected_base<T, E>;
+
+ public:
+ // Inherit base's constructors
+ using base::base;
+ expected() = default;
+
+ // Expected takes in_place not in_place_type
+ template <class... Args>
+ constexpr explicit expected(in_place_t /*unused*/, Args &&... args)
+ : base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>, std::forward<Args>(args)...}
+ {
+ }
+
+ // Expected always accepts a T even if ambiguous
+ BOOST_OUTCOME_TEMPLATE(class U)
+ BOOST_OUTCOME_TREQUIRES(BOOST_OUTCOME_TPRED(std::is_constructible<T, U>::value))
+ constexpr expected(U &&v) // NOLINT
+ : base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>, std::forward<U>(v)}
+ {
+ }
+
+ // Expected has an emplace() modifier
+ template <class... Args> void emplace(Args &&... args) { *static_cast<base *>(this) = base{BOOST_OUTCOME_V2_NAMESPACE::in_place_type<T>, std::forward<Args>(args)...}; }
+
+ // Expected has a narrow operator* and operator->
+ constexpr const T &operator*() const & { return base::assume_value(); }
+ constexpr T &operator*() & { return base::assume_value(); }
+ constexpr const T &&operator*() const && { return base::assume_value(); }
+ constexpr T &&operator*() && { return base::assume_value(); }
+ constexpr const T *operator->() const { return &base::assume_value(); }
+ constexpr T *operator->() { return &base::assume_value(); }
+
+ // Expected has a narrow error() observer
+ constexpr const E &error() const & { return base::assume_error(); }
+ constexpr E &error() & { return base::assume_error(); }
+ constexpr const E &&error() const && { return base::assume_error(); }
+ constexpr E &error() && { return base::assume_error(); }
+ };
+ 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>>
+ {
+ using base = BOOST_OUTCOME_V2_NAMESPACE::result<void, E, BOOST_OUTCOME_V2_NAMESPACE::policy::throw_bad_result_access<E, void>>;
+
+ public:
+ // Inherit base constructors
+ using base::base;
+
+ // Expected has a narrow operator* and operator->
+ constexpr void operator*() const { base::assume_value(); }
+ constexpr void operator->() const { base::assume_value(); }
+ };
+ template <class E> using unexpected = BOOST_OUTCOME_V2_NAMESPACE::failure_type<E>;
+ template <class E> unexpected<E> make_unexpected(E &&arg) { return BOOST_OUTCOME_V2_NAMESPACE::failure<E>(std::forward<E>(arg)); }
+ template <class E, class... Args> unexpected<E> make_unexpected(Args &&... args) { return BOOST_OUTCOME_V2_NAMESPACE::failure<E>(std::forward<Args>(args)...); }
+ template <class E> using bad_expected_access = BOOST_OUTCOME_V2_NAMESPACE::bad_result_access_with<E>;
+ //! [expected_implementation]
+
+ // Not actually part of the Expected proposal, but needed to pass the test
+ template <typename T> using exception_or = expected<T, std::exception_ptr>;
+} // namespace stde
+
+template <class T> using expected_sc = stde::expected<T, std::error_code>;
+
+struct NoDefaultConstructible
+{
+ NoDefaultConstructible() = delete;
+ NoDefaultConstructible(int /*unused*/) {} // NOLINT
+};
+
+struct NoCopyConstructible
+{
+ NoCopyConstructible() = default;
+ NoCopyConstructible(NoCopyConstructible const &) = delete;
+ NoCopyConstructible(NoCopyConstructible &&) noexcept = default;
+};
+struct NoMoveConstructible
+{
+ NoMoveConstructible() = default;
+ NoMoveConstructible(NoMoveConstructible const &) noexcept = default;
+ NoMoveConstructible(NoMoveConstructible &&) = delete;
+ NoMoveConstructible &operator=(NoMoveConstructible const &) noexcept = default;
+ NoMoveConstructible &operator=(NoMoveConstructible &&) = delete;
+};
+
+enum State
+{
+ sDefaultConstructed,
+ sValueCopyConstructed,
+ sValueMoveConstructed,
+ sCopyConstructed,
+ sMoveConstructed,
+ sMoveAssigned,
+ sCopyAssigned,
+ sValueCopyAssigned,
+ sValueMoveAssigned,
+ sMovedFrom,
+ sValueConstructed
+};
+
+struct OracleVal
+{
+ State s{sValueConstructed};
+ int i;
+ constexpr OracleVal(int i_ = 0) // NOLINT
+ : i(i_)
+ {
+ }
+};
+
+struct Oracle
+{
+ State s{sDefaultConstructed};
+ OracleVal val;
+
+ Oracle() = default;
+ Oracle(const OracleVal &v) // NOLINT
+ : s(sValueCopyConstructed),
+ val(v)
+ {
+ }
+ Oracle(OracleVal &&v) noexcept : s(sValueMoveConstructed), val(v) { v.s = sMovedFrom; } // NOLINT
+ Oracle(const Oracle &o)
+ : s(sCopyConstructed)
+ , val(o.val)
+ {
+ }
+ Oracle(Oracle &&o) noexcept : s(sMoveConstructed), val(std::move(o.val)) { o.s = sMovedFrom; } // NOLINT
+
+ Oracle &operator=(const OracleVal &v)
+ {
+ s = sValueCopyConstructed;
+ val = v;
+ return *this;
+ }
+ Oracle &operator=(OracleVal &&v) noexcept
+ {
+ s = sValueMoveConstructed;
+ val = std::move(v); // NOLINT
+ v.s = sMovedFrom;
+ return *this;
+ }
+ Oracle &operator=(const Oracle &o)
+ {
+ s = sCopyConstructed;
+ val = o.val;
+ return *this;
+ }
+ Oracle &operator=(Oracle &&o) noexcept
+ {
+ s = sMoveConstructed;
+ val = std::move(o.val); // NOLINT
+ o.s = sMovedFrom;
+ return *this;
+ }
+};
+
+struct Guard
+{
+ std::string val;
+ Guard() = default;
+ explicit Guard(std::string s, int /*unused*/ = 0)
+ : val(std::move(s))
+ {
+ }
+ Guard(const Guard &) = delete;
+ Guard(Guard &&) = delete;
+ void operator=(const Guard &) = delete;
+ void operator=(Guard &&) = delete;
+};
+
+struct ExplicitStr
+{
+ std::string s;
+ explicit ExplicitStr(const char *chp)
+ : s(chp)
+ {
+ }
+};
+
+struct Date
+{
+ int i;
+ Date() = delete;
+ Date(int i_) noexcept : i{i_} {} // NOLINT
+ Date(Date &&d) noexcept : i(d.i) { d.i = 0; }
+ Date(const Date &) = delete;
+ Date &operator=(const Date &) = delete;
+ Date &operator=(Date &&d) noexcept
+ {
+ i = d.i;
+ d.i = 0;
+ return *this;
+ }
+};
+
+struct TExcept
+{
+ int i;
+ TExcept() = delete;
+ TExcept(int i_) // NOLINT
+ : i{i_}
+ {
+ }
+ TExcept(TExcept &&d)
+ : i(d.i)
+ {
+ d.i = 0;
+ }
+ TExcept(const TExcept &) = delete;
+ TExcept &operator=(const TExcept &) = delete;
+ TExcept &operator=(TExcept &&d)
+ {
+ i = d.i;
+ d.i = 0;
+ return *this;
+ }
+};
+
+template <class T> struct MoveAware
+{
+ T val;
+ bool moved;
+ MoveAware(T val_) // NOLINT
+ : val(val_),
+ moved(false)
+ {
+ }
+ MoveAware(MoveAware const &) = delete;
+ MoveAware(MoveAware &&rhs)
+ : val(rhs.val)
+ , moved(rhs.moved)
+ {
+ rhs.moved = true;
+ }
+ MoveAware &operator=(MoveAware const &) = delete;
+ MoveAware &operator=(MoveAware &&rhs)
+ {
+ val = (rhs.val);
+ moved = (rhs.moved);
+ rhs.moved = true;
+ return *this;
+ }
+};
+
+struct OverloadedAddressOf
+{
+ OverloadedAddressOf() = default;
+ OverloadedAddressOf *operator&() const { return nullptr; }
+};
+
+// using namespace boost;
+// using namespace boost::functional;
+
+class test_exception : public std::exception
+{
+};
+
+int throwing_fun()
+{
+ throw test_exception();
+}
+int nothrowing_fun()
+{
+ return 4;
+}
+
+JASEL_NORETURN void void_throwing_fun()
+{
+ throw test_exception();
+}
+void do_nothing_fun()
+{
+}
+
+void except_default_constructor()
+{
+ // From value constructor.
+ expected_sc<int> e{};
+ try
+ {
+ int i = e.value();
+ (void) i;
+ BOOST_TEST(true);
+ }
+ catch(...)
+ {
+ BOOST_TEST(false);
+ };
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(e);
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+
+void except_default_constructor_error_code()
+{
+ // From value constructor.
+ stde::expected<int, std::error_code> e;
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(e);
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void except_default_constructor_constexpr()
+{
+ // From value constructor.
+ BOOST_CONSTEXPR stde::expected<int, long> e;
+ BOOST_TEST(e.has_value());
+}
+
+void expected_from_value()
+{
+ // using T = int;
+ using E = std::error_code;
+
+ // static_assert(noexcept(stde::adl::swap_impl(std::declval<T &>(), std::declval<T &>())), "");
+ static_assert(std::is_nothrow_copy_constructible<E>::value, "");
+ // static_assert(noexcept(stde::adl::swap_impl(std::declval<E &>(), std::declval<E &>())), "");
+
+ static_assert(std::is_nothrow_copy_constructible<expected_sc<int>>::value, "");
+ static_assert(std::is_nothrow_copy_assignable<expected_sc<int>>::value, "");
+ static_assert(std::is_nothrow_move_constructible<expected_sc<int>>::value, "");
+ static_assert(std::is_nothrow_move_assignable<expected_sc<int>>::value, "");
+
+ // From value constructor.
+ expected_sc<int> e(5);
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), 5);
+ BOOST_TEST_EQ(*e, 5);
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void expected_from_value2()
+{
+ // From value constructor.
+ expected_sc<int> e(5);
+ e = {};
+ BOOST_TEST(e.has_value());
+ BOOST_TEST_EQ(e.value(), 0);
+}
+
+void expected_from_cnv_value()
+{
+ OracleVal v;
+ expected_sc<Oracle> e(v);
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST(!!e);
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(bool(e));
+ BOOST_TEST_EQ(e.value().s, sValueCopyConstructed);
+ BOOST_TEST_EQ(v.s, sValueConstructed);
+
+ expected_sc<Oracle> e2(std::move(v)); // NOLINT
+ // BOOST_REQUIRE_NO_THROW(e2.value());
+ BOOST_TEST(!!e2);
+ BOOST_TEST(e2.has_value());
+ BOOST_TEST(bool(e2));
+ BOOST_TEST_EQ(e2.value().s, sValueMoveConstructed);
+ BOOST_TEST_EQ(v.s, sMovedFrom);
+}
+
+struct NDCE // no default constructor
+{ // (no default date exists)
+ explicit NDCE(int /*unused*/) {}
+};
+
+void except_constructor_NDCE()
+{
+ expected_sc<NDCE> e{NDCE{1}};
+ BOOST_TEST(e.has_value());
+}
+struct NDC // no default constructor
+{ // (no default date exists)
+ NDC(int /*unused*/) {} // NOLINT
+};
+
+void except_constructor_NDC()
+{
+ static_assert(std::is_nothrow_copy_constructible<expected_sc<NDC>>::value, "");
+ static_assert(std::is_nothrow_copy_assignable<expected_sc<NDC>>::value, "");
+ static_assert(std::is_nothrow_move_constructible<expected_sc<NDC>>::value, "");
+ static_assert(std::is_nothrow_move_assignable<expected_sc<NDC>>::value, "");
+ expected_sc<NDC> e{1};
+ BOOST_TEST(e.has_value());
+}
+
+void except_constructor_Date()
+{
+ static_assert(std::is_nothrow_move_constructible<expected_sc<Date>>::value, "");
+ static_assert(std::is_nothrow_move_assignable<expected_sc<Date>>::value, "");
+ expected_sc<Date> e{Date{1}};
+ BOOST_TEST(e.has_value());
+}
+
+void except_constructor_TExcept()
+{
+ static_assert(!std::is_nothrow_move_constructible<expected_sc<TExcept>>::value, "");
+ static_assert(!std::is_nothrow_move_assignable<expected_sc<TExcept>>::value, "");
+ expected_sc<TExcept> e{TExcept{1}};
+ BOOST_TEST(e.has_value());
+}
+
+void expected_from_in_place_value()
+{
+ OracleVal v;
+ expected_sc<Oracle> e{stde::in_place, v};
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST(!!e);
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(bool(e));
+ BOOST_TEST_EQ(e.value().s, sValueCopyConstructed);
+ BOOST_TEST_EQ(v.s, sValueConstructed);
+
+ expected_sc<Oracle> e2{stde::in_place, std::move(v)}; // NOLINT
+ // BOOST_REQUIRE_NO_THROW(e2.value());
+ BOOST_TEST(!!e2);
+ BOOST_TEST(e2.has_value());
+ BOOST_TEST(bool(e2));
+ BOOST_TEST_EQ(e2.value().s, sValueMoveConstructed);
+ BOOST_TEST_EQ(v.s, sMovedFrom);
+}
+
+#if 0
+void expected_from_exception()
+{
+ // From stde::unexpected constructor.
+ stde::exception_or<int> e(stde::make_unexpected(test_exception()));
+ BOOST_TEST_THROWS(e.value(), test_exception);
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+#endif
+
+void expected_from_copy_value()
+{
+ // From copy constructor.
+ expected_sc<int> ef(5);
+ expected_sc<int> e(ef);
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), 5);
+ BOOST_TEST_EQ(*e, 5);
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+#if 0
+void expected_from_copy_exception()
+{
+ // From stde::unexpected constructor.
+ stde::exception_or<int> ef(stde::make_unexpected(test_exception()));
+ stde::exception_or<int> e(ef);
+ BOOST_TEST_THROWS(e.value(), test_exception);
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+#endif
+
+void expected_from_in_place()
+{
+ // From stde::in_place constructor.
+ expected_sc<std::string> e(stde::in_place, "stde::in_place");
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), "stde::in_place");
+ BOOST_TEST_EQ(*e, "stde::in_place");
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+#if 0
+void expected_from_exception_ptr()
+{
+ // From exception_ptr constructor.
+ stde::exception_or<int> e(stde::make_unexpected(std::make_exception_ptr(test_exception())));
+ BOOST_TEST_THROWS(e.value(), test_exception);
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+#endif
+
+void expected_from_moved_value()
+{
+ // From move value constructor.
+ std::string value = "my value";
+ expected_sc<std::string> e = std::move(value);
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), "my value");
+ BOOST_TEST_EQ(*e, "my value");
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void expected_from_catch_block()
+{
+ // From catch block
+ try
+ {
+ throw test_exception();
+ }
+ catch(...)
+ {
+ stde::exception_or<int> e(stde::make_unexpected(std::current_exception()));
+
+ BOOST_TEST_THROWS(e.value(), std::exception);
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+ }
+}
+
+
+void make_expected_E_from_value()
+{
+ // auto e = stde::make_expected<std::string>( 5 );
+ // BOOST_TEST_EQ(e.has_value(), false);
+}
+void make_expected_const_from_value()
+{
+#if defined __clang__ && __clang_major__ >= 4 && __cplusplus > 201402L
+ const int i = 0;
+ auto e = expected_sc<const int>(i);
+ (void) e;
+// static_assert(std::is_same<decltype(e), stde::success<const int>>::value, "");
+#endif
+}
+void make_expected_from_U_value()
+{
+ expected_sc<int> e = expected_sc<int>(short(5));
+ static_assert(std::is_same<decltype(e), expected_sc<int>>{}, "");
+ BOOST_TEST_EQ(e.has_value(), true);
+}
+void make_expected_from_U_value2()
+{
+ expected_sc<std::string> e = expected_sc<std::string>("aa");
+ static_assert(std::is_same<decltype(e), expected_sc<std::string>>{}, "");
+ BOOST_TEST_EQ(e.has_value(), true);
+}
+
+void expected_from_value_error_condition()
+{
+ // From value constructor.
+ stde::expected<int, std::error_condition> e(5);
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), 5);
+ BOOST_TEST_EQ(*e, 5);
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void expected_from_error_error_condition()
+{
+ // From stde::unexpected constructor.
+ stde::expected<int, std::error_condition> e(stde::make_unexpected<std::error_condition>(std::make_error_condition(std::errc::invalid_argument)));
+ auto error_from_except_check = [](const stde::bad_expected_access<std::error_condition> &except) { return std::errc(except.error().value()) == std::errc::invalid_argument; };
+ try
+ {
+ (void) e.value();
+ }
+ catch(stde::bad_expected_access<std::error_condition> &ex)
+ {
+ BOOST_TEST(error_from_except_check(ex));
+ }
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+
+
+void expected_from_error_convertible()
+{
+ {
+ stde::expected<int, short> e1 = stde::make_unexpected<short>(1);
+ stde::expected<int, long> e2(e1);
+ BOOST_TEST_EQ(e2.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e2), false);
+ BOOST_TEST_EQ(e2.error(), 1);
+ }
+ {
+ stde::expected<void, short> e1 = stde::make_unexpected<short>(1);
+ stde::expected<void, int> e2(e1);
+ BOOST_TEST_EQ(e2.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e2), false);
+ BOOST_TEST_EQ(e2.error(), 1);
+ }
+}
+
+void except_valid_constexpr_int()
+{
+ // From value constructor.
+ BOOST_CONSTEXPR stde::expected<int, long> e;
+ BOOST_CONSTEXPR bool b = e.has_value();
+ BOOST_TEST(b);
+}
+void except_value_constexpr_int()
+{
+ // From value constructor.
+ BOOST_CONSTEXPR stde::expected<int, long> e(1);
+ BOOST_CONSTEXPR int x = e.value();
+ BOOST_TEST_EQ(x, 1);
+}
+
+void expected_from_value3()
+{
+ expected_sc<int> e(5);
+ BOOST_TEST_EQ(e.value(), 5);
+
+ // From value assignment.
+ e = 8;
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), 8);
+ BOOST_TEST_EQ(*e, 8);
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void expected_from_copy_expected()
+{
+ expected_sc<int> e(5);
+ expected_sc<int> e2(8);
+
+ // From value assignment.
+ e = e2;
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), 8);
+ BOOST_TEST_EQ(*e, 8);
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void expected_from_moved_expected()
+{
+ expected_sc<std::string> e("e");
+ expected_sc<std::string> e2("e2");
+
+ // From value assignment.
+ e = std::move(e2);
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), "e2");
+ BOOST_TEST_EQ(*e, "e2");
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+
+// BOOST_REQUIRE_NO_THROW(e2.value());
+#ifndef __GLIBBOOST_OUTCOME_C__
+ BOOST_TEST_EQ(e2.value(), "");
+ BOOST_TEST_EQ(*e2, "");
+#endif
+ BOOST_TEST(e2.has_value());
+ BOOST_TEST(static_cast<bool>(e2));
+}
+
+void expected_from_in_place2()
+{
+ // From stde::in_place constructor.
+ expected_sc<std::string> e(stde::in_place, "stde::in_place");
+ BOOST_TEST_EQ(e.value(), "stde::in_place");
+
+ // From emplace method.
+ e.emplace("emplace method");
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), "emplace method");
+ BOOST_TEST_EQ(*e, "emplace method");
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void expected_from_move_value()
+{
+ expected_sc<std::string> e("v");
+
+ std::string value = "my value";
+ // From assignment operator.
+ e = std::move(value);
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), "my value");
+ BOOST_TEST_EQ(*e, "my value");
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+
+void expected_from_in_place3()
+{
+ // From stde::in_place factory.
+ // auto e = stde::make_expected<std::string>("stde::in_place");
+ auto e = expected_sc<std::string>("stde::in_place");
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), "stde::in_place");
+ BOOST_TEST_EQ(*e, "stde::in_place");
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+void expected_from_in_place_error()
+{
+ // From stde::in_place factory.
+ auto e = stde::expected<std::string, std::error_condition>("stde::in_place");
+ // BOOST_REQUIRE_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.value(), "stde::in_place");
+ BOOST_TEST_EQ(*e, "stde::in_place");
+ BOOST_TEST(e.has_value());
+ BOOST_TEST(static_cast<bool>(e));
+}
+
+void expected_from_exception_catch()
+{
+ // From catch block
+ try
+ {
+ throw test_exception();
+ }
+ catch(...)
+ {
+ stde::exception_or<int> e = stde::make_unexpected(std::current_exception());
+
+ BOOST_TEST_THROWS(e.value(), std::exception);
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+ }
+}
+
+#if 0
+void expected_from_error()
+{
+ // From stde::unexpected constructor.
+ auto e = stde::make_expected_from_error<int>(std::make_error_condition(std::errc::invalid_argument));
+ auto error_from_except_check = [](const stde::bad_expected_access<std::error_condition> &except) { return std::errc(except.error().value()) == std::errc::invalid_argument; };
+ try
+ {
+ (void) e.value();
+ }
+ catch(stde::bad_expected_access<std::error_condition> &ex)
+ {
+ BOOST_TEST(error_from_except_check(ex));
+ }
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+
+void expected_from_error_U()
+{
+ // From stde::unexpected constructor.
+ auto e = stde::make_expected_from_error<int, short>(42);
+ static_assert(std::is_same<decltype(e), stde::expected<int, short>>{}, "");
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+
+void expected_from_exception2()
+{
+ // From stde::unexpected constructor.
+ auto e = stde::make_expected_from_exception<int>(test_exception());
+ // auto e = expected_sc<int>(stde::unexpected<>(test_exception()));
+ BOOST_TEST_THROWS(e.value(), test_exception );
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+
+void expected_from_exception_ptr2()
+{
+ // From exception_ptr constructor.
+ auto e = stde::exception_or<int>(stde::make_unexpected(test_exception()));
+ BOOST_TEST_THROWS(e.value(), test_exception );
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+}
+
+void make_expected_from_call_fun()
+{
+ try
+ {
+ stde::make_expected_from_call(throwing_fun);
+ BOOST_TEST(true);
+ }
+ catch(...)
+ {
+ BOOST_TEST(false);
+ }
+ stde::exception_or<int> e = stde::make_expected_from_call(throwing_fun);
+ BOOST_TEST_THROWS(e.value(), std::exception );
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+
+ e = stde::make_expected_from_call(nothrowing_fun);
+ try
+ {
+ (void) e.value();
+ BOOST_TEST(true);
+ }
+ catch(...)
+ {
+ BOOST_TEST(false);
+ }
+ BOOST_TEST_EQ(e.value(), 4);
+ BOOST_TEST_EQ(*e, 4);
+ BOOST_TEST_EQ(e.has_value(), true);
+ BOOST_TEST_EQ(static_cast<bool>(e), true);
+
+#if 0
+ BOOST_TEST_THROWS(stde::make_expected_from_call<std::error_condition>(throwing_fun), test_exception);
+
+ BOOST_TEST_NO_THROW(stde::make_expected_from_call<std::error_condition>(nothrowing_fun));
+ stde::expected<int, std::error_condition> e2 = stde::make_expected_from_call<std::error_condition>(nothrowing_fun);
+ BOOST_TEST_NO_THROW(e2.value());
+ BOOST_TEST_EQ(e2.value(), 4);
+ BOOST_TEST_EQ(*e2, 4);
+ BOOST_TEST_EQ(e2.has_value(), true);
+ BOOST_TEST_EQ(static_cast<bool>(e2), true);
+#endif
+}
+
+void make_expected_from_call_void_fun()
+{
+#if 0
+ BOOST_TEST_NO_THROW(stde::make_expected_from_call(void_throwing_fun));
+ expected_sc<void> e = stde::make_expected_from_call(void_throwing_fun);
+ BOOST_TEST_THROWS(e.value(), std::exception);
+ BOOST_TEST_EQ(e.has_value(), false);
+ BOOST_TEST_EQ(static_cast<bool>(e), false);
+
+ e = stde::make_expected_from_call(do_nothing_fun);
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(e.has_value(), true);
+ BOOST_TEST_EQ(static_cast<bool>(e), true);
+
+ BOOST_TEST_THROWS(stde::make_expected_from_call<std::error_condition>(void_throwing_fun), test_exception);
+
+ try {
+ stde::make_expected_from_call<std::error_condition>(do_nothing_fun);
+ BOOST_TEST(true);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ stde::expected<void, std::error_condition> e2 = stde::make_expected_from_call<std::error_condition>(do_nothing_fun);
+ try {
+ (void)e2.value();
+ BOOST_TEST(true);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
+ //BOOST_TEST_NO_THROW(e2.value());
+ BOOST_TEST_EQ(e2.has_value(), true);
+ BOOST_TEST_EQ(static_cast<bool>(e2), true);
+#endif
+}
+#endif
+
+void expected_swap_value()
+{
+ // From value constructor.
+ expected_sc<int> e(5);
+ expected_sc<int> e2(8);
+
+ e.swap(e2);
+
+ BOOST_TEST_EQ(e.value(), 8);
+ BOOST_TEST_EQ(e2.value(), 5);
+
+ e2.swap(e);
+
+ BOOST_TEST_EQ(e.value(), 5);
+ BOOST_TEST_EQ(e2.value(), 8);
+}
+
+#if 0
+void expected_swap_exception()
+{
+ // From value constructor.
+ stde::exception_or<int> e = stde::make_unexpected(std::invalid_argument("e"));
+ stde::exception_or<int> e2 = stde::make_unexpected(std::invalid_argument("e2"));
+
+ e.swap(e2);
+
+ auto equal_to_e = [](const std::invalid_argument &except) { return std::string(except.what()) == "e"; };
+ auto equal_to_e2 = [](const std::invalid_argument &except) { return std::string(except.what()) == "e2"; };
+
+ try
+ {
+ (void) e.value();
+ BOOST_TEST(true);
+ }
+ catch(std::invalid_argument &ex)
+ {
+ BOOST_TEST(equal_to_e2(ex));
+ }
+ try
+ {
+ (void) e2.value();
+ BOOST_TEST(true);
+ }
+ catch(std::invalid_argument &ex)
+ {
+ BOOST_TEST(equal_to_e(ex));
+ }
+
+ e2.swap(e);
+
+ try
+ {
+ (void) e.value();
+ BOOST_TEST(true);
+ }
+ catch(std::invalid_argument &ex)
+ {
+ BOOST_TEST(equal_to_e(ex));
+ }
+ try
+ {
+ (void) e2.value();
+ BOOST_TEST(true);
+ }
+ catch(std::invalid_argument &ex)
+ {
+ BOOST_TEST(equal_to_e2(ex));
+ }
+}
+#endif
+
+void expected_swap_function_value()
+{
+ // From value constructor.
+ expected_sc<int> e(5);
+ expected_sc<int> e2(8);
+
+ swap(e, e2);
+
+ BOOST_TEST_EQ(e.value(), 8);
+ BOOST_TEST_EQ(e2.value(), 5);
+
+ swap(e, e2);
+
+ BOOST_TEST_EQ(e.value(), 5);
+ BOOST_TEST_EQ(e2.value(), 8);
+}
+
+
+#ifdef QUICKCPPLIB_BOOST_UNIT_TEST_HPP
+int main()
+#else
+BOOST_AUTO_TEST_CASE(expected_pass)
+#endif
+{
+
+ static_assert(!std::is_default_constructible<NoDefaultConstructible>::value, "");
+ static_assert(!std::is_default_constructible<expected_sc<NoDefaultConstructible>>::value, "");
+
+ static_assert(!std::is_copy_constructible<NoCopyConstructible>::value, "");
+ static_assert(!std::is_constructible<expected_sc<NoCopyConstructible>, NoCopyConstructible const &>::value, "");
+ static_assert(!std::is_constructible<stde::exception_or<NoCopyConstructible>, stde::exception_or<NoCopyConstructible> const &>::value, "");
+ static_assert(!std::is_copy_constructible<stde::exception_or<NoCopyConstructible>>::value, "");
+
+#if 0
+ // fixme
+ {
+ NoMoveConstructible nmc;
+ // NoMoveConstructible nmc2 = std::move(nmc); // FAILS as expected
+
+ expected_sc<NoMoveConstructible> x{std::move(nmc)}; // DOESN'T FAIL as copy is selected instead
+ (void) x;
+ }
+// fixme
+#if defined __clang__ && __clang_major__ >= 4 && __cplusplus > 201402L
+ {
+ NoMoveConstructible nmc;
+ // NoMoveConstructible nmc2 = std::move(nmc); // FAILS as expected
+
+ expected_sc<NoMoveConstructible> x = std::move(nmc); // DOESN'T FAIL as copy is selected instead
+ (void) x;
+ }
+#endif
+#endif
+
+ static_assert(!std::is_move_constructible<NoMoveConstructible>::value, "");
+ static_assert(!std::is_constructible<expected_sc<NoMoveConstructible>, NoMoveConstructible &&>::value, "");
+ static_assert(std::is_move_constructible<expected_sc<NoMoveConstructible>>::value, "");
+
+ except_default_constructor();
+ except_default_constructor_error_code();
+ except_default_constructor_constexpr();
+ expected_from_value();
+ expected_from_value2();
+ expected_from_cnv_value();
+ except_constructor_NDCE();
+ except_constructor_NDC();
+ except_constructor_Date();
+ expected_from_in_place_value();
+ // expected_from_exception();
+ expected_from_copy_value();
+ // expected_from_copy_exception();
+ expected_from_in_place();
+ // expected_from_exception_ptr();
+ expected_from_moved_value();
+ expected_from_catch_block();
+ make_expected_E_from_value();
+ make_expected_const_from_value();
+ make_expected_from_U_value2();
+ expected_from_value_error_condition();
+ expected_from_error_error_condition();
+ expected_from_error_convertible();
+ except_valid_constexpr_int();
+ except_value_constexpr_int();
+ expected_from_value3();
+ expected_from_copy_expected();
+ expected_from_moved_expected();
+ expected_from_in_place2();
+ expected_from_move_value();
+ expected_from_in_place3();
+ expected_from_in_place_error();
+ expected_from_exception_catch();
+ // expected_from_error();
+ // expected_from_error_U();
+ // expected_from_exception2();
+ // expected_from_exception_ptr2();
+ // make_expected_from_call_fun();
+ // make_expected_from_call_void_fun();
+ expected_swap_value();
+ // expected_swap_exception();
+ expected_swap_function_value();
+
+#ifdef QUICKCPPLIB_BOOST_UNIT_TEST_HPP
+ return QUICKCPPLIB_NAMESPACE::unit_test::current_test_case()->fails != 0;
+#endif
+}
+
+#if 0
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+//void expected_from_error_catch_exception)
+//{
+// // From catch block
+// try
+// {
+// throw test_exception();
+// }
+// catch(...)
+// {
+// auto throw_lambda = [](){ return stde::make_expected_from_error<int,std::error_condition>();};
+//
+// //BOOST_TEST_THROWS(throw_lambda(), test_exception);
+// }
+//}
+
+
+
+////////////////////////////////////
+BOOST_AUTO_TEST_SUITE(expected_map)
+
+void expected_map()
+{
+ auto fun = [](bool b) -> expected_sc<int>
+ {
+ if (b)
+ return stde::make_expected(5);
+ else
+ return stde::make_unexpected(test_exception());
+ };
+
+ auto add_five = [](int sum) -> int
+ {
+ return sum + 5;
+ };
+
+ auto launch_except = [](int sum) -> int
+ {
+ throw test_exception();
+ };
+
+ expected_sc<int> e = fun(true).map(add_five);
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 10);
+
+ e = fun(true).map(add_five).map(add_five);
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 15);
+
+ e = fun(false).map(add_five).map(add_five);
+ BOOST_TEST_THROWS(e.value(), test_exception);
+
+ BOOST_TEST_THROWS(fun(true).map(launch_except), test_exception);
+
+}
+
+void expected_void_map()
+{
+ auto fun = [](bool b)
+ {
+ if (b)
+ return stde::make_expected();
+ else
+ return expected_sc<void>(stde::make_unexpected(test_exception()));
+ };
+
+ auto launch_except = []() -> void
+ {
+ throw test_exception();
+ };
+
+ auto do_nothing = []() {};
+
+ expected_sc<void> e = fun(true).map(do_nothing);
+ BOOST_TEST_NO_THROW(e.value());
+
+ e = fun(false).map(do_nothing);
+ BOOST_TEST_THROWS(e.value(), test_exception);
+
+ BOOST_TEST_THROWS(fun(true).map(launch_except), test_exception);
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+////////////////////////////////////
+BOOST_AUTO_TEST_SUITE(expected_bind)
+
+void expected_bind()
+{
+ auto fun = [](bool b) -> expected_sc<int>
+ {
+ if (b)
+ return stde::make_expected(5);
+ else
+ return stde::make_unexpected(test_exception());
+ };
+
+ auto add_five = [](int sum) -> expected_sc<int>
+ {
+ return stde::make_expected(sum + 5);
+ };
+
+ auto launch_except = [](int sum) -> expected_sc<int>
+ {
+ throw test_exception();
+ };
+
+ expected_sc<int> e = fun(true).bind(add_five);
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 10);
+
+ e = fun(true).bind(add_five).bind(add_five);
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 15);
+
+ e = fun(false).bind(add_five).bind(add_five);
+ BOOST_TEST_THROWS(e.value(), test_exception);
+
+ BOOST_TEST_THROWS(fun(true).bind(launch_except), test_exception);
+
+}
+
+void expected_void_bind()
+{
+ auto fun = [](bool b)
+ {
+ if (b)
+ return stde::make_expected();
+ else
+ return expected_sc<void>(stde::make_unexpected(test_exception()));
+ };
+
+ auto launch_except = []() -> expected_sc<void>
+ {
+ throw test_exception();
+ };
+
+ auto do_nothing = []() {
+ return stde::make_expected();
+ };
+
+ expected_sc<void> e = fun(true).bind(do_nothing);
+ BOOST_TEST_NO_THROW(e.value());
+
+ e = fun(false).bind(do_nothing);
+ BOOST_TEST_THROWS(e.value(), test_exception);
+
+ BOOST_TEST_THROWS(fun(true).bind(launch_except), test_exception);
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+
+////////////////////////////////////
+BOOST_AUTO_TEST_SUITE(expected_then)
+
+void expected_non_void_then()
+{
+ auto fun = [](bool b) -> expected_sc<int>
+ {
+ if (b)
+ return stde::make_expected(5);
+ else
+ return stde::make_unexpected(test_exception());
+ };
+
+
+ auto add_five = [](int sum) -> int
+ {
+ return sum + 5;
+ };
+ auto six = []() -> int
+ {
+ return 6;
+ };
+
+ auto pair = [](int a) -> bool
+ {
+ return (a % 2) == 0;
+ };
+
+ auto launch_except = [](int sum) -> int
+ {
+ throw test_exception();
+ };
+
+ auto then_launch_except = [](expected<int>) -> int
+ {
+ throw test_exception();
+ };
+
+ expected_sc<int> e = fun(true).then(if_valued(add_five));
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 10);
+
+ e = fun(true).then(if_valued(ident(six)));
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 6);
+
+ e = fun(false).then(if_unexpected(ident(six)));
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 6);
+
+ expected_sc<bool> e1 = fun(true).then(if_valued(pair));
+ BOOST_TEST_NO_THROW(e1.value());
+ BOOST_TEST_EQ(*e1, false);
+
+
+
+ e = fun(true).then(if_valued(add_five)).then(if_valued(add_five));
+ BOOST_TEST_NO_THROW(e.value());
+ BOOST_TEST_EQ(*e, 15);
+
+ e = fun(false).then(if_valued(add_five)).then(if_valued(add_five));
+ BOOST_TEST_THROWS(e.value(), test_exception);
+
+ BOOST_TEST_THROWS(fun(true).then(if_valued(launch_except)), test_exception);
+
+ e = fun(false).then(catch_all(then_launch_except));
+ BOOST_TEST_THROWS(e.value(), test_exception);
+
+}
+
+void expected_void_then()
+{
+ auto fun = [](bool b) -> expected_sc<void>
+ {
+ if (b)
+ return stde::make_expected();
+ else
+ return stde::make_unexpected(test_exception());
+ };
+
+ auto launch_except = []()
+ {
+ throw test_exception();
+ };
+
+ auto do_nothing = []() {};
+
+ BOOST_TEST(true);
+ expected_sc<void> e = fun(true).then(if_valued(do_nothing));
+ BOOST_TEST_NO_THROW(e.value());
+
+ e = fun(false).then(if_valued(do_nothing));
+ BOOST_TEST_THROWS(e.value(), test_exception);
+
+ BOOST_TEST_THROWS(fun(true).then(if_valued(launch_except)), test_exception);
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE(expected_recover)
+
+void expected_recover()
+{
+ auto fun = [](bool b)
+ {
+ if (b)
+ return expected_sc<int>(5);
+ else
+ return expected_sc<int>(stde::make_unexpected(test_exception()));
+ };
+
+ auto add_five = [](int sum) -> expected_sc<int>
+ {
+ return stde::make_expected(sum + 5);
+ };
+
+ auto recover_error = [](std::exception_ptr p)
+ {
+ return stde::make_expected(0);
+ };
+
+ auto recover_error_silent_failure = [](std::exception_ptr p)
+ {
+ return expected_sc<int>(stde::make_unexpected(p));
+ };
+
+ auto recover_error_failure = [](std::exception_ptr p) -> expected_sc<int>
+ {
+ return expected_sc<int>(stde::make_unexpected(test_exception()));
+ };
+
+ auto recover_error_throws = [](std::exception_ptr p) -> expected_sc<int>
+ {
+ throw test_exception();
+ };
+
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error).has_value(), true);
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error).value(), 0);
+ BOOST_TEST_EQ(fun(true).catch_error(recover_error).value(), 5);
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error_silent_failure).has_value(), false);
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error_failure).has_value(), false);
+
+ BOOST_TEST_EQ(fun(true).bind(add_five).value(), 10);
+ BOOST_TEST_EQ(fun(true).bind(add_five).catch_error(recover_error).value(), 10);
+ BOOST_TEST_EQ(fun(true).bind(add_five).catch_error(recover_error_silent_failure).value(), 10);
+ BOOST_TEST_EQ(fun(true).bind(add_five).catch_error(recover_error_failure).value(), 10);
+
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error).bind(add_five).value(), 5);
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error).bind(add_five).bind(add_five).value(), 10);
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error_failure).bind(add_five).has_value(), false);
+ BOOST_TEST_EQ(fun(false).bind(add_five).catch_error(recover_error_failure).bind(add_five).has_value(), false);
+ BOOST_TEST_EQ(fun(false).bind(add_five).catch_error(recover_error_silent_failure).bind(add_five).has_value(), false);
+
+ BOOST_TEST_THROWS(fun(false).catch_error(recover_error_throws), test_exception);
+
+}
+
+void expected_void_recover()
+{
+ auto fun = [](bool b)
+ {
+ if (b)
+ return stde::make_expected();
+ else
+ return expected_sc<void>(boost::stde::make_unexpected(test_exception()));
+ };
+
+ auto do_nothing = []() {
+ return stde::make_expected();
+ };
+
+ auto recover_error = [](std::exception_ptr p)
+ {
+ return stde::make_expected();
+ };
+
+ auto recover_error_silent_failure = [](std::exception_ptr p)
+ {
+ return expected_sc<void>(boost::stde::make_unexpected(p));
+ };
+
+ auto recover_error_failure = [](std::exception_ptr p) -> expected_sc<void>
+ {
+ throw test_exception();
+ };
+
+ // The catch_error doesn't alter the stde::expected if it's valid.
+ BOOST_TEST_EQ(fun(true).catch_error(recover_error_failure).has_value(), true);
+
+ // Simple catch_error tests.
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error).has_value(), true);
+ BOOST_TEST_THROWS(fun(false).catch_error(recover_error_failure), test_exception);
+ BOOST_TEST_EQ(fun(false).catch_error(recover_error_silent_failure).has_value(), false);
+
+ // With a bind between.
+ BOOST_TEST_THROWS(fun(false).bind(do_nothing).catch_error(recover_error_failure), test_exception);
+
+}
+BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE(proposal)
+
+void proposal_concept()
+{
+ using namespace std;
+
+ {
+ stde::expected<int, string> ei = 0;
+ stde::expected<int, string> ej = 1;
+ stde::expected<int, string> ek = stde::make_unexpected(string());
+
+ ei = 1;
+ ej = stde::make_unexpected(string());;
+ ek = 0;
+
+ ei = stde::make_unexpected(string());;
+ ej = 0;
+ ek = 1;
+ }
+}
+void proposal_init()
+{
+ using namespace std;
+ {
+ string s{ "STR" };
+
+ stde::expected<string, int> ep{ stde::make_unexpected(-1) }; // unexpected value, requires Movable<E>
+ stde::expected<string, int> eq = { stde::make_unexpected(-1) }; // unexpected value, requires Movable<E>
+
+ expected_sc<string> es{ s }; // requires Copyable<T>
+ expected_sc<string> et = s; // requires Copyable<T>
+ expected_sc<string> ev = string{ "STR" }; // requires Movable<T>
+
+ expected_sc<string> ew; // unexpected value
+ expected_sc<string> ex{}; // unexpected value
+ expected_sc<string> ey = {}; // unexpected value
+ expected_sc<string> ez = expected_sc<string>{}; // unexpected value
+ }
+
+ {
+ stde::expected<Guard, int> eg; // unexpected value
+ stde::expected<Guard, int> eh{}; // unexpected value
+ stde::expected<Guard, int> ei{ stde::in_place }; // calls Guard{} in place
+ stde::expected<Guard, int> ej{ stde::in_place, "arg" }; // calls Guard{"arg"} in place
+ }
+
+ {
+ stde::expected<int, string> ei{ unexpect }; // unexpected value, calls string{} in place
+ stde::expected<int, string> ej{ unexpect, "arg" }; // unexpected value, calls string{"arg"} in place
+ }
+}
+void proposal_make_unexpected_fact()
+{
+ using namespace std;
+ {
+ stde::expected<string, int> opt1 = stde::make_unexpected(1);
+ stde::expected<string, int> opt2 = { unexpect, 1 };
+
+ opt1 = stde::make_unexpected(1);
+ opt2 = { unexpect, 1 };
+ }
+}
+void proposal_error_exception_ts()
+{
+ using namespace std;
+ {
+ stde::expected<int, error_exception<std::error_code, std::system_error> > e =
+ stde::make_unexpected(make_error_code(errc::invalid_argument));
+#if !defined BOOST_MSVC || BOOST_MSVC >= 1900
+ BOOST_TEST(e.error() == make_error_code(errc::invalid_argument));
+#else
+ // VS2013 doesn't match operator==(boost::error_exception<std::error_code,std::system_error>, std::error_code)
+ BOOST_TEST(e.error() == (error_exception<std::error_code, std::system_error>(make_error_code(errc::invalid_argument))));
+#endif
+ try {
+ e.value();
+ BOOST_TEST(false);
+ }
+ catch (std::system_error const& ex) {
+
+ }
+ catch (...) {
+ BOOST_TEST(false);
+ }
+ stde::expected<int, error_exception<std::error_code, std::system_error> > e2 = stde::make_unexpected(e.error());
+#if !defined BOOST_MSVC || BOOST_MSVC >= 1900
+ BOOST_TEST(e2.error() == make_error_code(errc::invalid_argument));
+#else
+ // VS2013 doesn't match operator==(boost::error_exception<std::error_code,std::system_error>, std::error_code)
+ BOOST_TEST(e2.error() == (error_exception<std::error_code, std::system_error>(make_error_code(errc::invalid_argument))));
+#endif
+ try {
+ e2.value();
+ BOOST_TEST(false);
+ }
+ catch (std::system_error const& ex) {
+
+ }
+ catch (...) {
+ BOOST_TEST(false);
+ }
+
+ }
+}
+void proposal_ensured_read_ts()
+{
+ using namespace std;
+ {
+ ensured_read<int> e = make_ensured_read(1);
+ BOOST_TEST(e == 1);
+ }
+ {
+ ensured_read<int> e = make_ensured_read(1);
+ stde::unexpected<ensured_read<int>> ue1 = stde::make_unexpected(std::move(e));
+ BOOST_TEST(ue1.value() == 1);
+ }
+ // {
+ // stde::make_unexpected(make_ensured_read(1));
+ // // calls to terminate.
+ // }
+ // {
+ // stde::expected<int, ensured_read<int> > e = stde::make_unexpected(make_ensured_read(1));
+ // // calls to terminate.
+ // }
+ {
+ stde::expected<int, ensured_read<int> > e{ 1 };
+ BOOST_TEST(e.value() == 1);
+ }
+ {
+ stde::expected<int, ensured_read<int> > e = stde::make_unexpected(make_ensured_read(1));
+ BOOST_TEST(e.error() == 1);
+ }
+ {
+ stde::expected<int, ensured_read<int> > e{ unexpect, 1 };
+ BOOST_TEST(e.error() == 1);
+ }
+ {
+ ensured_read<std::exception_ptr> e = make_ensured_read(std::make_exception_ptr(1));
+ BOOST_TEST_THROWS(std::rethrow_exception(e.value()), int);
+ }
+ {
+ stde::expected<int, ensured_read<std::exception_ptr> > e = stde::make_unexpected(make_ensured_read(std::make_exception_ptr(1)));
+ BOOST_TEST_THROWS(std::rethrow_exception(e.error().value()), int);
+ }
+}
+void proposal_relational_operators()
+{
+ using namespace std;
+ {
+ stde::expected<unsigned, int> e0{ 0 };
+ stde::expected<unsigned, int> e1{ 1 };
+ stde::expected<unsigned, int> eN{ unexpect, -1 };
+
+ BOOST_TEST(eN < e0);
+ BOOST_TEST(e0 < e1);
+ BOOST_TEST(!(e0 < eN));
+ BOOST_TEST(eN <= e0);
+ BOOST_TEST(e0 <= e1);
+
+ BOOST_TEST(e0 > eN);
+ BOOST_TEST(e1 > e0);
+ BOOST_TEST(e0 >= eN);
+ BOOST_TEST(e1 >= e0);
+
+ BOOST_TEST(!(eN < eN));
+ BOOST_TEST(!(e1 < e1));
+ BOOST_TEST(eN <= eN);
+ BOOST_TEST(e1 <= e1);
+
+ BOOST_TEST(eN != e0);
+ BOOST_TEST(e0 != e1);
+ BOOST_TEST(eN == eN);
+ BOOST_TEST(e0 == e0);
+
+ //////
+
+ BOOST_TEST(eN == stde::make_unexpected(-1));
+ BOOST_TEST(e0 != stde::make_unexpected(1));
+ BOOST_TEST(eN != 1u);
+ BOOST_TEST(e1 == 1u);
+
+ BOOST_TEST(eN < 1u);
+ BOOST_TEST(eN <= 1u);
+ BOOST_TEST(1u > eN);
+ BOOST_TEST(!(1u < eN));
+ BOOST_TEST(1u >= eN);
+ BOOST_TEST(stde::make_unexpected(1) < e0);
+ BOOST_TEST(stde::make_unexpected(1) <= e0);
+ BOOST_TEST(!(stde::make_unexpected(1) > e0));
+ BOOST_TEST(!(stde::make_unexpected(1) >= e0));
+
+
+ BOOST_TEST(!(e0 < stde::make_unexpected(1)));
+ BOOST_TEST(!(e0 <= stde::make_unexpected(1)));
+ BOOST_TEST(e0 > stde::make_unexpected(1));
+ BOOST_TEST(e0 >= stde::make_unexpected(1));
+ }
+ {
+ stde::expected<void, int> e0{ boost::expect };
+ stde::expected<void, int> eN{ unexpect, -1 };
+
+ BOOST_TEST(!(e0 < e0));
+ BOOST_TEST(eN < e0);
+ BOOST_TEST(!(e0 < eN));
+ BOOST_TEST(!(eN < eN));
+ BOOST_TEST(e0 <= e0);
+ BOOST_TEST(eN <= e0);
+ BOOST_TEST(!(e0 <= eN));
+ BOOST_TEST(eN <= eN);
+
+ BOOST_TEST(!(e0 > e0));
+ BOOST_TEST(e0 > eN);
+ BOOST_TEST(!(eN > e0));
+ BOOST_TEST(!(eN > eN));
+ BOOST_TEST(e0 >= e0);
+ BOOST_TEST(e0 >= eN);
+ BOOST_TEST(!(eN >= e0));
+ BOOST_TEST(eN >= eN);
+
+ BOOST_TEST(!(e0 != e0));
+ BOOST_TEST(eN != e0);
+ BOOST_TEST(e0 != eN);
+ BOOST_TEST(!(eN != eN));
+ BOOST_TEST(e0 == e0);
+ BOOST_TEST(!(eN == e0));
+ BOOST_TEST(!(e0 == eN));
+ BOOST_TEST(eN == eN);
+
+ //////
+
+ BOOST_TEST(eN == stde::make_unexpected(-1));
+ BOOST_TEST(e0 != stde::make_unexpected(1));
+
+ BOOST_TEST(stde::make_unexpected(1) < e0);
+ BOOST_TEST(stde::make_unexpected(1) <= e0);
+ BOOST_TEST(!(stde::make_unexpected(1) > e0));
+ BOOST_TEST(!(stde::make_unexpected(1) >= e0));
+
+ BOOST_TEST(!(stde::make_unexpected(1) < eN));
+ BOOST_TEST(!(stde::make_unexpected(1) <= eN));
+ BOOST_TEST(stde::make_unexpected(1) > eN);
+ BOOST_TEST(stde::make_unexpected(1) >= eN);
+
+ BOOST_TEST(!(eN < stde::make_unexpected(-1)));
+ BOOST_TEST(eN <= stde::make_unexpected(-1));
+ BOOST_TEST(!(eN > stde::make_unexpected(-1)));
+ BOOST_TEST(eN >= stde::make_unexpected(-1));
+ }
+}
+void proposal_dereference_operators()
+{
+ using namespace std;
+ {
+ const string s{ "STR" };
+
+ expected_sc<string> e0{ s };
+ const expected_sc<string> e1{ s };
+ BOOST_TEST(*e0.operator->() == s);
+ BOOST_TEST(*e1.operator->() == s);
+
+ // Test with class which has operator&() overloaded
+ const OverloadedAddressOf o{};
+ BOOST_TEST(&o == nullptr);
+
+ expected_sc<OverloadedAddressOf> e2{ o };
+ const expected_sc<OverloadedAddressOf> e3{ o };
+ BOOST_TEST(e2.operator->() != nullptr);
+ BOOST_TEST(e3.operator->() != nullptr);
+ }
+}
+BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE(movesem)
+//////////////////////////////
+void movesem_moved_from_state()
+{
+ // first, test mock:
+ MoveAware<int> i{ 1 }, j{ 2 };
+ BOOST_TEST(i.val == 1);
+ BOOST_TEST(!i.moved);
+ BOOST_TEST(j.val == 2);
+ BOOST_TEST(!j.moved);
+
+ MoveAware<int> k = std::move(i);
+ BOOST_TEST(k.val == 1);
+ BOOST_TEST(!k.moved);
+ BOOST_TEST(i.val == 1);
+ BOOST_TEST(i.moved);
+
+ k = std::move(j);
+ BOOST_TEST(k.val == 2);
+ BOOST_TEST(!k.moved);
+ BOOST_TEST(j.val == 2);
+ BOOST_TEST(j.moved);
+
+ // now, test stde::expected
+ expected_sc<MoveAware<int>> oi{ 1 }, oj{ 2 };
+ BOOST_TEST(oi);
+ BOOST_TEST(!oi->moved);
+ BOOST_TEST(oj);
+ BOOST_TEST(!oj->moved);
+
+ expected_sc<MoveAware<int>> ok{ std::move(oi) };
+ BOOST_TEST(ok);
+ BOOST_TEST(!ok->moved);
+ BOOST_TEST(oi);
+ BOOST_TEST(oi->moved);
+
+ ok = std::move(oj);
+ BOOST_TEST(ok);
+ BOOST_TEST(!ok->moved);
+ BOOST_TEST(oj);
+ BOOST_TEST(oj->moved);
+
+}
+void movesem_move_only_value()
+{
+ const auto make_int = []() {
+ std::unique_ptr<int> value{ new int };
+ *value = 100;
+ return value;
+ };
+ const auto return_void = [](std::unique_ptr<int> value) {
+ BOOST_TEST(value != nullptr);
+ BOOST_TEST(*value == 100);
+ };
+ const auto return_expected = [](std::unique_ptr<int> value) {
+ BOOST_TEST(value != nullptr);
+ BOOST_TEST(*value == 100);
+ return expected_sc<void>{boost::expect};
+ };
+ const auto return_int = [](std::unique_ptr<int> value) {
+ BOOST_TEST(value != nullptr);
+ BOOST_TEST(*value == 100);
+ return 200;
+ };
+
+ BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.map(return_void));
+ BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.map(return_expected));
+ BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.map(return_int));
+}
+void movesem_move_only_value2()
+{
+ const auto make_int = []() {
+ std::unique_ptr<int> value{ new int };
+ *value = 100;
+ return value;
+ };
+ const auto return_expected_void = [](std::unique_ptr<int> value) {
+ BOOST_TEST(value != nullptr);
+ BOOST_TEST(*value == 100);
+ return stde::make_expected();
+ };
+ const auto return_expected = [](std::unique_ptr<int> value) {
+ BOOST_TEST(value != nullptr);
+ BOOST_TEST(*value == 100);
+ return expected_sc<void>{boost::expect};
+ };
+ BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.bind(return_expected_void));
+ BOOST_TEST(expected<std::unique_ptr<int>>{make_int()}.bind(return_expected));
+}
+void movesem_copy_move_ctor_optional_int()
+{
+ expected_sc<int> oi;
+ expected_sc<int> oj = oi;
+
+ BOOST_TEST(oj);
+ BOOST_TEST(oj == oi);
+ BOOST_TEST(bool(oj));
+
+ oi = 1;
+ expected_sc<int> ok = oi;
+ BOOST_TEST(!!ok);
+ BOOST_TEST(bool(ok));
+ BOOST_TEST(ok == oi);
+ BOOST_TEST(ok != oj);
+ BOOST_TEST(*ok == 1);
+
+ expected_sc<int> ol = std::move(oi);
+ BOOST_TEST(!!ol);
+ BOOST_TEST(bool(ol));
+ BOOST_TEST(ol == oi);
+ BOOST_TEST(ol != oj);
+ BOOST_TEST(*ol == 1);
+}
+void movesem_expected_expected()
+{
+ expected_sc<stde::expected<int, int>> oi1 = stde::make_unexpected(-1);
+ BOOST_TEST(!oi1);
+
+ {
+ expected_sc<expected_sc<int>> oi2{ stde::expect };
+ BOOST_TEST(bool(oi2));
+ BOOST_TEST((*oi2));
+ //std::cout << typeid(**oi2).name() << std::endl;
+ }
+
+ {
+ expected_sc<stde::expected<int, int>> oi2{ stde::expect, stde::make_unexpected(-1) };
+ BOOST_TEST(bool(oi2));
+ BOOST_TEST(!*oi2);
+ }
+
+ {
+ stde::expected<stde::expected<int>> oi2{ stde::expected<int>{} };
+ BOOST_TEST(bool(oi2));
+ BOOST_TEST(*oi2);
+ }
+
+ stde::expected<int> oi;
+ auto ooi = stde::make_expected(oi);
+ static_assert(std::is_same<expected<expected<int>>, decltype(ooi)>::value, "");
+
+}
+BOOST_AUTO_TEST_SUITE_END()
+
+void process() {}
+void process(int) {}
+void processNil() {}
+
+BOOST_AUTO_TEST_SUITE(Examples)
+//////////////////////////////
+
+void example1()
+{
+ stde::expected<int> oi; // create disengaged object
+ stde::expected<int> oj = { unexpect }; // alternative syntax
+ oi = oj; // assign disengaged object
+ stde::expected<int> ok = oj; // ok is disengaged
+
+ if (oi) BOOST_TEST(false); // 'if oi is engaged...'
+ if (!oi) BOOST_TEST(true); // 'if oi is disengaged...'
+
+ BOOST_TEST(oi == ok); // two disengaged optionals compare equal
+
+ ///////////////////////////////////////////////////////////////////////////
+ stde::expected<int> ol{ 1 }; // ol is engaged; its contained value is 1
+ ok = 2; // ok becomes engaged; its contained value is 2
+ oj = ol; // oj becomes engaged; its contained value is 1
+
+ BOOST_TEST(oi != ol); // disengaged != engaged
+ BOOST_TEST(ok != ol); // different contained values
+ BOOST_TEST(oj == ol); // same contained value
+ //BOOST_TEST(oi < ol); // disengaged < engaged
+ //BOOST_TEST(ol < ok); // less by contained value
+
+ /////////////////////////////////////////////////////////////////////////////
+ stde::expected<int> om{ 1 }; // om is engaged; its contained value is 1
+ stde::expected<int> on = om; // on is engaged; its contained value is 1
+ om = 2; // om is engaged; its contained value is 2
+ BOOST_TEST(on != om); // on still contains 3. They are not pointers
+
+ /////////////////////////////////////////////////////////////////////////////
+ int i = *ol; // i obtains the value contained in ol
+ BOOST_TEST(i == 1);
+ *ol = 9; // the object contained in ol becomes 9
+ BOOST_TEST(*ol == 9);
+ BOOST_TEST(ol == stde::make_expected(9));
+
+ ///////////////////////////////////
+ int p = 1;
+ stde::expected<int> op = p;
+ BOOST_TEST(*op == 1);
+ p = 2;
+ BOOST_TEST(*op == 1); // value contained in op is separated from p
+
+ ////////////////////////////////
+ if (ol)
+ process(*ol); // use contained value if present
+ else
+ process(); // proceed without contained value
+
+ if (!om)
+ processNil();
+ else
+ process(*om);
+
+ /////////////////////////////////////////
+ process(ol.value_or(0)); // use 0 if ol is disengaged
+
+ ////////////////////////////////////////////
+ ok = { unexpect }; // if ok was engaged calls T's dtor
+ oj = {}; // assigns a temporary disengaged stde::expected
+}
+//////////////////////////////////////////////////
+void ValueOr()
+{
+ stde::expected<int> oi = 1;
+ int i = oi.value_or(0);
+ BOOST_TEST(i == 1);
+
+ oi = { unexpect };
+ BOOST_TEST(oi.value_or(3) == 3);
+
+ stde::expected<std::string> os{ "AAA" };
+ BOOST_TEST(os.value_or("BBB") == "AAA");
+ os = {};
+ BOOST_TEST(os);
+ BOOST_TEST(os.value() == "");
+
+ BOOST_TEST(os.value_or(std::string("BBB")) == "");
+ {
+ constexpr stde::expected<int> e = 1;
+ static_assert(e.has_value(), "");
+ static_assert(*e == 1, "");
+ static_assert(e.value() == 1, "");
+ }
+ {
+ constexpr std::error_code ec = std::make_error_code(std::errc(1));
+ constexpr stde::expected<int> e = stde::make_unexpected(ec);
+ static_assert(!e.has_value(), "");
+ static_assert(e.error() == ec, "");
+ }
+ {
+ constexpr stde::expected<OracleVal> e = 1;
+ static_assert(e.has_value(), "");
+ static_assert(*e == 1, "");
+ static_assert(e.value() == 1, "");
+ }
+ {
+ constexpr std::error_code ec = std::make_error_code(std::errc(1));
+ constexpr stde::expected<OracleVal> e = stde::make_unexpected(ec);
+ static_assert(!e.has_value(), "");
+ static_assert(e.error() == ec, "");
+ }
+}
+
+//////////////////////////////////////////////////
+BOOST_AUTO_TEST_SUITE_END()
+
+#endif
+
+#else
+int main(void)
+{
+ return 0;
+}
+#endif