12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015 |
- //! \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
|