diff options
Diffstat (limited to '3rdparty/sol2/Optional/test_optional.cpp')
-rw-r--r-- | 3rdparty/sol2/Optional/test_optional.cpp | 1459 |
1 files changed, 0 insertions, 1459 deletions
diff --git a/3rdparty/sol2/Optional/test_optional.cpp b/3rdparty/sol2/Optional/test_optional.cpp deleted file mode 100644 index 8ed356a562b..00000000000 --- a/3rdparty/sol2/Optional/test_optional.cpp +++ /dev/null @@ -1,1459 +0,0 @@ -// Copyright (C) 2011 - 2012 Andrzej Krzemienski. -// -// Use, modification, and distribution is 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) -// -// The idea and interface is based on Boost.Optional library -// authored by Fernando Luis Cacciola Carballal - -# include "optional.hpp" -# include <vector> -# include <iostream> -# include <functional> -# include <complex> - - - -struct caller { - template <class T> caller(T fun) { fun(); } -}; -# define CAT2(X, Y) X ## Y -# define CAT(X, Y) CAT2(X, Y) -# define TEST(NAME) caller CAT(__VAR, __LINE__) = [] - -enum State -{ - sDefaultConstructed, - sValueCopyConstructed, - sValueMoveConstructed, - sCopyConstructed, - sMoveConstructed, - sMoveAssigned, - sCopyAssigned, - sValueCopyAssigned, - sValueMoveAssigned, - sMovedFrom, - sValueConstructed -}; - -struct OracleVal -{ - State s; - int i; - OracleVal(int i = 0) : s(sValueConstructed), i(i) {} -}; - -struct Oracle -{ - State s; - OracleVal val; - - Oracle() : s(sDefaultConstructed) {} - Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {} - Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;} - Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {} - Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;} - - Oracle& operator=(const OracleVal& v) { s = sValueCopyConstructed; val = v; return *this; } - Oracle& operator=(OracleVal&& v) { s = sValueMoveConstructed; val = std::move(v); v.s = sMovedFrom; return *this; } - Oracle& operator=(const Oracle& o) { s = sCopyConstructed; val = o.val; return *this; } - Oracle& operator=(Oracle&& o) { s = sMoveConstructed; val = std::move(o.val); o.s = sMovedFrom; return *this; } -}; - -struct Guard -{ - std::string val; - Guard() : val{} {} - explicit Guard(std::string s, int = 0) : val(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) : i{i} {}; - Date(Date&& d) : i(d.i) { d.i = 0; } - Date(const Date&) = delete; - Date& operator=(const Date&) = delete; - Date& operator=(Date&& d) { i = d.i; d.i = 0; return *this;}; -}; - -bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; } -bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; } - - -namespace tr2 = std::experimental; - - -TEST(disengaged_ctor) -{ - tr2::optional<int> o1; - assert (!o1); - - tr2::optional<int> o2 = tr2::nullopt; - assert (!o2); - - tr2::optional<int> o3 = o2; - assert (!o3); - - assert (o1 == tr2::nullopt); - assert (o1 == tr2::optional<int>{}); - assert (!o1); - assert (bool(o1) == false); - - assert (o2 == tr2::nullopt); - assert (o2 == tr2::optional<int>{}); - assert (!o2); - assert (bool(o2) == false); - - assert (o3 == tr2::nullopt); - assert (o3 == tr2::optional<int>{}); - assert (!o3); - assert (bool(o3) == false); - - assert (o1 == o2); - assert (o2 == o1); - assert (o1 == o3); - assert (o3 == o1); - assert (o2 == o3); - assert (o3 == o2); -}; - - -TEST(value_ctor) -{ - OracleVal v; - tr2::optional<Oracle> oo1(v); - assert (oo1 != tr2::nullopt); - assert (oo1 != tr2::optional<Oracle>{}); - assert (oo1 == tr2::optional<Oracle>{v}); - assert (!!oo1); - assert (bool(oo1)); - // NA: assert (oo1->s == sValueCopyConstructed); - assert (oo1->s == sMoveConstructed); - assert (v.s == sValueConstructed); - - tr2::optional<Oracle> oo2(std::move(v)); - assert (oo2 != tr2::nullopt); - assert (oo2 != tr2::optional<Oracle>{}); - assert (oo2 == oo1); - assert (!!oo2); - assert (bool(oo2)); - // NA: assert (oo2->s == sValueMoveConstructed); - assert (oo2->s == sMoveConstructed); - assert (v.s == sMovedFrom); - - { - OracleVal v; - tr2::optional<Oracle> oo1{tr2::in_place, v}; - assert (oo1 != tr2::nullopt); - assert (oo1 != tr2::optional<Oracle>{}); - assert (oo1 == tr2::optional<Oracle>{v}); - assert (!!oo1); - assert (bool(oo1)); - assert (oo1->s == sValueCopyConstructed); - assert (v.s == sValueConstructed); - - tr2::optional<Oracle> oo2{tr2::in_place, std::move(v)}; - assert (oo2 != tr2::nullopt); - assert (oo2 != tr2::optional<Oracle>{}); - assert (oo2 == oo1); - assert (!!oo2); - assert (bool(oo2)); - assert (oo2->s == sValueMoveConstructed); - assert (v.s == sMovedFrom); - } -}; - - -TEST(assignment) -{ - tr2::optional<int> oi; - oi = tr2::optional<int>{1}; - assert (*oi == 1); - - oi = tr2::nullopt; - assert (!oi); - - oi = 2; - assert (*oi == 2); - - oi = {}; - assert (!oi); -}; - - -template <class T> -struct MoveAware -{ - T val; - bool moved; - MoveAware(T val) : 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; - } -}; - -TEST(moved_from_state) -{ - // first, test mock: - MoveAware<int> i{1}, j{2}; - assert (i.val == 1); - assert (!i.moved); - assert (j.val == 2); - assert (!j.moved); - - MoveAware<int> k = std::move(i); - assert (k.val == 1); - assert (!k.moved); - assert (i.val == 1); - assert (i.moved); - - k = std::move(j); - assert (k.val == 2); - assert (!k.moved); - assert (j.val == 2); - assert (j.moved); - - // now, test optional - tr2::optional<MoveAware<int>> oi{1}, oj{2}; - assert (oi); - assert (!oi->moved); - assert (oj); - assert (!oj->moved); - - tr2::optional<MoveAware<int>> ok = std::move(oi); - assert (ok); - assert (!ok->moved); - assert (oi); - assert (oi->moved); - - ok = std::move(oj); - assert (ok); - assert (!ok->moved); - assert (oj); - assert (oj->moved); -}; - - -TEST(copy_move_ctor_optional_int) -{ - tr2::optional<int> oi; - tr2::optional<int> oj = oi; - - assert (!oj); - assert (oj == oi); - assert (oj == tr2::nullopt); - assert (!bool(oj)); - - oi = 1; - tr2::optional<int> ok = oi; - assert (!!ok); - assert (bool(ok)); - assert (ok == oi); - assert (ok != oj); - assert (*ok == 1); - - tr2::optional<int> ol = std::move(oi); - assert (!!ol); - assert (bool(ol)); - assert (ol == oi); - assert (ol != oj); - assert (*ol == 1); -}; - - -TEST(optional_optional) -{ - tr2::optional<tr2::optional<int>> oi1 = tr2::nullopt; - assert (oi1 == tr2::nullopt); - assert (!oi1); - - { - tr2::optional<tr2::optional<int>> oi2 {tr2::in_place}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - //assert (!(*oi2)); - //std::cout << typeid(**oi2).name() << std::endl; - } - - { - tr2::optional<tr2::optional<int>> oi2 {tr2::in_place, tr2::nullopt}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - assert (!*oi2); - } - - { - tr2::optional<tr2::optional<int>> oi2 {tr2::optional<int>{}}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - assert (!*oi2); - } - - tr2::optional<int> oi; - auto ooi = tr2::make_optional(oi); - static_assert( std::is_same<tr2::optional<tr2::optional<int>>, decltype(ooi)>::value, ""); - -}; - -TEST(example_guard) -{ - using namespace tr2; - //FAILS: optional<Guard> ogx(Guard("res1")); - //FAILS: optional<Guard> ogx = "res1"; - //FAILS: optional<Guard> ogx("res1"); - optional<Guard> oga; // Guard is non-copyable (and non-moveable) - optional<Guard> ogb(in_place, "res1"); // initialzes the contained value with "res1" - assert (bool(ogb)); - assert (ogb->val == "res1"); - - optional<Guard> ogc(in_place); // default-constructs the contained value - assert (bool(ogc)); - assert (ogc->val == ""); - - oga.emplace("res1"); // initialzes the contained value with "res1" - assert (bool(oga)); - assert (oga->val == "res1"); - - oga.emplace(); // destroys the contained value and - // default-constructs the new one - assert (bool(oga)); - assert (oga->val == ""); - - oga = nullopt; // OK: make disengaged the optional Guard - assert (!(oga)); - //FAILS: ogb = {}; // ERROR: Guard is not Moveable -}; - - -void process(){} -void process(int ){} -void processNil(){} - - -TEST(example1) -{ - using namespace tr2; - optional<int> oi; // create disengaged object - optional<int> oj = nullopt; // alternative syntax - oi = oj; // assign disengaged object - optional<int> ok = oj; // ok is disengaged - - if (oi) assert(false); // 'if oi is engaged...' - if (!oi) assert(true); // 'if oi is disengaged...' - - if (oi != nullopt) assert(false); // 'if oi is engaged...' - if (oi == nullopt) assert(true); // 'if oi is disengaged...' - - assert(oi == ok); // two disengaged optionals compare equal - - /////////////////////////////////////////////////////////////////////////// - optional<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 - - assert(oi != ol); // disengaged != engaged - assert(ok != ol); // different contained values - assert(oj == ol); // same contained value - assert(oi < ol); // disengaged < engaged - assert(ol < ok); // less by contained value - - ///////////////////////////////////////////////////////////////////////////// - optional<int> om{1}; // om is engaged; its contained value is 1 - optional<int> on = om; // on is engaged; its contained value is 1 - om = 2; // om is engaged; its contained value is 2 - assert (on != om); // on still contains 3. They are not pointers - - ///////////////////////////////////////////////////////////////////////////// - int i = *ol; // i obtains the value contained in ol - assert (i == 1); - *ol = 9; // the object contained in ol becomes 9 - assert(*ol == 9); - assert(ol == make_optional(9)); - - /////////////////////////////////// - int p = 1; - optional<int> op = p; - assert(*op == 1); - p = 2; - assert(*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 = nullopt; // if ok was engaged calls T's dtor - oj = {}; // assigns a temporary disengaged optional -}; - - -TEST(example_guard) -{ - using std::experimental::optional; - const optional<int> c = 4; - int i = *c; // i becomes 4 - assert (i == 4); - // FAILS: *c = i; // ERROR: cannot assign to const int& -}; - - -TEST(example_ref) -{ - using namespace std::experimental; - int i = 1; - int j = 2; - optional<int&> ora; // disengaged optional reference to int - optional<int&> orb = i; // contained reference refers to object i - - *orb = 3; // i becomes 3 - // FAILS: ora = j; // ERROR: optional refs do not have assignment from T - // FAILS: ora = {j}; // ERROR: optional refs do not have copy/move assignment - // FAILS: ora = orb; // ERROR: no copy/move assignment - ora.emplace(j); // OK: contained reference refers to object j - ora.emplace(i); // OK: contained reference now refers to object i - - ora = nullopt; // OK: ora becomes disengaged -}; - - -template <typename T> -T getValue( tr2::optional<T> newVal = tr2::nullopt, tr2::optional<T&> storeHere = tr2::nullopt ) -{ - T cached{}; - - if (newVal) { - cached = *newVal; - - if (storeHere) { - *storeHere = *newVal; // LEGAL: assigning T to T - } - } - return cached; -} - -TEST(example_optional_arg) -{ - int iii = 0; - iii = getValue<int>(iii, iii); - iii = getValue<int>(iii); - iii = getValue<int>(); - - { - using namespace std::experimental; - optional<Guard> grd1{in_place, "res1", 1}; // guard 1 initialized - optional<Guard> grd2; - - grd2.emplace("res2", 2); // guard 2 initialized - grd1 = nullopt; // guard 1 released - - } // guard 2 released (in dtor) -}; - - -std::tuple<Date, Date, Date> getStartMidEnd() { return std::tuple<Date, Date, Date>{Date{1}, Date{2}, Date{3}}; } -void run(Date const&, Date const&, Date const&) {} - -TEST(example_date) -{ - using namespace std::experimental; - optional<Date> start, mid, end; // Date doesn't have default ctor (no good default date) - - std::tie(start, mid, end) = getStartMidEnd(); - run(*start, *mid, *end); -}; - - -std::experimental::optional<char> readNextChar(){ return{}; } - -void run(std::experimental::optional<std::string>) {} -void run(std::complex<double>) {} - - -template <class T> -void assign_norebind(tr2::optional<T&>& optref, T& obj) -{ - if (optref) *optref = obj; - else optref.emplace(obj); -} - -template <typename T> void unused(T&&) {} - -TEST(example_conceptual_model) -{ - using namespace std::experimental; - - optional<int> oi = 0; - optional<int> oj = 1; - optional<int> ok = nullopt; - - oi = 1; - oj = nullopt; - ok = 0; - - unused(oi == nullopt); - unused(oj == 0); - unused(ok == 1); -}; - -TEST(example_rationale) -{ - using namespace std::experimental; - if (optional<char> ch = readNextChar()) { - unused(ch); - // ... - } - - ////////////////////////////////// - optional<int> opt1 = nullopt; - optional<int> opt2 = {}; - - opt1 = nullopt; - opt2 = {}; - - if (opt1 == nullopt) {} - if (!opt2) {} - if (opt2 == optional<int>{}) {} - - - - //////////////////////////////// - - run(nullopt); // pick the second overload - // FAILS: run({}); // ambiguous - - if (opt1 == nullopt) {} // fine - // FAILS: if (opt2 == {}) {} // ilegal - - //////////////////////////////// - assert (optional<unsigned>{} < optional<unsigned>{0}); - assert (optional<unsigned>{0} < optional<unsigned>{1}); - assert (!(optional<unsigned>{} < optional<unsigned>{}) ); - assert (!(optional<unsigned>{1} < optional<unsigned>{1})); - - assert (optional<unsigned>{} != optional<unsigned>{0}); - assert (optional<unsigned>{0} != optional<unsigned>{1}); - assert (optional<unsigned>{} == optional<unsigned>{} ); - assert (optional<unsigned>{0} == optional<unsigned>{0}); - - ///////////////////////////////// - optional<int> o; - o = make_optional(1); // copy/move assignment - o = 1; // assignment from T - o.emplace(1); // emplacement - - //////////////////////////////////// - int isas = 0, i = 9; - optional<int&> asas = i; - assign_norebind(asas, isas); - - ///////////////////////////////////// - ////tr2::optional<std::vector<int>> ov2 = {2, 3}; - ////assert (bool(ov2)); - ////assert ((*ov2)[1] == 3); - //// - //////////////////////////////// - ////std::vector<int> v = {1, 2, 4, 8}; - ////optional<std::vector<int>> ov = {1, 2, 4, 8}; - - ////assert (v == *ov); - //// - ////ov = {1, 2, 4, 8}; - - ////std::allocator<int> a; - ////optional<std::vector<int>> ou { in_place, {1, 2, 4, 8}, a }; - - ////assert (ou == ov); - - ////////////////////////////// - // inconvenient syntax: - { - - tr2::optional<std::vector<int>> ov2{tr2::in_place, {2, 3}}; - - assert (bool(ov2)); - assert ((*ov2)[1] == 3); - - //////////////////////////// - - std::vector<int> v = {1, 2, 4, 8}; - optional<std::vector<int>> ov{tr2::in_place, {1, 2, 4, 8}}; - - assert (v == *ov); - - ov.emplace({1, 2, 4, 8}); -/* - std::allocator<int> a; - optional<std::vector<int>> ou { in_place, {1, 2, 4, 8}, a }; - - assert (ou == ov); -*/ - } - - ///////////////////////////////// - { - typedef int T; - optional<optional<T>> ot {in_place}; - optional<optional<T>> ou {in_place, nullopt}; - optional<optional<T>> ov {optional<T>{}}; - - optional<int> oi; - auto ooi = make_optional(oi); - static_assert( std::is_same<optional<optional<int>>, decltype(ooi)>::value, ""); - } -}; - - -bool fun(std::string , std::experimental::optional<int> oi = std::experimental::nullopt) -{ - return bool(oi); -} - -TEST(example_converting_ctor) -{ - using namespace std::experimental; - - assert (true == fun("dog", 2)); - assert (false == fun("dog")); - assert (false == fun("dog", nullopt)); // just to be explicit -}; - - -TEST(bad_comparison) -{ - tr2::optional<int> oi, oj; - int i; - bool b = (oi == oj); - b = (oi >= i); - b = (oi == i); - unused(b); -}; - - -//// NOT APPLICABLE ANYMORE -////TEST(perfect_ctor) -////{ -//// //tr2::optional<std::string> ois = "OS"; -//// assert (*ois == "OS"); -//// -//// // FAILS: tr2::optional<ExplicitStr> oes = "OS"; -//// tr2::optional<ExplicitStr> oes{"OS"}; -//// assert (oes->s == "OS"); -////}; - -TEST(value_or) -{ - tr2::optional<int> oi = 1; - int i = oi.value_or(0); - assert (i == 1); - - oi = tr2::nullopt; - assert (oi.value_or(3) == 3); - - tr2::optional<std::string> os{"AAA"}; - assert (os.value_or("BBB") == "AAA"); - os = {}; - assert (os.value_or("BBB") == "BBB"); -}; - -TEST(mixed_order) -{ - using namespace std::experimental; - - optional<int> oN {nullopt}; - optional<int> o0 {0}; - optional<int> o1 {1}; - - assert ( (oN < 0)); - assert ( (oN < 1)); - assert (!(o0 < 0)); - assert ( (o0 < 1)); - assert (!(o1 < 0)); - assert (!(o1 < 1)); - - assert (!(oN >= 0)); - assert (!(oN >= 1)); - assert ( (o0 >= 0)); - assert (!(o0 >= 1)); - assert ( (o1 >= 0)); - assert ( (o1 >= 1)); - - assert (!(oN > 0)); - assert (!(oN > 1)); - assert (!(o0 > 0)); - assert (!(o0 > 1)); - assert ( (o1 > 0)); - assert (!(o1 > 1)); - - assert ( (oN <= 0)); - assert ( (oN <= 1)); - assert ( (o0 <= 0)); - assert ( (o0 <= 1)); - assert (!(o1 <= 0)); - assert ( (o1 <= 1)); - - assert ( (0 > oN)); - assert ( (1 > oN)); - assert (!(0 > o0)); - assert ( (1 > o0)); - assert (!(0 > o1)); - assert (!(1 > o1)); - - assert (!(0 <= oN)); - assert (!(1 <= oN)); - assert ( (0 <= o0)); - assert (!(1 <= o0)); - assert ( (0 <= o1)); - assert ( (1 <= o1)); - - assert (!(0 < oN)); - assert (!(1 < oN)); - assert (!(0 < o0)); - assert (!(1 < o0)); - assert ( (0 < o1)); - assert (!(1 < o1)); - - assert ( (0 >= oN)); - assert ( (1 >= oN)); - assert ( (0 >= o0)); - assert ( (1 >= o0)); - assert (!(0 >= o1)); - assert ( (1 >= o1)); -}; - -struct BadRelops -{ - int i; -}; - -constexpr bool operator<(BadRelops a, BadRelops b) { return a.i < b.i; } -constexpr bool operator>(BadRelops a, BadRelops b) { return a.i < b.i; } // intentional error! - -TEST(bad_relops) -{ - using namespace std::experimental; - BadRelops a{1}, b{2}; - assert (a < b); - assert (a > b); - - optional<BadRelops> oa = a, ob = b; - assert (oa < ob); - assert (!(oa > ob)); - - assert (oa < b); - assert (oa > b); - - optional<BadRelops&> ra = a, rb = b; - assert (ra < rb); - assert (!(ra > rb)); - - assert (ra < b); - assert (ra > b); -}; - - -TEST(mixed_equality) -{ - using namespace std::experimental; - - assert (make_optional(0) == 0); - assert (make_optional(1) == 1); - assert (make_optional(0) != 1); - assert (make_optional(1) != 0); - - optional<int> oN {nullopt}; - optional<int> o0 {0}; - optional<int> o1 {1}; - - assert (o0 == 0); - assert ( 0 == o0); - assert (o1 == 1); - assert ( 1 == o1); - assert (o1 != 0); - assert ( 0 != o1); - assert (o0 != 1); - assert ( 1 != o0); - - assert ( 1 != oN); - assert ( 0 != oN); - assert (oN != 1); - assert (oN != 0); - assert (!( 1 == oN)); - assert (!( 0 == oN)); - assert (!(oN == 1)); - assert (!(oN == 0)); - - std::string cat{"cat"}, dog{"dog"}; - optional<std::string> oNil{}, oDog{"dog"}, oCat{"cat"}; - - assert (oCat == cat); - assert ( cat == oCat); - assert (oDog == dog); - assert ( dog == oDog); - assert (oDog != cat); - assert ( cat != oDog); - assert (oCat != dog); - assert ( dog != oCat); - - assert ( dog != oNil); - assert ( cat != oNil); - assert (oNil != dog); - assert (oNil != cat); - assert (!( dog == oNil)); - assert (!( cat == oNil)); - assert (!(oNil == dog)); - assert (!(oNil == cat)); -}; - -TEST(const_propagation) -{ - using namespace std::experimental; - - optional<int> mmi{0}; - static_assert(std::is_same<decltype(*mmi), int&>::value, "WTF"); - - const optional<int> cmi{0}; - static_assert(std::is_same<decltype(*cmi), const int&>::value, "WTF"); - - optional<const int> mci{0}; - static_assert(std::is_same<decltype(*mci), const int&>::value, "WTF"); - - optional<const int> cci{0}; - static_assert(std::is_same<decltype(*cci), const int&>::value, "WTF"); -}; - - -static_assert(std::is_base_of<std::logic_error, std::experimental::bad_optional_access>::value, ""); - -TEST(safe_value) -{ - using namespace std::experimental; - - try { - optional<int> ovN{}, ov1{1}; - - int& r1 = ov1.value(); - assert (r1 == 1); - - try { - ovN.value(); - assert (false); - } - catch (bad_optional_access const&) { - } - - { // ref variant - int i1 = 1; - optional<int&> orN{}, or1{i1}; - - int& r2 = or1.value(); - assert (r2 == 1); - - try { - orN.value(); - assert (false); - } - catch (bad_optional_access const&) { - } - } - } - catch(...) { - assert (false); - } -}; - -TEST(optional_ref) -{ - using namespace tr2; - // FAILS: optional<int&&> orr; - // FAILS: optional<nullopt_t&> on; - int i = 8; - optional<int&> ori; - assert (!ori); - ori.emplace(i); - assert (bool(ori)); - assert (*ori == 8); - assert (&*ori == &i); - *ori = 9; - assert (i == 9); - - // FAILS: int& ir = ori.value_or(i); - int ii = ori.value_or(i); - assert (ii == 9); - ii = 7; - assert (*ori == 9); - - int j = 22; - auto&& oj = make_optional(std::ref(j)); - *oj = 23; - assert (&*oj == &j); - assert (j == 23); -}; - -TEST(optional_ref_const_propagation) -{ - using namespace std::experimental; - - int i = 9; - const optional<int&> mi = i; - int& r = *mi; - optional<const int&> ci = i; - static_assert(std::is_same<decltype(*mi), int&>::value, "WTF"); - static_assert(std::is_same<decltype(*ci), const int&>::value, "WTF"); - - unused(r); -}; - -TEST(optional_ref_assign) -{ - using namespace std::experimental; - - int i = 9; - optional<int&> ori = i; - - int j = 1; - ori = optional<int&>{j}; - ori = {j}; - // FAILS: ori = j; - - optional<int&> orx = ori; - ori = orx; - - optional<int&> orj = j; - - assert (ori); - assert (*ori == 1); - assert (ori == orj); - assert (i == 9); - - *ori = 2; - assert (*ori == 2); - assert (ori == 2); - assert (2 == ori); - assert (ori != 3); - - assert (ori == orj); - assert (j == 2); - assert (i == 9); - - ori = {}; - assert (!ori); - assert (ori != orj); - assert (j == 2); - assert (i == 9); -}; - - -TEST(optional_ref_swap) -{ - using namespace std::experimental; - int i = 0; - int j = 1; - optional<int&> oi = i; - optional<int&> oj = j; - - assert (&*oi == &i); - assert (&*oj == &j); - - swap(oi, oj); - assert (&*oi == &j); - assert (&*oj == &i); -}; - -TEST(optional_initialization) -{ - using namespace tr2; - using std::string; - string s = "STR"; - - optional<string> os{s}; - optional<string> ot = s; - optional<string> ou{"STR"}; - optional<string> ov = string{"STR"}; - -}; - -#include <unordered_set> - -TEST(optional_hashing) -{ - using namespace tr2; - using std::string; - - std::hash<int> hi; - std::hash<optional<int>> hoi; - std::hash<string> hs; - std::hash<optional<string>> hos; - - assert (hi(0) == hoi(optional<int>{0})); - assert (hi(1) == hoi(optional<int>{1})); - assert (hi(3198) == hoi(optional<int>{3198})); - - assert (hs("") == hos(optional<string>{""})); - assert (hs("0") == hos(optional<string>{"0"})); - assert (hs("Qa1#") == hos(optional<string>{"Qa1#"})); - - std::unordered_set<optional<string>> set; - assert(set.find({"Qa1#"}) == set.end()); - - set.insert({"0"}); - assert(set.find({"Qa1#"}) == set.end()); - - set.insert({"Qa1#"}); - assert(set.find({"Qa1#"}) != set.end()); -}; - - -// optional_ref_emulation -template <class T> -struct generic -{ - typedef T type; -}; - -template <class U> -struct generic<U&> -{ - typedef std::reference_wrapper<U> type; -}; - -template <class T> -using Generic = typename generic<T>::type; - -template <class X> -bool generic_fun() -{ - std::experimental::optional<Generic<X>> op; - return bool(op); -} - -TEST(optional_ref_emulation) -{ - using namespace std::experimental; - optional<Generic<int>> oi = 1; - assert (*oi == 1); - - int i = 8; - int j = 4; - optional<Generic<int&>> ori {i}; - assert (*ori == 8); - assert ((void*)&*ori != (void*)&i); // !DIFFERENT THAN optional<T&> - - *ori = j; - assert (*ori == 4); -}; - - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 -TEST(moved_on_value_or) -{ - using namespace tr2; - optional<Oracle> oo{in_place}; - - assert (oo); - assert (oo->s == sDefaultConstructed); - - Oracle o = std::move(oo).value_or( Oracle{OracleVal{}} ); - assert (oo); - assert (oo->s == sMovedFrom); - assert (o.s == sMoveConstructed); - - optional<MoveAware<int>> om {in_place, 1}; - assert (om); - assert (om->moved == false); - - /*MoveAware<int> m =*/ std::move(om).value_or( MoveAware<int>{1} ); - assert (om); - assert (om->moved == true); - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - { - Date d = optional<Date>{in_place, 1}.value(); - assert (d.i); // to silence compiler warning - - Date d2 = *optional<Date>{in_place, 1}; - assert (d2.i); // to silence compiler warning - } -# endif -}; -# endif - - -TEST(optional_ref_hashing) -{ - using namespace tr2; - using std::string; - - std::hash<int> hi; - std::hash<optional<int&>> hoi; - std::hash<string> hs; - std::hash<optional<string&>> hos; - - int i0 = 0; - int i1 = 1; - assert (hi(0) == hoi(optional<int&>{i0})); - assert (hi(1) == hoi(optional<int&>{i1})); - - string s{""}; - string s0{"0"}; - string sCAT{"CAT"}; - assert (hs("") == hos(optional<string&>{s})); - assert (hs("0") == hos(optional<string&>{s0})); - assert (hs("CAT") == hos(optional<string&>{sCAT})); - - std::unordered_set<optional<string&>> set; - assert(set.find({sCAT}) == set.end()); - - set.insert({s0}); - assert(set.find({sCAT}) == set.end()); - - set.insert({sCAT}); - assert(set.find({sCAT}) != set.end()); -}; - -struct Combined -{ - int m = 0; - int n = 1; - - constexpr Combined() : m{5}, n{6} {} - constexpr Combined(int m, int n) : m{m}, n{n} {} -}; - -struct Nasty -{ - int m = 0; - int n = 1; - - constexpr Nasty() : m{5}, n{6} {} - constexpr Nasty(int m, int n) : m{m}, n{n} {} - - int operator&() { return n; } - int operator&() const { return n; } -}; - -TEST(arrow_operator) -{ - using namespace std::experimental; - - optional<Combined> oc1{in_place, 1, 2}; - assert (oc1); - assert (oc1->m == 1); - assert (oc1->n == 2); - - optional<Nasty> on{in_place, 1, 2}; - assert (on); - assert (on->m == 1); - assert (on->n == 2); -}; - -TEST(arrow_wit_optional_ref) -{ - using namespace std::experimental; - - Combined c{1, 2}; - optional<Combined&> oc = c; - assert (oc); - assert (oc->m == 1); - assert (oc->n == 2); - - Nasty n{1, 2}; - Nasty m{3, 4}; - Nasty p{5, 6}; - - optional<Nasty&> on{n}; - assert (on); - assert (on->m == 1); - assert (on->n == 2); - - on = {m}; - assert (on); - assert (on->m == 3); - assert (on->n == 4); - - on.emplace(p); - assert (on); - assert (on->m == 5); - assert (on->n == 6); - - optional<Nasty&> om{in_place, n}; - assert (om); - assert (om->m == 1); - assert (om->n == 2); -}; - -TEST(no_dangling_reference_in_value) -{ - // this mostly tests compiler warnings - using namespace std::experimental; - optional<int> oi {2}; - unused (oi.value()); - const optional<int> coi {3}; - unused (coi.value()); -}; - -struct CountedObject -{ - static int _counter; - bool _throw; - CountedObject(bool b) : _throw(b) { ++_counter; } - CountedObject(CountedObject const& rhs) : _throw(rhs._throw) { if (_throw) throw int(); } - ~CountedObject() { --_counter; } -}; - -int CountedObject::_counter = 0; - -TEST(exception_safety) -{ - using namespace std::experimental; - try { - optional<CountedObject> oo(in_place, true); // throw - optional<CountedObject> o1(oo); - } - catch(...) - { - // - } - assert(CountedObject::_counter == 0); - - try { - optional<CountedObject> oo(in_place, true); // throw - optional<CountedObject> o1(std::move(oo)); // now move - } - catch(...) - { - // - } - assert(CountedObject::_counter == 0); -}; - -//// constexpr tests - -// these 4 classes have different noexcept signatures in move operations -struct NothrowBoth { - NothrowBoth(NothrowBoth&&) noexcept(true) {}; - void operator=(NothrowBoth&&) noexcept(true) {}; -}; -struct NothrowCtor { - NothrowCtor(NothrowCtor&&) noexcept(true) {}; - void operator=(NothrowCtor&&) noexcept(false) {}; -}; -struct NothrowAssign { - NothrowAssign(NothrowAssign&&) noexcept(false) {}; - void operator=(NothrowAssign&&) noexcept(true) {}; -}; -struct NothrowNone { - NothrowNone(NothrowNone&&) noexcept(false) {}; - void operator=(NothrowNone&&) noexcept(false) {}; -}; - -void test_noexcept() -{ - { - tr2::optional<NothrowBoth> b1, b2; - static_assert(noexcept(tr2::optional<NothrowBoth>{tr2::constexpr_move(b1)}), "bad noexcept!"); - static_assert(noexcept(b1 = tr2::constexpr_move(b2)), "bad noexcept!"); - } - { - tr2::optional<NothrowCtor> c1, c2; - static_assert(noexcept(tr2::optional<NothrowCtor>{tr2::constexpr_move(c1)}), "bad noexcept!"); - static_assert(!noexcept(c1 = tr2::constexpr_move(c2)), "bad noexcept!"); - } - { - tr2::optional<NothrowAssign> a1, a2; - static_assert(!noexcept(tr2::optional<NothrowAssign>{tr2::constexpr_move(a1)}), "bad noexcept!"); - static_assert(!noexcept(a1 = tr2::constexpr_move(a2)), "bad noexcept!"); - } - { - tr2::optional<NothrowNone> n1, n2; - static_assert(!noexcept(tr2::optional<NothrowNone>{tr2::constexpr_move(n1)}), "bad noexcept!"); - static_assert(!noexcept(n1 = tr2::constexpr_move(n2)), "bad noexcept!"); - } -} - - -void constexpr_test_disengaged() -{ - constexpr tr2::optional<int> g0{}; - constexpr tr2::optional<int> g1{tr2::nullopt}; - static_assert( !g0, "initialized!" ); - static_assert( !g1, "initialized!" ); - - static_assert( bool(g1) == bool(g0), "ne!" ); - - static_assert( g1 == g0, "ne!" ); - static_assert( !(g1 != g0), "ne!" ); - static_assert( g1 >= g0, "ne!" ); - static_assert( !(g1 > g0), "ne!" ); - static_assert( g1 <= g0, "ne!" ); - static_assert( !(g1 <g0), "ne!" ); - - static_assert( g1 == tr2::nullopt, "!" ); - static_assert( !(g1 != tr2::nullopt), "!" ); - static_assert( g1 <= tr2::nullopt, "!" ); - static_assert( !(g1 < tr2::nullopt), "!" ); - static_assert( g1 >= tr2::nullopt, "!" ); - static_assert( !(g1 > tr2::nullopt), "!" ); - - static_assert( (tr2::nullopt == g0), "!" ); - static_assert( !(tr2::nullopt != g0), "!" ); - static_assert( (tr2::nullopt >= g0), "!" ); - static_assert( !(tr2::nullopt > g0), "!" ); - static_assert( (tr2::nullopt <= g0), "!" ); - static_assert( !(tr2::nullopt < g0), "!" ); - - static_assert( (g1 != tr2::optional<int>(1)), "!" ); - static_assert( !(g1 == tr2::optional<int>(1)), "!" ); - static_assert( (g1 < tr2::optional<int>(1)), "!" ); - static_assert( (g1 <= tr2::optional<int>(1)), "!" ); - static_assert( !(g1 > tr2::optional<int>(1)), "!" ); - static_assert( !(g1 > tr2::optional<int>(1)), "!" ); -} - - -constexpr tr2::optional<int> g0{}; -constexpr tr2::optional<int> g2{2}; -static_assert( g2, "not initialized!" ); -static_assert( *g2 == 2, "not 2!" ); -static_assert( g2 == tr2::optional<int>(2), "not 2!" ); -static_assert( g2 != g0, "eq!" ); - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 -static_assert( *tr2::optional<int>{3} == 3, "WTF!" ); -static_assert( tr2::optional<int>{3}.value() == 3, "WTF!" ); -static_assert( tr2::optional<int>{3}.value_or(1) == 3, "WTF!" ); -static_assert( tr2::optional<int>{}.value_or(4) == 4, "WTF!" ); -# endif - -constexpr tr2::optional<Combined> gc0{tr2::in_place}; -static_assert(gc0->n == 6, "WTF!"); - -// optional refs -int gi = 0; -constexpr tr2::optional<int&> gori = gi; -constexpr tr2::optional<int&> gorn{}; -constexpr int& gri = *gori; -static_assert(gori, "WTF"); -static_assert(!gorn, "WTF"); -static_assert(gori != tr2::nullopt, "WTF"); -static_assert(gorn == tr2::nullopt, "WTF"); -static_assert(&gri == &*gori, "WTF"); - -constexpr int gci = 1; -constexpr tr2::optional<int const&> gorci = gci; -constexpr tr2::optional<int const&> gorcn{}; - -static_assert(gorcn < gorci, "WTF"); -static_assert(gorcn <= gorci, "WTF"); -static_assert(gorci == gorci, "WTF"); -static_assert(*gorci == 1, "WTF"); -static_assert(gorci == gci, "WTF"); - -namespace constexpr_optional_ref_and_arrow -{ - using namespace std::experimental; - constexpr Combined c{1, 2}; - constexpr optional<Combined const&> oc = c; - static_assert(oc, "WTF!"); - static_assert(oc->m == 1, "WTF!"); - static_assert(oc->n == 2, "WTF!"); -} - -#if OPTIONAL_HAS_CONSTEXPR_INIT_LIST - -namespace InitList -{ - using namespace std::experimental; - - struct ConstInitLister - { - template <typename T> - constexpr ConstInitLister(std::initializer_list<T> il) : len (il.size()) {} - size_t len; - }; - - constexpr ConstInitLister CIL {2, 3, 4}; - static_assert(CIL.len == 3, "WTF!"); - - constexpr optional<ConstInitLister> oil {in_place, {4, 5, 6, 7}}; - static_assert(oil, "WTF!"); - static_assert(oil->len == 4, "WTF!"); -} - -#endif // OPTIONAL_HAS_CONSTEXPR_INIT_LIST - -// end constexpr tests - - -#include <string> - - -struct VEC -{ - std::vector<int> v; - template <typename... X> - VEC( X&&...x) : v(std::forward<X>(x)...) {} - - template <typename U, typename... X> - VEC(std::initializer_list<U> il, X&&...x) : v(il, std::forward<X>(x)...) {} -}; - - - -int main() { - tr2::optional<int> oi = 1; - assert (bool(oi)); - oi.operator=({}); - assert (!oi); - - VEC v = {5, 6}; - - if (OPTIONAL_HAS_THIS_RVALUE_REFS) - std::cout << "Optional has rvalue references for *this" << std::endl; - else - std::cout << "Optional doesn't have rvalue references for *this" << std::endl; - - if (OPTIONAL_HAS_CONSTEXPR_INIT_LIST) - std::cout << "Optional has constexpr initializer_list" << std::endl; - else - std::cout << "Optional doesn't have constexpr initializer_list" << std::endl; - - if (OPTIONAL_HAS_MOVE_ACCESSORS) - std::cout << "Optional has constexpr move accessors" << std::endl; - else - std::cout << "Optional doesn't have constexpr move accessors" << std::endl; -} - |