| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780 |
- #include <iostream>
- #include <type_traits>
- #include <vector>
- #include <cm/optional>
- #include <cm/utility>
- class EventLogger;
- class Event
- {
- public:
- enum EventType
- {
- DEFAULT_CONSTRUCT,
- COPY_CONSTRUCT,
- MOVE_CONSTRUCT,
- VALUE_CONSTRUCT,
- DESTRUCT,
- COPY_ASSIGN,
- MOVE_ASSIGN,
- VALUE_ASSIGN,
- REFERENCE,
- CONST_REFERENCE,
- RVALUE_REFERENCE,
- CONST_RVALUE_REFERENCE,
- SWAP,
- COMPARE_EE_EQ,
- COMPARE_EE_NE,
- COMPARE_EE_LT,
- COMPARE_EE_LE,
- COMPARE_EE_GT,
- COMPARE_EE_GE,
- };
- EventType Type;
- const EventLogger* Logger1;
- const EventLogger* Logger2;
- int Value;
- bool operator==(const Event& other) const;
- bool operator!=(const Event& other) const;
- };
- bool Event::operator==(const Event& other) const
- {
- return this->Type == other.Type && this->Logger1 == other.Logger1 &&
- this->Logger2 == other.Logger2 && this->Value == other.Value;
- }
- bool Event::operator!=(const Event& other) const
- {
- return !(*this == other);
- }
- static std::vector<Event> events;
- class EventLogger
- {
- public:
- EventLogger();
- EventLogger(const EventLogger& other);
- EventLogger(EventLogger&& other);
- EventLogger(int value);
- ~EventLogger();
- EventLogger& operator=(const EventLogger& other);
- EventLogger& operator=(EventLogger&& other);
- EventLogger& operator=(int value);
- void Reference() &;
- void Reference() const&;
- void Reference() &&;
- void Reference() const&&;
- int Value = 0;
- };
- #define ASSERT_TRUE(x) \
- do { \
- if (!(x)) { \
- std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
- return false; \
- } \
- } while (false)
- // Certain builds of GCC generate false -Wmaybe-uninitialized warnings when
- // doing a release build with the system version of std::optional. These
- // warnings do not manifest when using our own cm::optional implementation.
- // Silence these false warnings.
- #if defined(__GNUC__) && !defined(__clang__)
- # define BEGIN_IGNORE_UNINITIALIZED \
- _Pragma("GCC diagnostic push") \
- _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
- # define END_IGNORE_UNINITIALIZED _Pragma("GCC diagnostic pop")
- #else
- # define BEGIN_IGNORE_UNINITIALIZED
- # define END_IGNORE_UNINITIALIZED
- #endif
- void swap(EventLogger& e1, EventLogger& e2)
- {
- BEGIN_IGNORE_UNINITIALIZED
- events.push_back({ Event::SWAP, &e1, &e2, e2.Value });
- END_IGNORE_UNINITIALIZED
- auto tmp = e1.Value;
- e1.Value = e2.Value;
- e2.Value = tmp;
- }
- EventLogger::EventLogger()
- : Value(0)
- {
- events.push_back({ Event::DEFAULT_CONSTRUCT, this, nullptr, 0 });
- }
- EventLogger::EventLogger(const EventLogger& other)
- : Value(other.Value)
- {
- events.push_back({ Event::COPY_CONSTRUCT, this, &other, other.Value });
- }
- BEGIN_IGNORE_UNINITIALIZED
- EventLogger::EventLogger(EventLogger&& other)
- : Value(other.Value)
- {
- events.push_back({ Event::MOVE_CONSTRUCT, this, &other, other.Value });
- }
- END_IGNORE_UNINITIALIZED
- EventLogger::EventLogger(int value)
- : Value(value)
- {
- events.push_back({ Event::VALUE_CONSTRUCT, this, nullptr, value });
- }
- EventLogger::~EventLogger()
- {
- BEGIN_IGNORE_UNINITIALIZED
- events.push_back({ Event::DESTRUCT, this, nullptr, this->Value });
- END_IGNORE_UNINITIALIZED
- }
- EventLogger& EventLogger::operator=(const EventLogger& other)
- {
- events.push_back({ Event::COPY_ASSIGN, this, &other, other.Value });
- this->Value = other.Value;
- return *this;
- }
- EventLogger& EventLogger::operator=(EventLogger&& other)
- {
- events.push_back({ Event::MOVE_ASSIGN, this, &other, other.Value });
- this->Value = other.Value;
- return *this;
- }
- EventLogger& EventLogger::operator=(int value)
- {
- events.push_back({ Event::VALUE_ASSIGN, this, nullptr, value });
- this->Value = value;
- return *this;
- }
- bool operator==(const EventLogger& lhs, const EventLogger& rhs)
- {
- events.push_back({ Event::COMPARE_EE_EQ, &lhs, &rhs, lhs.Value });
- return lhs.Value == rhs.Value;
- }
- bool operator!=(const EventLogger& lhs, const EventLogger& rhs)
- {
- events.push_back({ Event::COMPARE_EE_NE, &lhs, &rhs, lhs.Value });
- return lhs.Value != rhs.Value;
- }
- bool operator<(const EventLogger& lhs, const EventLogger& rhs)
- {
- events.push_back({ Event::COMPARE_EE_LT, &lhs, &rhs, lhs.Value });
- return lhs.Value < rhs.Value;
- }
- bool operator<=(const EventLogger& lhs, const EventLogger& rhs)
- {
- events.push_back({ Event::COMPARE_EE_LE, &lhs, &rhs, lhs.Value });
- return lhs.Value <= rhs.Value;
- }
- bool operator>(const EventLogger& lhs, const EventLogger& rhs)
- {
- events.push_back({ Event::COMPARE_EE_GT, &lhs, &rhs, lhs.Value });
- return lhs.Value > rhs.Value;
- }
- bool operator>=(const EventLogger& lhs, const EventLogger& rhs)
- {
- events.push_back({ Event::COMPARE_EE_GE, &lhs, &rhs, lhs.Value });
- return lhs.Value >= rhs.Value;
- }
- void EventLogger::Reference() &
- {
- events.push_back({ Event::REFERENCE, this, nullptr, this->Value });
- }
- void EventLogger::Reference() const&
- {
- events.push_back({ Event::CONST_REFERENCE, this, nullptr, this->Value });
- }
- void EventLogger::Reference() &&
- {
- events.push_back({ Event::RVALUE_REFERENCE, this, nullptr, this->Value });
- }
- void EventLogger::Reference() const&&
- {
- events.push_back(
- { Event::CONST_RVALUE_REFERENCE, this, nullptr, this->Value });
- }
- static bool testDefaultConstruct(std::vector<Event>& expected)
- {
- const cm::optional<EventLogger> o{};
- expected = {};
- return true;
- }
- static bool testNulloptConstruct(std::vector<Event>& expected)
- {
- const cm::optional<EventLogger> o{ cm::nullopt };
- expected = {};
- return true;
- }
- static bool testValueConstruct(std::vector<Event>& expected)
- {
- const cm::optional<EventLogger> o{ 4 };
- expected = {
- { Event::VALUE_CONSTRUCT, &*o, nullptr, 4 },
- { Event::DESTRUCT, &*o, nullptr, 4 },
- };
- return true;
- }
- static bool testInPlaceConstruct(std::vector<Event>& expected)
- {
- const cm::optional<EventLogger> o1{ cm::in_place, 4 };
- const cm::optional<EventLogger> o2{ cm::in_place_t{}, 4 };
- expected = {
- { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 },
- { Event::VALUE_CONSTRUCT, &*o2, nullptr, 4 },
- { Event::DESTRUCT, &*o2, nullptr, 4 },
- { Event::DESTRUCT, &*o1, nullptr, 4 },
- };
- return true;
- }
- static bool testCopyConstruct(std::vector<Event>& expected)
- {
- const cm::optional<EventLogger> o1{ 4 };
- const cm::optional<EventLogger> o2{ o1 };
- const cm::optional<EventLogger> o3{};
- const cm::optional<EventLogger> o4{ o3 };
- expected = {
- { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 },
- { Event::COPY_CONSTRUCT, &*o2, &o1.value(), 4 },
- { Event::DESTRUCT, &*o2, nullptr, 4 },
- { Event::DESTRUCT, &*o1, nullptr, 4 },
- };
- return true;
- }
- static bool testMoveConstruct(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{ 4 };
- const cm::optional<EventLogger> o2{ std::move(o1) };
- cm::optional<EventLogger> o3{};
- const cm::optional<EventLogger> o4{ std::move(o3) };
- expected = {
- { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 },
- { Event::MOVE_CONSTRUCT, &*o2, &*o1, 4 },
- { Event::DESTRUCT, &*o2, nullptr, 4 },
- { Event::DESTRUCT, &*o1, nullptr, 4 },
- };
- return true;
- }
- static bool testNulloptAssign(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{ 4 };
- auto const* v1 = &*o1;
- o1 = cm::nullopt;
- cm::optional<EventLogger> o2{};
- o2 = cm::nullopt;
- expected = {
- { Event::VALUE_CONSTRUCT, v1, nullptr, 4 },
- { Event::DESTRUCT, v1, nullptr, 4 },
- };
- return true;
- }
- static bool testCopyAssign(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{};
- const cm::optional<EventLogger> o2{ 4 };
- auto const* v2 = &*o2;
- o1 = o2;
- auto const* v1 = &*o1;
- const cm::optional<EventLogger> o3{ 5 };
- auto const* v3 = &*o3;
- o1 = o3;
- const cm::optional<EventLogger> o4{};
- o1 = o4;
- o1 = o4; // Intentionally duplicated to test assigning an empty optional to
- // an empty optional
- expected = {
- { Event::VALUE_CONSTRUCT, v2, nullptr, 4 },
- { Event::COPY_CONSTRUCT, v1, v2, 4 },
- { Event::VALUE_CONSTRUCT, v3, nullptr, 5 },
- { Event::COPY_ASSIGN, v1, v3, 5 },
- { Event::DESTRUCT, v1, nullptr, 5 },
- { Event::DESTRUCT, v3, nullptr, 5 },
- { Event::DESTRUCT, v2, nullptr, 4 },
- };
- return true;
- }
- static bool testMoveAssign(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{};
- cm::optional<EventLogger> o2{ 4 };
- auto const* v2 = &*o2;
- o1 = std::move(o2);
- auto const* v1 = &*o1;
- cm::optional<EventLogger> o3{ 5 };
- auto const* v3 = &*o3;
- o1 = std::move(o3);
- cm::optional<EventLogger> o4{};
- o1 = std::move(o4);
- expected = {
- { Event::VALUE_CONSTRUCT, v2, nullptr, 4 },
- { Event::MOVE_CONSTRUCT, v1, v2, 4 },
- { Event::VALUE_CONSTRUCT, v3, nullptr, 5 },
- { Event::MOVE_ASSIGN, v1, v3, 5 },
- { Event::DESTRUCT, v1, nullptr, 5 },
- { Event::DESTRUCT, v3, nullptr, 5 },
- { Event::DESTRUCT, v2, nullptr, 4 },
- };
- return true;
- }
- static bool testPointer(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{ 4 };
- const cm::optional<EventLogger> o2{ 5 };
- o1->Reference();
- o2->Reference();
- expected = {
- { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 },
- { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 },
- { Event::REFERENCE, &*o1, nullptr, 4 },
- { Event::CONST_REFERENCE, &*o2, nullptr, 5 },
- { Event::DESTRUCT, &*o2, nullptr, 5 },
- { Event::DESTRUCT, &*o1, nullptr, 4 },
- };
- return true;
- }
- #if !__GNUC__ || __GNUC__ > 4
- # define ALLOW_CONST_RVALUE
- #endif
- static bool testDereference(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{ 4 };
- auto const* v1 = &*o1;
- const cm::optional<EventLogger> o2{ 5 };
- auto const* v2 = &*o2;
- (*o1).Reference();
- (*o2).Reference();
- (*std::move(o1)).Reference();
- #ifdef ALLOW_CONST_RVALUE
- (*std::move(o2)).Reference(); // Broken in GCC 4.9.0. Sigh...
- #endif
- expected = {
- { Event::VALUE_CONSTRUCT, v1, nullptr, 4 },
- { Event::VALUE_CONSTRUCT, v2, nullptr, 5 },
- { Event::REFERENCE, v1, nullptr, 4 },
- { Event::CONST_REFERENCE, v2, nullptr, 5 },
- { Event::RVALUE_REFERENCE, v1, nullptr, 4 },
- #ifdef ALLOW_CONST_RVALUE
- { Event::CONST_RVALUE_REFERENCE, v2, nullptr, 5 },
- #endif
- { Event::DESTRUCT, v2, nullptr, 5 },
- { Event::DESTRUCT, v1, nullptr, 4 },
- };
- return true;
- }
- static bool testHasValue(std::vector<Event>& expected)
- {
- const cm::optional<EventLogger> o1{ 4 };
- const cm::optional<EventLogger> o2{};
- ASSERT_TRUE(o1.has_value());
- ASSERT_TRUE(o1);
- ASSERT_TRUE(!o2.has_value());
- ASSERT_TRUE(!o2);
- expected = {
- { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 },
- { Event::DESTRUCT, &*o1, nullptr, 4 },
- };
- return true;
- }
- static bool testValue(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{ 4 };
- const cm::optional<EventLogger> o2{ 5 };
- cm::optional<EventLogger> o3{};
- const cm::optional<EventLogger> o4{};
- o1.value().Reference();
- o2.value().Reference();
- bool thrown = false;
- try {
- (void)o3.value();
- } catch (cm::bad_optional_access&) {
- thrown = true;
- }
- ASSERT_TRUE(thrown);
- thrown = false;
- try {
- (void)o4.value();
- } catch (cm::bad_optional_access&) {
- thrown = true;
- }
- ASSERT_TRUE(thrown);
- expected = {
- { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 },
- { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 },
- { Event::REFERENCE, &*o1, nullptr, 4 },
- { Event::CONST_REFERENCE, &*o2, nullptr, 5 },
- { Event::DESTRUCT, &*o2, nullptr, 5 },
- { Event::DESTRUCT, &*o1, nullptr, 4 },
- };
- return true;
- }
- static bool testValueOr()
- {
- const cm::optional<EventLogger> o1{ 4 };
- cm::optional<EventLogger> o2{ 5 };
- const cm::optional<EventLogger> o3{};
- cm::optional<EventLogger> o4{};
- EventLogger e1{ 6 };
- EventLogger e2{ 7 };
- EventLogger e3{ 8 };
- EventLogger e4{ 9 };
- EventLogger r1 = o1.value_or(e1);
- ASSERT_TRUE(r1.Value == 4);
- EventLogger r2 = std::move(o2).value_or(e2);
- ASSERT_TRUE(r2.Value == 5);
- EventLogger r3 = o3.value_or(e3);
- ASSERT_TRUE(r3.Value == 8);
- EventLogger r4 = std::move(o4).value_or(e4);
- ASSERT_TRUE(r4.Value == 9);
- return true;
- }
- static bool testComparison(std::vector<Event>& expected)
- {
- const cm::optional<EventLogger> o1{ 1 };
- const cm::optional<EventLogger> o2{ 2 };
- const cm::optional<EventLogger> o3{ 2 };
- const cm::optional<EventLogger> o4{};
- const cm::optional<EventLogger> o5{};
- const EventLogger e1{ 2 };
- ASSERT_TRUE(!(o1 == o2) && o1 != o2);
- ASSERT_TRUE(o1 < o2 && !(o1 >= o2));
- ASSERT_TRUE(!(o1 > o2) && o1 <= o2);
- ASSERT_TRUE(o2 == o3 && !(o2 != o3));
- ASSERT_TRUE(!(o2 < o3) && o2 >= o3);
- ASSERT_TRUE(!(o2 > o3) && o2 <= o3);
- ASSERT_TRUE(!(o3 == o4) && o3 != o4);
- ASSERT_TRUE(!(o3 < o4) && o3 >= o4);
- ASSERT_TRUE(o3 > o4 && !(o3 <= o4));
- ASSERT_TRUE(o4 == o5 && !(o4 != o5));
- ASSERT_TRUE(!(o4 < o5) && o4 >= o5);
- ASSERT_TRUE(!(o4 > o5) && o4 <= o5);
- ASSERT_TRUE(!(o1 == cm::nullopt) && o1 != cm::nullopt);
- ASSERT_TRUE(!(o1 < cm::nullopt) && o1 >= cm::nullopt);
- ASSERT_TRUE(o1 > cm::nullopt && !(o1 <= cm::nullopt));
- ASSERT_TRUE(!(cm::nullopt == o1) && cm::nullopt != o1);
- ASSERT_TRUE(cm::nullopt < o1 && !(cm::nullopt >= o1));
- ASSERT_TRUE(!(cm::nullopt > o1) && cm::nullopt <= o1);
- ASSERT_TRUE(o4 == cm::nullopt && !(o4 != cm::nullopt));
- ASSERT_TRUE(!(o4 < cm::nullopt) && o4 >= cm::nullopt);
- ASSERT_TRUE(!(o4 > cm::nullopt) && o4 <= cm::nullopt);
- ASSERT_TRUE(cm::nullopt == o4 && !(cm::nullopt != o4));
- ASSERT_TRUE(!(cm::nullopt < o4) && cm::nullopt >= o4);
- ASSERT_TRUE(!(cm::nullopt > o4) && cm::nullopt <= o4);
- ASSERT_TRUE(!(o1 == e1) && o1 != e1);
- ASSERT_TRUE(o1 < e1 && !(o1 >= e1));
- ASSERT_TRUE(!(o1 > e1) && o1 <= e1);
- ASSERT_TRUE(o2 == e1 && !(o2 != e1));
- ASSERT_TRUE(!(o2 < e1) && o2 >= e1);
- ASSERT_TRUE(!(o2 > e1) && o2 <= e1);
- ASSERT_TRUE(!(o4 == e1) && o4 != e1);
- ASSERT_TRUE(o4 < e1 && !(o4 >= e1));
- ASSERT_TRUE(!(o4 > e1) && o4 <= e1);
- ASSERT_TRUE(!(e1 == o1) && e1 != o1);
- ASSERT_TRUE(!(e1 < o1) && e1 >= o1);
- ASSERT_TRUE(e1 > o1 && !(e1 <= o1));
- ASSERT_TRUE(e1 == o2 && !(e1 != o2));
- ASSERT_TRUE(!(e1 < o2) && e1 >= o2);
- ASSERT_TRUE(!(e1 > o2) && e1 <= o2);
- ASSERT_TRUE(!(e1 == o4) && e1 != o4);
- ASSERT_TRUE(!(e1 < o4) && e1 >= o4);
- ASSERT_TRUE(e1 > o4 && !(e1 <= o4));
- expected = {
- { Event::VALUE_CONSTRUCT, &*o1, nullptr, 1 },
- { Event::VALUE_CONSTRUCT, &*o2, nullptr, 2 },
- { Event::VALUE_CONSTRUCT, &*o3, nullptr, 2 },
- { Event::VALUE_CONSTRUCT, &e1, nullptr, 2 },
- { Event::COMPARE_EE_EQ, &*o1, &*o2, 1 },
- { Event::COMPARE_EE_NE, &*o1, &*o2, 1 },
- { Event::COMPARE_EE_LT, &*o1, &*o2, 1 },
- { Event::COMPARE_EE_GE, &*o1, &*o2, 1 },
- { Event::COMPARE_EE_GT, &*o1, &*o2, 1 },
- { Event::COMPARE_EE_LE, &*o1, &*o2, 1 },
- { Event::COMPARE_EE_EQ, &*o2, &*o3, 2 },
- { Event::COMPARE_EE_NE, &*o2, &*o3, 2 },
- { Event::COMPARE_EE_LT, &*o2, &*o3, 2 },
- { Event::COMPARE_EE_GE, &*o2, &*o3, 2 },
- { Event::COMPARE_EE_GT, &*o2, &*o3, 2 },
- { Event::COMPARE_EE_LE, &*o2, &*o3, 2 },
- { Event::COMPARE_EE_EQ, &*o1, &e1, 1 },
- { Event::COMPARE_EE_NE, &*o1, &e1, 1 },
- { Event::COMPARE_EE_LT, &*o1, &e1, 1 },
- { Event::COMPARE_EE_GE, &*o1, &e1, 1 },
- { Event::COMPARE_EE_GT, &*o1, &e1, 1 },
- { Event::COMPARE_EE_LE, &*o1, &e1, 1 },
- { Event::COMPARE_EE_EQ, &*o2, &e1, 2 },
- { Event::COMPARE_EE_NE, &*o2, &e1, 2 },
- { Event::COMPARE_EE_LT, &*o2, &e1, 2 },
- { Event::COMPARE_EE_GE, &*o2, &e1, 2 },
- { Event::COMPARE_EE_GT, &*o2, &e1, 2 },
- { Event::COMPARE_EE_LE, &*o2, &e1, 2 },
- { Event::COMPARE_EE_EQ, &e1, &*o1, 2 },
- { Event::COMPARE_EE_NE, &e1, &*o1, 2 },
- { Event::COMPARE_EE_LT, &e1, &*o1, 2 },
- { Event::COMPARE_EE_GE, &e1, &*o1, 2 },
- { Event::COMPARE_EE_GT, &e1, &*o1, 2 },
- { Event::COMPARE_EE_LE, &e1, &*o1, 2 },
- { Event::COMPARE_EE_EQ, &e1, &*o2, 2 },
- { Event::COMPARE_EE_NE, &e1, &*o2, 2 },
- { Event::COMPARE_EE_LT, &e1, &*o2, 2 },
- { Event::COMPARE_EE_GE, &e1, &*o2, 2 },
- { Event::COMPARE_EE_GT, &e1, &*o2, 2 },
- { Event::COMPARE_EE_LE, &e1, &*o2, 2 },
- { Event::DESTRUCT, &e1, nullptr, 2 },
- { Event::DESTRUCT, &*o3, nullptr, 2 },
- { Event::DESTRUCT, &*o2, nullptr, 2 },
- { Event::DESTRUCT, &*o1, nullptr, 1 },
- };
- return true;
- }
- static bool testSwap(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o1{ 4 };
- auto const* v1 = &*o1;
- cm::optional<EventLogger> o2{};
- o1.swap(o2);
- auto const* v2 = &*o2;
- ASSERT_TRUE(!o1.has_value());
- ASSERT_TRUE(o2.has_value());
- ASSERT_TRUE(o2.value().Value == 4);
- o1.swap(o2);
- ASSERT_TRUE(o1.has_value());
- ASSERT_TRUE(o1.value().Value == 4);
- ASSERT_TRUE(!o2.has_value());
- o2.emplace(5);
- o1.swap(o2);
- ASSERT_TRUE(o1.has_value());
- ASSERT_TRUE(o1.value().Value == 5);
- ASSERT_TRUE(o2.has_value());
- ASSERT_TRUE(o2.value().Value == 4);
- o1.reset();
- o2.reset();
- o1.swap(o2);
- ASSERT_TRUE(!o1.has_value());
- ASSERT_TRUE(!o2.has_value());
- expected = {
- { Event::VALUE_CONSTRUCT, v1, nullptr, 4 },
- { Event::MOVE_CONSTRUCT, v2, v1, 4 },
- { Event::DESTRUCT, v1, nullptr, 4 },
- { Event::MOVE_CONSTRUCT, v1, v2, 4 },
- { Event::DESTRUCT, v2, nullptr, 4 },
- { Event::VALUE_CONSTRUCT, v2, nullptr, 5 },
- { Event::SWAP, v1, v2, 5 },
- { Event::DESTRUCT, v1, nullptr, 5 },
- { Event::DESTRUCT, v2, nullptr, 4 },
- };
- return true;
- }
- static bool testReset(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o{ 4 };
- auto const* v = &*o;
- o.reset();
- ASSERT_TRUE(!o.has_value());
- o.reset();
- expected = {
- { Event::VALUE_CONSTRUCT, v, nullptr, 4 },
- { Event::DESTRUCT, v, nullptr, 4 },
- };
- return true;
- }
- static bool testEmplace(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o{ 4 };
- o.emplace(5);
- o.reset();
- o.emplace();
- expected = {
- { Event::VALUE_CONSTRUCT, &*o, nullptr, 4 },
- { Event::DESTRUCT, &*o, nullptr, 4 },
- { Event::VALUE_CONSTRUCT, &*o, nullptr, 5 },
- { Event::DESTRUCT, &*o, nullptr, 5 },
- { Event::DEFAULT_CONSTRUCT, &*o, nullptr, 0 },
- { Event::DESTRUCT, &*o, nullptr, 0 },
- };
- return true;
- }
- static bool testMakeOptional(std::vector<Event>& expected)
- {
- EventLogger e{ 4 };
- cm::optional<EventLogger> o1 = cm::make_optional<EventLogger>(e);
- cm::optional<EventLogger> o2 = cm::make_optional<EventLogger>(5);
- expected = {
- { Event::VALUE_CONSTRUCT, &e, nullptr, 4 },
- { Event::COPY_CONSTRUCT, &*o1, &e, 4 },
- { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 },
- { Event::DESTRUCT, &*o2, nullptr, 5 },
- { Event::DESTRUCT, &*o1, nullptr, 4 },
- { Event::DESTRUCT, &e, nullptr, 4 },
- };
- return true;
- }
- static bool testMemoryRange(std::vector<Event>& expected)
- {
- cm::optional<EventLogger> o{ 4 };
- auto* ostart = &o;
- auto* oend = ostart + 1;
- auto* estart = &o.value();
- auto* eend = estart + 1;
- ASSERT_TRUE(static_cast<void*>(estart) >= static_cast<void*>(ostart) &&
- static_cast<void*>(eend) <= static_cast<void*>(oend));
- expected = {
- { Event::VALUE_CONSTRUCT, &*o, nullptr, 4 },
- { Event::DESTRUCT, &*o, nullptr, 4 },
- };
- return true;
- }
- int testOptional(int /*unused*/, char* /*unused*/ [])
- {
- int retval = 0;
- #define DO_EVENT_TEST(name) \
- do { \
- events.clear(); \
- std::vector<Event> expected; \
- if (!name(expected)) { \
- std::cout << "in " #name << std::endl; \
- retval = 1; \
- } else if (expected != events) { \
- std::cout << #name " did not produce expected events" << std::endl; \
- retval = 1; \
- } \
- } while (0)
- #define DO_TEST(name) \
- do { \
- if (!name()) { \
- std::cout << "in " #name << std::endl; \
- retval = 1; \
- } \
- } while (0)
- DO_EVENT_TEST(testDefaultConstruct);
- DO_EVENT_TEST(testNulloptConstruct);
- DO_EVENT_TEST(testValueConstruct);
- DO_EVENT_TEST(testInPlaceConstruct);
- DO_EVENT_TEST(testCopyConstruct);
- DO_EVENT_TEST(testMoveConstruct);
- DO_EVENT_TEST(testNulloptAssign);
- DO_EVENT_TEST(testCopyAssign);
- DO_EVENT_TEST(testMoveAssign);
- DO_EVENT_TEST(testPointer);
- DO_EVENT_TEST(testDereference);
- DO_EVENT_TEST(testHasValue);
- DO_EVENT_TEST(testValue);
- DO_TEST(testValueOr);
- DO_EVENT_TEST(testComparison);
- DO_EVENT_TEST(testSwap);
- DO_EVENT_TEST(testReset);
- DO_EVENT_TEST(testEmplace);
- DO_EVENT_TEST(testMakeOptional);
- DO_EVENT_TEST(testMemoryRange);
- return retval;
- }
|