From 5832ba80c3c4417428eb1adcd77d326bb49b3548 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Wed, 12 Jun 2024 10:23:22 +0300 Subject: [PATCH 01/20] Apply P3168R1 wording --- include/Beman/Optional26/optional.hpp | 55 +++++++++++---------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index 3b8d0f0f..0b6df829 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -165,10 +165,11 @@ namespace std { */ #include -#include +#include #include -#include #include +#include +#include namespace beman::optional { @@ -202,7 +203,9 @@ template class optional; } // namespace beman::optional + namespace std { +// Since P3168R1: Give std::optional Range Support. template inline constexpr bool ranges::enable_view> = true; @@ -218,6 +221,10 @@ inline constexpr bool ranges::enable_borrowed_range inline constexpr bool ranges::enable_borrowed_range> = true; +// Since P3168R1: Give std::optional Range Support. +// template +// inline constexpr auto format_kind> = range_format::disabled; + } // namespace std namespace beman::optional { @@ -309,6 +316,11 @@ class optional { } public: + using value_type = T; + // Since P3168R1: Give std::optional Range Support. + using iterator = T*; // see [optional.iterators] + using const_iterator = const T*; // see [optional.iterators] + constexpr optional() noexcept requires std::is_default_constructible_v = default; @@ -675,6 +687,13 @@ class optional { swap(engaged, rhs.engaged); } + // Since P3168R1: Give std::optional Range Support. + // [optional.iterators], iterator support + constexpr iterator begin() noexcept { return has_value() ? std::addressof(value_) : nullptr; }; + constexpr const_iterator begin() const noexcept { return has_value() ? std::addressof(value_) : nullptr; }; + constexpr iterator end() noexcept { return begin() + has_value(); } + constexpr const_iterator end() const noexcept { return begin() + has_value(); } + /// Returns a pointer to the stored value constexpr const T* operator->() const { return std::addressof(value_); } @@ -699,36 +718,6 @@ class optional { } engaged = false; } - using iterator = T*; - using const_iterator = const T*; - - // [optional.iterators], iterator support - constexpr T* begin() noexcept { - if (has_value()) { - return std::addressof(value_); - } else { - return nullptr; - } - } - constexpr const T* begin() const noexcept { - if (has_value()) { - return std::addressof(value_); - } else { - return nullptr; - } - } - constexpr T* end() noexcept { return begin() + has_value(); } - constexpr const T* end() const noexcept { return begin() + has_value(); } - - constexpr std::reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - constexpr std::reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } - constexpr std::reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - constexpr std::reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } - - constexpr const T* cbegin() const noexcept { return begin(); } - constexpr const T* cend() const noexcept { return end(); } - constexpr std::reverse_iterator crbegin() const noexcept { return rbegin(); } - constexpr std::reverse_iterator crend() const noexcept { return rend(); } }; template @@ -1120,6 +1109,8 @@ class optional { } constexpr void reset() noexcept { value_ = nullptr; } + + // TODO: mirror changes from optional here. using iterator = T*; using const_iterator = const T*; From d4c86e9b37afaad724841a62f1268182373dc029 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Wed, 12 Jun 2024 10:30:00 +0300 Subject: [PATCH 02/20] Apply P3168R1 wording also for optional --- include/Beman/Optional26/optional.hpp | 50 +++++++++------------------ 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index 0b6df829..3ae72598 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -222,7 +222,7 @@ template inline constexpr bool ranges::enable_borrowed_range> = true; // Since P3168R1: Give std::optional Range Support. -// template +// template // inline constexpr auto format_kind> = range_format::disabled; } // namespace std @@ -936,6 +936,12 @@ template class optional { public: using value_type = T&; + // Since ${PAPER_NUMBER}: ${PAPER_TITLE}. + // Note: P3168 and P2988 may have different flows inside LEWG/LWG. + // Implementation of the range support for optional reflects P3168R1 for now. + // [optional.iterators], iterator support + using iterator = T*; // see [optional.iterators] + using const_iterator = const T*; // see [optional.iterators] // [optional.ctor], constructors // constexpr optional() noexcept; @@ -1065,6 +1071,15 @@ class optional { constexpr void swap(optional& rhs) noexcept { std::swap(value_, rhs.value_); } + // Since ${PAPER_NUMBER}: ${PAPER_TITLE}. + // Note: P3168 and P2988 may have different flows inside LEWG/LWG. + // Implementation of the range support for optional reflects P3168R1 for now. + // [optional.iterators], iterator support + constexpr iterator begin() noexcept { return has_value() ? value_ : nullptr; }; + constexpr const_iterator begin() const noexcept { return has_value() ? value_ : nullptr; }; + constexpr iterator end() noexcept { return begin() + has_value(); } + constexpr const_iterator end() const noexcept { return begin() + has_value(); } + // \rSec3[optional.observe]{Observers} constexpr T* operator->() const noexcept { return value_; } @@ -1109,39 +1124,6 @@ class optional { } constexpr void reset() noexcept { value_ = nullptr; } - - // TODO: mirror changes from optional here. - using iterator = T*; - using const_iterator = const T*; - - // [optional.iterators], iterator support - constexpr T* begin() noexcept { - if (has_value()) { - return value_; - } else { - return nullptr; - } - } - constexpr const T* begin() const noexcept { - if (has_value()) { - return value_; - } else { - return nullptr; - } - } - constexpr T* end() noexcept { return begin() + has_value(); } - - constexpr const T* end() const noexcept { return begin() + has_value(); } - - constexpr std::reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - constexpr std::reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } - constexpr std::reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - constexpr std::reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } - - constexpr const T* cbegin() const noexcept { return begin(); } - constexpr const T* cend() const noexcept { return end(); } - constexpr std::reverse_iterator crbegin() const noexcept { return rbegin(); } - constexpr std::reverse_iterator crend() const noexcept { return rend(); } }; } // namespace beman::optional #endif From 419703c6407b9860418704eeefd94a69610cad15 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Thu, 13 Jun 2024 13:17:01 +0300 Subject: [PATCH 03/20] Move tests to src/beman/optional/tests --- src/Beman/optional/CMakeLists.txt | 9 +- src/Beman/optional/tests/optional.t.cpp | 1278 +++++++++++++++++ .../optional/tests/optional_monadic.t.cpp | 311 ++++ .../tests/optional_range_support.t.cpp | 9 + src/Beman/optional/tests/optional_ref.t.cpp | 560 ++++++++ .../optional/tests/optional_ref_monadic.t.cpp | 318 ++++ src/beman/optional/optional.t.cpp | 1278 +++++++++++++++++ src/beman/optional/optional_monadic.t.cpp | 311 ++++ src/beman/optional/optional_ref.t.cpp | 560 ++++++++ src/beman/optional/optional_ref_monadic.t.cpp | 318 ++++ src/beman/optional/tests/optional.t.cpp | 1278 +++++++++++++++++ .../optional/tests/optional_monadic.t.cpp | 311 ++++ .../tests/optional_range_support.t.cpp | 9 + src/beman/optional/tests/optional_ref.t.cpp | 560 ++++++++ .../optional/tests/optional_ref_monadic.t.cpp | 318 ++++ 15 files changed, 7424 insertions(+), 4 deletions(-) create mode 100644 src/Beman/optional/tests/optional.t.cpp create mode 100644 src/Beman/optional/tests/optional_monadic.t.cpp create mode 100644 src/Beman/optional/tests/optional_range_support.t.cpp create mode 100644 src/Beman/optional/tests/optional_ref.t.cpp create mode 100644 src/Beman/optional/tests/optional_ref_monadic.t.cpp create mode 100644 src/beman/optional/optional.t.cpp create mode 100644 src/beman/optional/optional_monadic.t.cpp create mode 100644 src/beman/optional/optional_ref.t.cpp create mode 100644 src/beman/optional/optional_ref_monadic.t.cpp create mode 100644 src/beman/optional/tests/optional.t.cpp create mode 100644 src/beman/optional/tests/optional_monadic.t.cpp create mode 100644 src/beman/optional/tests/optional_range_support.t.cpp create mode 100644 src/beman/optional/tests/optional_ref.t.cpp create mode 100644 src/beman/optional/tests/optional_ref_monadic.t.cpp diff --git a/src/Beman/optional/CMakeLists.txt b/src/Beman/optional/CMakeLists.txt index 9ca5065e..82942f2a 100644 --- a/src/Beman/optional/CMakeLists.txt +++ b/src/Beman/optional/CMakeLists.txt @@ -37,10 +37,11 @@ add_executable(optional_test "") target_sources( optional_test PRIVATE - optional.t.cpp - optional_ref.t.cpp - optional_monadic.t.cpp - optional_ref_monadic.t.cpp + tests/optional.t.cpp + tests/optional_ref.t.cpp + tests/optional_monadic.t.cpp + tests/optional_range_support.t.cpp + tests/optional_ref_monadic.t.cpp ) target_link_libraries(optional_test "${TARGET_LIBRARY}") diff --git a/src/Beman/optional/tests/optional.t.cpp b/src/Beman/optional/tests/optional.t.cpp new file mode 100644 index 00000000..9da8715d --- /dev/null +++ b/src/Beman/optional/tests/optional.t.cpp @@ -0,0 +1,1278 @@ +#include + +#include // test 2nd include OK + +#include +#include +#include + +#include + +TEST(OptionalTest, TestGTest) { ASSERT_EQ(1, 1); } + +namespace { +struct empty {}; +struct no_default { + no_default() = delete; + no_default(const no_default&) = default; + no_default(no_default&&) = default; + no_default& operator=(const no_default&) = default; + no_default& operator=(no_default&&) = default; + no_default(empty){}; +}; + +struct base { + int i_; + base() : i_(0) {} + base(int i) : i_(i) {} +}; + +struct derived : public base { + int j_; + derived() : base(0), j_(0) {} + derived(int i, int j) : base(i), j_(j) {} +}; +} // namespace + +TEST(OptionalTest, Constructors) { + beman::optional::optional i1; + beman::optional::optional i2{beman::optional::nullopt}; + + int i = 0; + beman::optional::optional i3 = i; + (void)i3; + + beman::optional::optional e1; + beman::optional::optional e2{beman::optional::nullopt}; + + empty e{}; + beman::optional::optional e3 = e; + (void)e3; +} + + +TEST(OptionalTest, Constructors2) { + beman::optional::optional o1; + EXPECT_TRUE(!o1); + + beman::optional::optional o2 = beman::optional::nullopt; + EXPECT_TRUE(!o2); + + beman::optional::optional o3 = 42; + EXPECT_TRUE(*o3 == 42); + + beman::optional::optional o4 = o3; + EXPECT_TRUE(*o4 == 42); + + beman::optional::optional o5 = o1; + EXPECT_TRUE(!o5); + + beman::optional::optional o6 = std::move(o3); + EXPECT_TRUE(*o6 == 42); + + beman::optional::optional o7 = 42; + EXPECT_TRUE(*o7 == 42); + + beman::optional::optional o8 = o7; + EXPECT_TRUE(*o8 == 42); + + beman::optional::optional o9 = std::move(o7); + EXPECT_TRUE(*o9 == 42); + + { + beman::optional::optional o; + EXPECT_TRUE(!o); + + beman::optional::optional oo = o; + EXPECT_TRUE(!oo); + } + + { + auto i = 42; + beman::optional::optional o = i; + EXPECT_TRUE(o); + EXPECT_TRUE(*o == 42); + + beman::optional::optional oo = o; + EXPECT_TRUE(oo); + EXPECT_TRUE(*oo == 42); + } + + std::vector v; + v.emplace_back(); + beman::optional::optional> ov = std::move(v); + EXPECT_TRUE(ov->size() == 1); +} + +TEST(OptionalTest, Constructors3) { + beman::optional::optional ie; + beman::optional::optional i4 = ie; + EXPECT_FALSE(i4); + + base b{1}; + derived d(1, 2); + beman::optional::optional b1{b}; + beman::optional::optional b2{d}; + + beman::optional::optional d2{d}; + beman::optional::optional b3 = d2; + beman::optional::optional b4{d2}; +} + +namespace { +class NoDefault { + int v_; + + public: + NoDefault(int v) : v_(v) {} +}; +} // namespace + +TEST(OptionalTest, NonDefaultConstruct) { + NoDefault i = 7; + beman::optional::optional v1{}; + beman::optional::optional v2{i}; +} + +TEST(OptionalTest, AssignmentValue) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = 12; + beman::optional::optional o3; + + o1 = o1; + EXPECT_TRUE(*o1 == 42); + + o1 = o2; + EXPECT_TRUE(*o1 == 12); + + o1 = o3; + EXPECT_TRUE(!o1); + + o1 = 42; + EXPECT_TRUE(*o1 == 42); + + o1 = beman::optional::nullopt; + EXPECT_TRUE(!o1); + + o1 = std::move(o2); + EXPECT_TRUE(*o1 == 12); + + beman::optional::optional o4 = 42; + + o1 = o4; + EXPECT_TRUE(*o1 == 42); + + o1 = std::move(o4); + EXPECT_TRUE(*o1 == 42); +} + +TEST(OptionalTest, Triviality) { + EXPECT_TRUE(std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE( + std::is_trivially_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE( + std::is_trivially_destructible>::value); + } + + { + struct T { + T(const T&) {} + T(T&&){}; + T& operator=(const T&) { return *this; } + T& operator=(T&&) { return *this; }; + ~T() {} + }; + EXPECT_TRUE(!std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_destructible< + beman::optional::optional>::value); + } +} + +TEST(OptionalTest, Deletion) { + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE( + std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE( + std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = delete; + T& operator=(const T&) = delete; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE( + !std::is_copy_constructible>::value); + EXPECT_TRUE( + !std::is_copy_assignable>::value); + EXPECT_TRUE( + !std::is_move_constructible>::value); + EXPECT_TRUE( + !std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = default; + T& operator=(const T&) = delete; + T& operator=(T&&) = default; + }; + EXPECT_TRUE( + !std::is_copy_constructible>::value); + EXPECT_TRUE( + !std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE( + std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = default; + T(T&&) = delete; + T& operator=(const T&) = default; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE( + std::is_copy_assignable>::value); + } +} + +struct takes_init_and_variadic { + std::vector v; + std::tuple t; + template + takes_init_and_variadic(std::initializer_list l, Args&&... args) + : v(l), t(std::forward(args)...) {} +}; + +TEST(OptionalTest, InPlace) { + beman::optional::optional o1{beman::optional::in_place}; + beman::optional::optional o2(beman::optional::in_place); + EXPECT_TRUE(o1); + EXPECT_TRUE(o1 == 0); + EXPECT_TRUE(o2); + EXPECT_TRUE(o2 == 0); + + beman::optional::optional o3(beman::optional::in_place, 42); + EXPECT_TRUE(o3 == 42); + + beman::optional::optional> o4( + beman::optional::in_place, 0, 1); + EXPECT_TRUE(o4); + EXPECT_TRUE(std::get<0>(*o4) == 0); + EXPECT_TRUE(std::get<1>(*o4) == 1); + + beman::optional::optional> o5(beman::optional::in_place, + {0, 1}); + EXPECT_TRUE(o5); + EXPECT_TRUE((*o5)[0] == 0); + EXPECT_TRUE((*o5)[1] == 1); + + beman::optional::optional o6( + beman::optional::in_place, {0, 1}, 2, 3); + EXPECT_TRUE(o6->v[0] == 0); + EXPECT_TRUE(o6->v[1] == 1); + EXPECT_TRUE(std::get<0>(o6->t) == 2); + EXPECT_TRUE(std::get<1>(o6->t) == 3); +} + +TEST(OptionalTest, MakeOptional) { + auto o1 = beman::optional::make_optional(42); + auto o2 = beman::optional::optional(42); + + constexpr bool is_same = + std::is_same>::value; + EXPECT_TRUE(is_same); + EXPECT_TRUE(o1 == o2); + + auto o3 = beman::optional::make_optional>( + 0, 1, 2, 3); + EXPECT_TRUE(std::get<0>(*o3) == 0); + EXPECT_TRUE(std::get<1>(*o3) == 1); + EXPECT_TRUE(std::get<2>(*o3) == 2); + EXPECT_TRUE(std::get<3>(*o3) == 3); + + auto o4 = beman::optional::make_optional>({0, 1, 2, 3}); + EXPECT_TRUE(o4.value()[0] == 0); + EXPECT_TRUE(o4.value()[1] == 1); + EXPECT_TRUE(o4.value()[2] == 2); + EXPECT_TRUE(o4.value()[3] == 3); + + auto o5 = + beman::optional::make_optional({0, 1}, 2, 3); + EXPECT_TRUE(o5->v[0] == 0); + EXPECT_TRUE(o5->v[1] == 1); + EXPECT_TRUE(std::get<0>(o5->t) == 2); + EXPECT_TRUE(std::get<1>(o5->t) == 3); + + auto i = 42; + auto o6 = beman::optional::make_optional(i); + static_assert(std::is_same>::value); + + EXPECT_TRUE( + (std::is_same>::value)); + EXPECT_TRUE(o6); + EXPECT_TRUE(*o6 == 42); +} + +TEST(OptionalTest, Nullopt) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2{beman::optional::nullopt}; + beman::optional::optional o3(beman::optional::nullopt); + beman::optional::optional o4 = {beman::optional::nullopt}; + + EXPECT_TRUE(!o1); + EXPECT_TRUE(!o2); + EXPECT_TRUE(!o3); + EXPECT_TRUE(!o4); + + EXPECT_TRUE( + !std::is_default_constructible::value); +} + +struct move_detector { + move_detector() = default; + move_detector(move_detector&& rhs) { rhs.been_moved = true; } + bool been_moved = false; +}; + +TEST(OptionalTest, Observers) { + beman::optional::optional o1 = 42; + beman::optional::optional o2; + const beman::optional::optional o3 = 42; + + EXPECT_TRUE(*o1 == 42); + EXPECT_TRUE(*o1 == o1.value()); + EXPECT_TRUE(o2.value_or(42) == 42); + EXPECT_TRUE(o3.value() == 42); + auto success = std::is_same::value; + EXPECT_TRUE(success); + success = std::is_same::value; + EXPECT_TRUE(success); + success = std::is_same::value; + EXPECT_TRUE(success); + + beman::optional::optional o4{beman::optional::in_place}; + move_detector o5 = std::move(o4).value(); + EXPECT_TRUE(o4->been_moved); + EXPECT_TRUE(!o5.been_moved); +} + +TEST(OptionalTest, RelationalOps) { + beman::optional::optional o1{4}; + beman::optional::optional o2{42}; + beman::optional::optional o3{}; + + // SECTION("self simple") + { + EXPECT_TRUE(!(o1 == o2)); + EXPECT_TRUE(o1 == o1); + EXPECT_TRUE(o1 != o2); + EXPECT_TRUE(!(o1 != o1)); + EXPECT_TRUE(o1 < o2); + EXPECT_TRUE(!(o1 < o1)); + EXPECT_TRUE(!(o1 > o2)); + EXPECT_TRUE(!(o1 > o1)); + EXPECT_TRUE(o1 <= o2); + EXPECT_TRUE(o1 <= o1); + EXPECT_TRUE(!(o1 >= o2)); + EXPECT_TRUE(o1 >= o1); + } + // SECTION("nullopt simple") + { + EXPECT_TRUE(!(o1 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o1)); + EXPECT_TRUE(o1 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o1); + EXPECT_TRUE(!(o1 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o1); + EXPECT_TRUE(o1 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o1)); + EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o1); + EXPECT_TRUE(o1 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o1)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + // SECTION("with T simple") + { + EXPECT_TRUE(!(o1 == 1)); + EXPECT_TRUE(!(1 == o1)); + EXPECT_TRUE(o1 != 1); + EXPECT_TRUE(1 != o1); + EXPECT_TRUE(!(o1 < 1)); + EXPECT_TRUE(1 < o1); + EXPECT_TRUE(o1 > 1); + EXPECT_TRUE(!(1 > o1)); + EXPECT_TRUE(!(o1 <= 1)); + EXPECT_TRUE(1 <= o1); + EXPECT_TRUE(o1 >= 1); + EXPECT_TRUE(!(1 >= o1)); + + EXPECT_TRUE(o1 == 4); + EXPECT_TRUE(4 == o1); + EXPECT_TRUE(!(o1 != 4)); + EXPECT_TRUE(!(4 != o1)); + EXPECT_TRUE(!(o1 < 4)); + EXPECT_TRUE(!(4 < o1)); + EXPECT_TRUE(!(o1 > 4)); + EXPECT_TRUE(!(4 > o1)); + EXPECT_TRUE(o1 <= 4); + EXPECT_TRUE(4 <= o1); + EXPECT_TRUE(o1 >= 4); + EXPECT_TRUE(4 >= o1); + } + beman::optional::optional o4{"hello"}; + beman::optional::optional o5{"xyz"}; + + // SECTION("self complex") + { + EXPECT_TRUE(!(o4 == o5)); + EXPECT_TRUE(o4 == o4); + EXPECT_TRUE(o4 != o5); + EXPECT_TRUE(!(o4 != o4)); + EXPECT_TRUE(o4 < o5); + EXPECT_TRUE(!(o4 < o4)); + EXPECT_TRUE(!(o4 > o5)); + EXPECT_TRUE(!(o4 > o4)); + EXPECT_TRUE(o4 <= o5); + EXPECT_TRUE(o4 <= o4); + EXPECT_TRUE(!(o4 >= o5)); + EXPECT_TRUE(o4 >= o4); + } + // SECTION("nullopt complex") + { + EXPECT_TRUE(!(o4 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o4)); + EXPECT_TRUE(o4 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o4); + EXPECT_TRUE(!(o4 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o4); + EXPECT_TRUE(o4 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o4)); + EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o4); + EXPECT_TRUE(o4 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o4)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + + // SECTION("with T complex") + { + EXPECT_TRUE(!(o4 == "a")); + EXPECT_TRUE(!("a" == o4)); + EXPECT_TRUE(o4 != "a"); + EXPECT_TRUE("a" != o4); + EXPECT_TRUE(!(o4 < "a")); + EXPECT_TRUE("a" < o4); + EXPECT_TRUE(o4 > "a"); + EXPECT_TRUE(!("a" > o4)); + EXPECT_TRUE(!(o4 <= "a")); + EXPECT_TRUE("a" <= o4); + EXPECT_TRUE(o4 >= "a"); + EXPECT_TRUE(!("a" >= o4)); + + EXPECT_TRUE(o4 == "hello"); + EXPECT_TRUE("hello" == o4); + EXPECT_TRUE(!(o4 != "hello")); + EXPECT_TRUE(!("hello" != o4)); + EXPECT_TRUE(!(o4 < "hello")); + EXPECT_TRUE(!("hello" < o4)); + EXPECT_TRUE(!(o4 > "hello")); + EXPECT_TRUE(!("hello" > o4)); + EXPECT_TRUE(o4 <= "hello"); + EXPECT_TRUE("hello" <= o4); + EXPECT_TRUE(o4 >= "hello"); + EXPECT_TRUE("hello" >= o4); + } +} + +TEST(OptionalTest, SwapValue) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = 12; + o1.swap(o2); + EXPECT_EQ(o1.value(), 12); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalTest, SwapWNull) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = beman::optional::nullopt; + o1.swap(o2); + EXPECT_TRUE(!o1.has_value()); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalTest, SwapNullIntializedWithValue) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = 42; + o1.swap(o2); + EXPECT_EQ(o1.value(), 42); + EXPECT_TRUE(!o2.has_value()); +} + +TEST(OptionalTest, Emplace) { + beman::optional::optional< + std::pair, std::pair>> + i; + i.emplace(std::piecewise_construct, + std::make_tuple(0, 2), + std::make_tuple(3, 4)); + EXPECT_TRUE(i->first.first == 0); + EXPECT_TRUE(i->first.second == 2); + EXPECT_TRUE(i->second.first == 3); + EXPECT_TRUE(i->second.second == 4); +} + +struct A { + A() { throw std::exception(); } +}; + +TEST(OptionalTest, EmplaceWithExceptionThrown) { + beman::optional::optional a; + EXPECT_ANY_THROW(a.emplace()); +} + +TEST(OptionalTest, RangeTest) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = 42; + EXPECT_EQ(*o2, 42); + for(auto k : o1) { + (void)k; + EXPECT_TRUE(false); + } + for(auto k : o2) { + EXPECT_EQ(k, 42); + } +} + +TEST(ViewMaybeTest, Constructors) { + std::ranges::single_view> s; + std::ranges::single_view> s2{s}; + std::ranges::single_view> s3{std::optional{}}; + + beman::optional::optional> n; + beman::optional::optional> n2{n}; + beman::optional::optional> n3{std::optional{}}; +} + +TEST(ViewMaybeTest, ConceptCheck) { + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(!std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + static_assert(std::ranges::sized_range>); + + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + using ref = std::reference_wrapper; + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); +} + +TEST(ViewMaybeTest, ConceptCheckRef) { + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + using ref = std::reference_wrapper&; + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); +} + +TEST(ViewMaybeTest, BreathingTest) { + beman::optional::optional m; + // ASSERT_TRUE(m.empty()); + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m.data() == nullptr); + + beman::optional::optional m1{1}; + // ASSERT_TRUE(!m1.empty()); + // ASSERT_TRUE(m1.size() == 1); + // ASSERT_TRUE(m1.data() != nullptr); + // ASSERT_TRUE(*(m1.data()) == 1); + + m = m1; + ASSERT_EQ(*std::begin(m), 1); + + m = {}; + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m1.size() == 1); + + beman::optional::optional d0{0}; + // ASSERT_TRUE(!d0.empty()); + + beman::optional::optional d1{1}; + // ASSERT_TRUE(!d1.empty()); + + d0 = d1; + ASSERT_EQ(*std::begin(d0), 1.0); +} + +TEST(ViewMaybeTest, BreathingTestRef) { + beman::optional::optional m; + // ASSERT_TRUE(m.empty()); + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m.data() == nullptr); + + int one = 1; + beman::optional::optional m1{one}; + // ASSERT_TRUE(!m1.empty()); + // ASSERT_TRUE(m1.size() == 1); + // ASSERT_TRUE(m1.data() != nullptr); + // ASSERT_TRUE(*(m1.data()) == 1); + + m = m1; + ASSERT_EQ(*std::begin(m), 1); + + // m = {}; + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m1.size() == 1); + + double zero = 0.0; + beman::optional::optional d0{zero}; + // ASSERT_TRUE(!d0.empty()); + + double one_d = 1.0; + beman::optional::optional d1{one_d}; + // ASSERT_TRUE(!d1.empty()); + + d0 = d1; + ASSERT_EQ(*std::begin(d0), 1.0); +} + +TEST(ViewMaybe, CompTest) { + beman::optional::optional m; + beman::optional::optional m0{0}; + beman::optional::optional m1{1}; + beman::optional::optional m1a{1}; + + ASSERT_EQ(m, m); + ASSERT_EQ(m0, m0); + ASSERT_EQ(m1, m1); + ASSERT_EQ(m1a, m1a); + ASSERT_EQ(m1, m1a); + + ASSERT_NE(m, m0); + ASSERT_NE(m0, m1); + + ASSERT_TRUE(m < m0); + ASSERT_TRUE(m0 < m1); + ASSERT_TRUE(m1 <= m1a); +} + +TEST(ViewMaybe, CompTestRef) { + beman::optional::optional m; + int zero = 0; + int one = 1; + int one_a = 1; + beman::optional::optional m0{zero}; + beman::optional::optional m1{one}; + beman::optional::optional m1a{one_a}; + + ASSERT_EQ(m, m); + ASSERT_EQ(m0, m0); + ASSERT_EQ(m1, m1); + ASSERT_EQ(m1a, m1a); + ASSERT_EQ(m1, m1a); + + ASSERT_NE(m, m0); + ASSERT_NE(m0, m1); + + ASSERT_TRUE(m < m0); + ASSERT_TRUE(m0 > m); + ASSERT_TRUE(m0 < m1); + ASSERT_TRUE(m1a <= m1); +} + +// "and_then" creates a new view by applying a +// transformation to each element in an input +// range, and flattening the resulting range of +// ranges. A.k.a. bind +// (This uses one syntax for constrained lambdas +// in C++20.) +inline constexpr auto and_then = [](auto&& r, auto fun) { + return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | + std::ranges::views::join; +}; + +// "yield_if" takes a bool and a value and +// returns a view of zero or one elements. +inline constexpr auto yield_if = [](bool b, T x) { + return b ? + beman::optional::optional{move(x)} : + beman::optional::nullopt; +}; + + +TEST(ViewMaybeTest, PythTripleTest) { + using std::ranges::views::iota; + auto triples = and_then(iota(1), [](int z) { + return and_then(iota(1, z + 1), [=](int x) { + return and_then(iota(x, z + 1), [=](int y) { + return yield_if(x * x + y * y == z * z, + std::make_tuple(x, y, z)); + }); + }); + }); + + ASSERT_EQ(*std::ranges::begin(triples), std::make_tuple(3, 4, 5)); +} + +using namespace beman; + +TEST(ViewMaybeTest, ValueBase) { + int i = 7; + beman::optional::optional v1{}; + // ASSERT_TRUE(v1.size() == 0); + + beman::optional::optional v2{i}; + // ASSERT_TRUE(v2.size() == 1); + for (auto i : v1) + ASSERT_TRUE(i != i); // tautology so i is used and not warned + + + for (auto i : v2) + ASSERT_EQ(i, 7); + +// ASSERT_EQ(v2[0], 7); // no match for operator[] +// auto x = v2[1000]; + + // int s = 4; + // for (auto&& i : views::maybe(s)) { + // ASSERT_EQ(i, 4); + // i = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 4); +} + +TEST(ViewMaybeTest, RefWrapper) { + int i = 7; + + beman::optional::optional v2{std::ref(i)}; + + for (auto i : v2) + ASSERT_EQ(i, 7); + + // int s = 4; + // for (auto&& i : views::maybe(std::ref(s))) { + // ASSERT_EQ(i, 4); + // i.get() = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 9); +} + + +TEST(ViewMaybeTest, ValueNonDefaultConstruct) { + NoDefault i = 7; + beman::optional::optional v1{}; + beman::optional::optional v2{i}; +} + +TEST(ViewMaybeTest, RefBase) { + int i = 7; + beman::optional::optional v1{}; + // ASSERT_TRUE(v1.size() == 0); + + beman::optional::optional v2{i}; + // ASSERT_TRUE(v2.size() == 1); + for (auto i : v1) + ASSERT_TRUE(i != i); // tautology so i is used and not warned + + for (auto i : v2) { + ASSERT_EQ(i, 7); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(i, 7); + + for (auto&& i : v2) { + ASSERT_EQ(i, 7); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(i, 9); + + int s = 4; + // for (auto&& i : views::maybe(s)) { + // ASSERT_EQ(i, 4); + // i = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 4); + + for (auto&& i : beman::optional::optional(s)) { + ASSERT_EQ(i, 4); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(s, 9); +} + +// TEST(ViewMaybeTest, MonadicAndThen) { +// beman::optional::optional mv{40}; +// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); +// ASSERT_TRUE(r2.empty()); +// ASSERT_TRUE(r2.size() == 0); +// ASSERT_TRUE(r2.data() == nullptr); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).and_then([](int&& i) { +// int k = i; +// i = 0; +// return beman::optional::optional{k + 2}; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); + +// const beman::optional::optional cmv{40}; +// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicTransform) { +// beman::optional::optional mv{40}; +// auto r = mv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.transform([](int& i) { +// i += 2; +// return i; +// }); +// ASSERT_TRUE(!r2.empty()); +// ASSERT_TRUE(r2.size() == 1); +// ASSERT_TRUE(r2.data() != nullptr); +// ASSERT_TRUE(*(r2.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 42); + +// beman::optional::optional empty{}; + +// auto r3 = empty.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.transform([](double d) { return d + 2; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 44.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 44); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 42); + +// auto r6 = std::move(mv).transform([](int&& i) { +// int k = i; +// i = 0; +// return k + 2; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 44); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); + +// const beman::optional::optional cmv{40}; +// auto r7 = cmv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicOrElse) { +// beman::optional::optional o1(42); +// auto r = o1.or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r.data()) == 42); + +// beman::optional::optional o2; +// ASSERT_TRUE(*(o2.or_else([] { return beman::optional::optional(13); })).data() == +// 13); + +// auto r2 = std::move(o1).or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r2.data()) == 42); + +// auto r3 = std::move(o2).or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r3.data()) == 13); +// } + +// TEST(ViewMaybeTest, MonadicAndThenRef) { +// int forty{40}; +// beman::optional::optional mv{forty}; +// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); +// ASSERT_TRUE(r2.empty()); +// ASSERT_TRUE(r2.size() == 0); +// ASSERT_TRUE(r2.data() == nullptr); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).and_then([](int&& i) { +// int k = i; +// i = 0; +// return beman::optional::optional{k + 2}; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); +// ASSERT_EQ(forty, 0); +// forty = 40; + +// const beman::optional::optional cmv{forty}; +// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_EQ(*(r7.data()), 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_EQ(*(r8.data()), 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicTransformRef) { +// int forty{40}; +// beman::optional::optional mv{forty}; +// auto r = mv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_EQ(*(r.data()), 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.transform([](double d) { return d + 2; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).transform([](int&& i) { +// int k = i; +// i = 0; +// return k + 2; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); +// ASSERT_EQ(forty, 0); +// forty = 40; + +// const beman::optional::optional cmv{forty}; +// ASSERT_EQ(*(cmv.data()), 40); +// auto r7 = cmv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r9 = mv.transform([](int& i) { +// int k = i; +// i = 56; +// return k * 2; +// }); +// ASSERT_TRUE(!r9.empty()); +// ASSERT_EQ(r9.size(), 1); +// ASSERT_TRUE(r9.data() != nullptr); +// for (auto r: r9) { +// ASSERT_EQ(r, 80); +// } +// ASSERT_TRUE(!mv.empty()); +// for (auto v: mv) { +// ASSERT_EQ(v, 56); +// } +// ASSERT_EQ(forty, 56); +// forty = 40; +// } + +// TEST(MaybeView, MonadicOrElseRef) { +// int fortytwo{42}; +// int thirteen{13}; +// beman::optional::optional o1(fortytwo); +// auto r = o1.or_else([&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r.data()) == 42); + +// beman::optional::optional o2; +// ASSERT_TRUE(*(o2.or_else([&thirteen] { +// return beman::optional::optional(thirteen); +// })).data() == 13); + +// auto r2 = std::move(o1).or_else( +// [&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r2.data()) == 42); + +// auto r3 = std::move(o2).or_else( +// [&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r3.data()) == 13); +// } diff --git a/src/Beman/optional/tests/optional_monadic.t.cpp b/src/Beman/optional/tests/optional_monadic.t.cpp new file mode 100644 index 00000000..79a1c6a7 --- /dev/null +++ b/src/Beman/optional/tests/optional_monadic.t.cpp @@ -0,0 +1,311 @@ +#include + +#include + +constexpr int get_int(int) { return 42; } +constexpr beman::optional::optional get_opt_int(int) { return 42; } + + +TEST(OptionalMonadicTest, Transform) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 40; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + beman::optional::optional o3 = 42; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o4 = 40; + auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + const beman::optional::optional o5 = 40; + auto o5r = o5.transform([](const int &i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = 42; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = 42; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = 42; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + + // callable which returns a reference + beman::optional::optional o38 = 42; + auto o38r = o38.transform([](int &i) -> const int & { return i; }); + EXPECT_TRUE(o38r); + EXPECT_TRUE(*o38r == 42); + + } + + TEST(OptionalMonadicTest, TransformConstexpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = 42; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = 42; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); + } + +TEST(OptionalMonadicTest, Transform2) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 40; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + beman::optional::optional o3 = 42; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o4 = 40; + auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + const beman::optional::optional o5 = 40; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = 42; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = 42; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = 42; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + } + + TEST(OptionalMonadicTest, TransformConstxpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = 42; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = 42; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); + } + +TEST(OptionalMonadicTest, and_then) + { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 12; + auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42.f); + + // lhs is empty, rhs returns empty + beman::optional::optional o3; + auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o3r); + + // rhs returns empty + beman::optional::optional o4 = 12; + auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o4r); + + struct rval_call_and_then { + beman::optional::optional operator()(int) && { + return beman::optional::optional(42.0); + }; + }; + + // ensure that function object is forwarded + beman::optional::optional o5 = 42; + auto o5r = o5.and_then(rval_call_and_then{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o6 = 42; + auto o6r = + std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o6r.value() == 42); + + // ensure that function object is const-propagated + const beman::optional::optional o7 = 42; + auto o7r = + o7.and_then([](const int &i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o7r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o9 = 42; + auto o9r = + std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o9r == 42); + + const beman::optional::optional o10 = 42; + auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o10r == 42); + + const beman::optional::optional o11 = 42; + auto o11r = + std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o11r == 42); + + beman::optional::optional o16 = beman::optional::nullopt; + auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o16r); + + beman::optional::optional o17 = beman::optional::nullopt; + auto o17r = + std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o17r); + + const beman::optional::optional o18 = beman::optional::nullopt; + auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o18r); + + const beman::optional::optional o19 = beman::optional::nullopt; + auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o19r); + + int i = 3; + beman::optional::optional o20{i}; + std::move(o20).and_then([](int& r){return beman::optional::optional{++r};}); + EXPECT_TRUE(o20); + EXPECT_TRUE(i == 4); + } + +TEST(OptionalMonadicTest, Constexpr_and_then) +{ + constexpr beman::optional::optional o10 = 42; + constexpr auto o10r = o10.and_then(get_opt_int); + EXPECT_TRUE(*o10r == 42); + + constexpr beman::optional::optional o11 = 42; + constexpr auto o11r = std::move(o11).and_then(get_opt_int); + EXPECT_TRUE(*o11r == 42); + + constexpr beman::optional::optional o18 = beman::optional::nullopt; + constexpr auto o18r = o18.and_then(get_opt_int); + EXPECT_TRUE(!o18r); + + constexpr beman::optional::optional o19 = beman::optional::nullopt; + constexpr auto o19r = std::move(o19).and_then(get_opt_int); + EXPECT_TRUE(!o19r); + } + +TEST(OptionalMonadicTest, or_else){ + beman::optional::optional o1 = 42; + EXPECT_TRUE(*(o1.or_else([] { return beman::optional::make_optional(13); })) == 42); + + beman::optional::optional o2; + EXPECT_EQ(*(o2.or_else([] { return beman::optional::make_optional(13); })), 13); + } diff --git a/src/Beman/optional/tests/optional_range_support.t.cpp b/src/Beman/optional/tests/optional_range_support.t.cpp new file mode 100644 index 00000000..3e34ed14 --- /dev/null +++ b/src/Beman/optional/tests/optional_range_support.t.cpp @@ -0,0 +1,9 @@ +#include + +#include +#include +#include +#include +#include +#include + diff --git a/src/Beman/optional/tests/optional_ref.t.cpp b/src/Beman/optional/tests/optional_ref.t.cpp new file mode 100644 index 00000000..3591256b --- /dev/null +++ b/src/Beman/optional/tests/optional_ref.t.cpp @@ -0,0 +1,560 @@ +#include + +#include + +TEST(OptionalRefTest, TestGTest) { ASSERT_EQ(1, 1); } + +namespace { +struct empty {}; +struct no_default { + no_default() = delete; + no_default(const no_default&) = default; + no_default(no_default&&) = default; + no_default& operator=(const no_default&) = default; + no_default& operator=(no_default&&) = default; + no_default(empty){}; +}; + +struct base { + int i_; + base() : i_(0) {} + base(int i) : i_(i) {} +}; + +struct derived : public base { + int j_; + derived() : base(0), j_(0) {} + derived(int i, int j) : base(i), j_(j) {} +}; +} // namespace + +TEST(OptionalRefTest, Constructors) { + beman::optional::optional i1; + beman::optional::optional i2{beman::optional::nullopt}; + (void)i1; + (void)i2; + + int i = 0; + beman::optional::optional i3 = i; + (void)i3; + + beman::optional::optional e1; + beman::optional::optional e2{beman::optional::nullopt}; + (void)e1; + (void)e2; + + empty e{}; + beman::optional::optional e3 = e; + (void)e3; + + beman::optional::optional nd1; + beman::optional::optional nd2{beman::optional::nullopt}; + (void)nd1; + (void)nd2; + + no_default nd{e}; + + beman::optional::optional nd3 = nd; + (void)nd3; + + beman::optional::optional ie; + beman::optional::optional i4 = ie; + EXPECT_FALSE(i4); + + base b{1}; + derived d(1, 2); + beman::optional::optional b1 = b; + beman::optional::optional b2 = d; + + beman::optional::optional d2 = d; + beman::optional::optional b3 = d2; + beman::optional::optional b4{d2}; + + beman::optional::optional empty; + beman::optional::optional fromEmpty(empty); + beman::optional::optional fromEmpty2 = empty; +} + +TEST(OptionalRefTest, Assignment) { + beman::optional::optional i1; + EXPECT_FALSE(i1); + int i = 5; + i1 = i; + i = 7; + EXPECT_TRUE(i1); + EXPECT_TRUE(*i1 = 7); + + double d; + // i1 = d; // ill-formed by mandate + beman::optional::optional d1 = d; + // i1 = d1; // ill-formed by mandate + beman::optional::optional i2 = i1; + EXPECT_TRUE(i2); + EXPECT_TRUE(*i2 = 7); + + beman::optional::optional empty; + EXPECT_FALSE(empty); + i2 = empty; + EXPECT_FALSE(i2); + int eight = 8; + empty.emplace(eight); + EXPECT_TRUE(empty); + EXPECT_EQ(empty, 8); +} + +TEST(OptionalRefTest, RelationalOps) { + int i1 = 4; + int i2 = 42; + beman::optional::optional o1{i1}; + beman::optional::optional o2{i2}; + beman::optional::optional o3{}; + + // SECTION("self simple") + { + EXPECT_TRUE(!(o1 == o2)); + EXPECT_TRUE(o1 == o1); + EXPECT_TRUE(o1 != o2); + EXPECT_TRUE(!(o1 != o1)); + EXPECT_TRUE(o1 < o2); + EXPECT_TRUE(!(o1 < o1)); + EXPECT_TRUE(!(o1 > o2)); + EXPECT_TRUE(!(o1 > o1)); + EXPECT_TRUE(o1 <= o2); + EXPECT_TRUE(o1 <= o1); + EXPECT_TRUE(!(o1 >= o2)); + EXPECT_TRUE(o1 >= o1); + } + // SECTION("nullopt simple") + { + EXPECT_TRUE(!(o1 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o1)); + EXPECT_TRUE(o1 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o1); + EXPECT_TRUE(!(o1 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o1); + EXPECT_TRUE(o1 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o1)); + EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o1); + EXPECT_TRUE(o1 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o1)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + // SECTION("with T simple") + { + EXPECT_TRUE(!(o1 == 1)); + EXPECT_TRUE(!(1 == o1)); + EXPECT_TRUE(o1 != 1); + EXPECT_TRUE(1 != o1); + EXPECT_TRUE(!(o1 < 1)); + EXPECT_TRUE(1 < o1); + EXPECT_TRUE(o1 > 1); + EXPECT_TRUE(!(1 > o1)); + EXPECT_TRUE(!(o1 <= 1)); + EXPECT_TRUE(1 <= o1); + EXPECT_TRUE(o1 >= 1); + EXPECT_TRUE(!(1 >= o1)); + + EXPECT_TRUE(o1 == 4); + EXPECT_TRUE(4 == o1); + EXPECT_TRUE(!(o1 != 4)); + EXPECT_TRUE(!(4 != o1)); + EXPECT_TRUE(!(o1 < 4)); + EXPECT_TRUE(!(4 < o1)); + EXPECT_TRUE(!(o1 > 4)); + EXPECT_TRUE(!(4 > o1)); + EXPECT_TRUE(o1 <= 4); + EXPECT_TRUE(4 <= o1); + EXPECT_TRUE(o1 >= 4); + EXPECT_TRUE(4 >= o1); + } + std::string s4 = "hello"; + std::string s5 = "xyz"; + beman::optional::optional o4{s4}; + beman::optional::optional o5{s5}; + + // SECTION("self complex") + { + EXPECT_TRUE(!(o4 == o5)); + EXPECT_TRUE(o4 == o4); + EXPECT_TRUE(o4 != o5); + EXPECT_TRUE(!(o4 != o4)); + EXPECT_TRUE(o4 < o5); + EXPECT_TRUE(!(o4 < o4)); + EXPECT_TRUE(!(o4 > o5)); + EXPECT_TRUE(!(o4 > o4)); + EXPECT_TRUE(o4 <= o5); + EXPECT_TRUE(o4 <= o4); + EXPECT_TRUE(!(o4 >= o5)); + EXPECT_TRUE(o4 >= o4); + } + // SECTION("nullopt complex") + { + EXPECT_TRUE(!(o4 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o4)); + EXPECT_TRUE(o4 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o4); + EXPECT_TRUE(!(o4 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o4); + EXPECT_TRUE(o4 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o4)); + EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o4); + EXPECT_TRUE(o4 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o4)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + + // SECTION("with T complex") + { + EXPECT_TRUE(!(o4 == "a")); + EXPECT_TRUE(!("a" == o4)); + EXPECT_TRUE(o4 != "a"); + EXPECT_TRUE("a" != o4); + EXPECT_TRUE(!(o4 < "a")); + EXPECT_TRUE("a" < o4); + EXPECT_TRUE(o4 > "a"); + EXPECT_TRUE(!("a" > o4)); + EXPECT_TRUE(!(o4 <= "a")); + EXPECT_TRUE("a" <= o4); + EXPECT_TRUE(o4 >= "a"); + EXPECT_TRUE(!("a" >= o4)); + + EXPECT_TRUE(o4 == "hello"); + EXPECT_TRUE("hello" == o4); + EXPECT_TRUE(!(o4 != "hello")); + EXPECT_TRUE(!("hello" != o4)); + EXPECT_TRUE(!(o4 < "hello")); + EXPECT_TRUE(!("hello" < o4)); + EXPECT_TRUE(!(o4 > "hello")); + EXPECT_TRUE(!("hello" > o4)); + EXPECT_TRUE(o4 <= "hello"); + EXPECT_TRUE("hello" <= o4); + EXPECT_TRUE(o4 >= "hello"); + EXPECT_TRUE("hello" >= o4); + } +} + +TEST(OptionalRefTest, Triviality) { + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + } + + { + struct T { + T(const T&) {} + T(T&&){}; + T& operator=(const T&) { return *this; } + T& operator=(T&&) { return *this; }; + ~T() {} + }; + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + } +} + +TEST(OptionalRefTest, Deletion) { + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = delete; + T& operator=(const T&) = delete; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = default; + T& operator=(const T&) = delete; + T& operator=(T&&) = default; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = default; + T(T&&) = delete; + T& operator=(const T&) = default; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + } +} + +struct takes_init_and_variadic { + std::vector v; + std::tuple t; + template + takes_init_and_variadic(std::initializer_list l, Args&&... args) : v(l), t(std::forward(args)...) {} +}; + +TEST(OptionalRefTest, MakeOptional) { + int var{42}; + auto o1 = beman::optional::make_optional(var); + auto o2 = beman::optional::optional(var); + + constexpr bool is_same = std::is_same>::value; + EXPECT_TRUE(is_same); + EXPECT_TRUE(o1 == o2); + + std::tuple tvar{0, 1, 2, 3}; + auto o3 = beman::optional::make_optional&>(tvar); + EXPECT_TRUE(std::get<0>(*o3) == 0); + EXPECT_TRUE(std::get<1>(*o3) == 1); + EXPECT_TRUE(std::get<2>(*o3) == 2); + EXPECT_TRUE(std::get<3>(*o3) == 3); + + std::vector ivec{0, 1, 2, 3}; + auto o4 = beman::optional::make_optional&>(ivec); + EXPECT_TRUE(o4.value()[0] == 0); + EXPECT_TRUE(o4.value()[1] == 1); + EXPECT_TRUE(o4.value()[2] == 2); + EXPECT_TRUE(o4.value()[3] == 3); + + takes_init_and_variadic tiv{{0, 1}, 2, 3}; + auto o5 = beman::optional::make_optional(tiv); + EXPECT_TRUE(o5->v[0] == 0); + EXPECT_TRUE(o5->v[1] == 1); + EXPECT_TRUE(std::get<0>(o5->t) == 2); + EXPECT_TRUE(std::get<1>(o5->t) == 3); + + auto i = 42; + auto o6 = beman::optional::make_optional(i); + static_assert(std::is_same_v>); + + EXPECT_TRUE((std::is_same_v>)); + EXPECT_TRUE(o6); + EXPECT_TRUE(*o6 == 42); +} + +TEST(OptionalRefTest, Nullopt) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2{beman::optional::nullopt}; + beman::optional::optional o3(beman::optional::nullopt); + beman::optional::optional o4 = {beman::optional::nullopt}; + + EXPECT_TRUE(!o1); + EXPECT_TRUE(!o2); + EXPECT_TRUE(!o3); + EXPECT_TRUE(!o4); + + EXPECT_TRUE(!std::is_default_constructible::value); +} + +struct move_detector { + move_detector() = default; + move_detector(move_detector&& rhs) { rhs.been_moved = true; } + bool been_moved = false; +}; + +TEST(OptionalRefTest, Observers) { + int var = 42; + beman::optional::optional o1 = var; + beman::optional::optional o2; + const beman::optional::optional o3 = var; + const beman::optional::optional o4; + int var2 = 42; + int var3 = 6*9; + EXPECT_TRUE(*o1 == 42); + EXPECT_TRUE(*o1 == o1.value()); + EXPECT_TRUE(o2.value_or(var2) == 42); + EXPECT_TRUE(o3.value() == 42); + EXPECT_TRUE(o3.value_or(var3) == 42); + EXPECT_TRUE(o4.value_or(var3) == 54); + int j = 99; + EXPECT_TRUE(o4.value_or(j) == 99); + // o4.value_or(j) = 88; + // EXPECT_TRUE(j == 88); + int var99 = 99; + j = 88; + EXPECT_TRUE([&](){beman::optional::optional o(j);return o; }().value_or(var99) == 88); + + EXPECT_TRUE([&](){beman::optional::optional o;return o; }().value_or(var99) == 99); + + + EXPECT_TRUE(o3.value_or([&]()->int&{return var3;}()) == 42); + EXPECT_TRUE(o4.value_or([&]()->int&{return var3;}()) == 54); + + std::string meow{"meow"}; + std::string bark{"bark"}; + beman::optional::optional so1; + beman::optional::optional so2{meow}; + auto t1 = so1.value_or(bark); + auto t2 = so2.value_or(bark); + // auto t3 = so1.value_or("bark"); + // auto t4 = so2.value_or("bark"); + // std::tuple t("meow"); + + auto success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + + struct int_box {int i_;}; + int_box i1{3}; + beman::optional::optional ob1 = i1; + beman::optional::optional ob2; + const beman::optional::optional ob3 = i1; + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + +} + +TEST(OptionalRefTest, MoveCheck) { + int x = 0; + int& y = std::move(beman::optional::optional(x)).value(); + EXPECT_EQ(&y, &x); + + int& z = *std::move(beman::optional::optional(x)); + EXPECT_EQ(&z, &x); + +} + +TEST(OptionalRefTest, SwapValue) { + int var = 42; + int twelve = 12; + beman::optional::optional o1 = var; + beman::optional::optional o2 = twelve; + o1.swap(o2); + EXPECT_EQ(o1.value(), 12); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalRefTest, SwapWNull) { + int var = 42; + + beman::optional::optional o1 = var; + beman::optional::optional o2 = beman::optional::nullopt; + o1.swap(o2); + EXPECT_TRUE(!o1.has_value()); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalRefTest, SwapNullIntializedWithValue) { + int var = 42; + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = var; + o1.swap(o2); + EXPECT_EQ(o1.value(), 42); + EXPECT_TRUE(!o2.has_value()); +} diff --git a/src/Beman/optional/tests/optional_ref_monadic.t.cpp b/src/Beman/optional/tests/optional_ref_monadic.t.cpp new file mode 100644 index 00000000..9d9f9fda --- /dev/null +++ b/src/Beman/optional/tests/optional_ref_monadic.t.cpp @@ -0,0 +1,318 @@ +#include + +#include + +namespace { +inline constexpr int constexpr_fortytwo = 42; +constexpr int get_int(int) { return constexpr_fortytwo; } +constexpr beman::optional::optional get_opt_int(int) { return constexpr_fortytwo; } +} // namespace + +TEST(OptionalRefMonadicTest, Transform) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int forty = 40; + beman::optional::optional o2 = forty; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o3 = fortytwo; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // // ensure that lhs is forwarded + // forty = 40; + // beman::optional::optional o4 = forty; + // auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + forty = 40; + const beman::optional::optional o5 = forty; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + fortytwo = 42; + beman::optional::optional o8 = fortytwo; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = fortytwo; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = fortytwo; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = fortytwo; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + + // callable which returns a reference + beman::optional::optional o38 = fortytwo; + auto o38r = o38.transform([](int& i) -> const int& { return i; }); + EXPECT_TRUE(o38r); + EXPECT_TRUE(*o38r == 42); +} + +TEST(OptionalRefMonadicTest, TransformConstexpr) { + + // test each overload in turn + constexpr beman::optional::optional o16 = constexpr_fortytwo; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = constexpr_fortytwo; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); +} + +TEST(OptionalRefMonadicTest, Transform2) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int forty = 40; + beman::optional::optional o2 = forty; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o3 = fortytwo; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // // ensure that lhs is forwarded + // int forty = 40; + // beman::optional::optional o4 = forty; + // auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + forty = 40; + const beman::optional::optional o5 = forty; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + fortytwo = 42; + beman::optional::optional o8 = fortytwo; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = fortytwo; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = fortytwo; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = fortytwo; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); +} + +TEST(OptionalRefMonadicTest, TransformConstxpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = constexpr_fortytwo; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = constexpr_fortytwo; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); +} + +TEST(OptionalRefMonadicTest, and_then) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int twelve = 12; + beman::optional::optional o2 = twelve; + auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42.f); + + // lhs is empty, rhs returns empty + beman::optional::optional o3; + auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o3r); + + // rhs returns empty + beman::optional::optional o4 = twelve; + auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o4r); + + struct rval_call_and_then { + beman::optional::optional operator()(int) && { return beman::optional::optional(42.0); }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o5 = fortytwo; + auto o5r = o5.and_then(rval_call_and_then{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // // ensure that lhs is forwarded + // beman::optional::optional o6 = fortytwo; + // auto o6r = + // std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o6r.value() == 42); + + // ensure that function object is const-propagated + const beman::optional::optional o7 = fortytwo; + auto o7r = o7.and_then([](const int& i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o7r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = fortytwo; + auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o9 = fortytwo; + auto o9r = std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o9r == 42); + + const beman::optional::optional o10 = fortytwo; + auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o10r == 42); + + const beman::optional::optional o11 = fortytwo; + auto o11r = std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o11r == 42); + + beman::optional::optional o16 = beman::optional::nullopt; + auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o16r); + + beman::optional::optional o17 = beman::optional::nullopt; + auto o17r = std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o17r); + + const beman::optional::optional o18 = beman::optional::nullopt; + auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o18r); + + const beman::optional::optional o19 = beman::optional::nullopt; + auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o19r); + + int i = 3; + beman::optional::optional o20{i}; + std::move(o20).and_then([](int& r) { return beman::optional::optional{++r}; }); + EXPECT_TRUE(o20); + EXPECT_TRUE(i == 4); +} + +TEST(OptionalRefMonadicTest, Constexpr_and_then) { + constexpr beman::optional::optional o10 = constexpr_fortytwo; + constexpr auto o10r = o10.and_then(get_opt_int); + EXPECT_TRUE(*o10r == 42); + + constexpr beman::optional::optional o11 = constexpr_fortytwo; + constexpr auto o11r = std::move(o11).and_then(get_opt_int); + EXPECT_TRUE(*o11r == 42); + + constexpr beman::optional::optional o18 = beman::optional::nullopt; + constexpr auto o18r = o18.and_then(get_opt_int); + EXPECT_TRUE(!o18r); + + constexpr beman::optional::optional o19 = beman::optional::nullopt; + constexpr auto o19r = std::move(o19).and_then(get_opt_int); + EXPECT_TRUE(!o19r); +} + +TEST(OptionalRefMonadicTest, or_else) { + int fortytwo = 42; + int thirteen = 13; + beman::optional::optional o1 = fortytwo; + EXPECT_TRUE(*(o1.or_else([&] { return beman::optional::optional(thirteen); })) == 42); + + beman::optional::optional o2; + EXPECT_EQ(*(o2.or_else([&] { return beman::optional::optional(thirteen); })), 13); +} diff --git a/src/beman/optional/optional.t.cpp b/src/beman/optional/optional.t.cpp new file mode 100644 index 00000000..9da8715d --- /dev/null +++ b/src/beman/optional/optional.t.cpp @@ -0,0 +1,1278 @@ +#include + +#include // test 2nd include OK + +#include +#include +#include + +#include + +TEST(OptionalTest, TestGTest) { ASSERT_EQ(1, 1); } + +namespace { +struct empty {}; +struct no_default { + no_default() = delete; + no_default(const no_default&) = default; + no_default(no_default&&) = default; + no_default& operator=(const no_default&) = default; + no_default& operator=(no_default&&) = default; + no_default(empty){}; +}; + +struct base { + int i_; + base() : i_(0) {} + base(int i) : i_(i) {} +}; + +struct derived : public base { + int j_; + derived() : base(0), j_(0) {} + derived(int i, int j) : base(i), j_(j) {} +}; +} // namespace + +TEST(OptionalTest, Constructors) { + beman::optional::optional i1; + beman::optional::optional i2{beman::optional::nullopt}; + + int i = 0; + beman::optional::optional i3 = i; + (void)i3; + + beman::optional::optional e1; + beman::optional::optional e2{beman::optional::nullopt}; + + empty e{}; + beman::optional::optional e3 = e; + (void)e3; +} + + +TEST(OptionalTest, Constructors2) { + beman::optional::optional o1; + EXPECT_TRUE(!o1); + + beman::optional::optional o2 = beman::optional::nullopt; + EXPECT_TRUE(!o2); + + beman::optional::optional o3 = 42; + EXPECT_TRUE(*o3 == 42); + + beman::optional::optional o4 = o3; + EXPECT_TRUE(*o4 == 42); + + beman::optional::optional o5 = o1; + EXPECT_TRUE(!o5); + + beman::optional::optional o6 = std::move(o3); + EXPECT_TRUE(*o6 == 42); + + beman::optional::optional o7 = 42; + EXPECT_TRUE(*o7 == 42); + + beman::optional::optional o8 = o7; + EXPECT_TRUE(*o8 == 42); + + beman::optional::optional o9 = std::move(o7); + EXPECT_TRUE(*o9 == 42); + + { + beman::optional::optional o; + EXPECT_TRUE(!o); + + beman::optional::optional oo = o; + EXPECT_TRUE(!oo); + } + + { + auto i = 42; + beman::optional::optional o = i; + EXPECT_TRUE(o); + EXPECT_TRUE(*o == 42); + + beman::optional::optional oo = o; + EXPECT_TRUE(oo); + EXPECT_TRUE(*oo == 42); + } + + std::vector v; + v.emplace_back(); + beman::optional::optional> ov = std::move(v); + EXPECT_TRUE(ov->size() == 1); +} + +TEST(OptionalTest, Constructors3) { + beman::optional::optional ie; + beman::optional::optional i4 = ie; + EXPECT_FALSE(i4); + + base b{1}; + derived d(1, 2); + beman::optional::optional b1{b}; + beman::optional::optional b2{d}; + + beman::optional::optional d2{d}; + beman::optional::optional b3 = d2; + beman::optional::optional b4{d2}; +} + +namespace { +class NoDefault { + int v_; + + public: + NoDefault(int v) : v_(v) {} +}; +} // namespace + +TEST(OptionalTest, NonDefaultConstruct) { + NoDefault i = 7; + beman::optional::optional v1{}; + beman::optional::optional v2{i}; +} + +TEST(OptionalTest, AssignmentValue) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = 12; + beman::optional::optional o3; + + o1 = o1; + EXPECT_TRUE(*o1 == 42); + + o1 = o2; + EXPECT_TRUE(*o1 == 12); + + o1 = o3; + EXPECT_TRUE(!o1); + + o1 = 42; + EXPECT_TRUE(*o1 == 42); + + o1 = beman::optional::nullopt; + EXPECT_TRUE(!o1); + + o1 = std::move(o2); + EXPECT_TRUE(*o1 == 12); + + beman::optional::optional o4 = 42; + + o1 = o4; + EXPECT_TRUE(*o1 == 42); + + o1 = std::move(o4); + EXPECT_TRUE(*o1 == 42); +} + +TEST(OptionalTest, Triviality) { + EXPECT_TRUE(std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE( + std::is_trivially_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE( + std::is_trivially_destructible>::value); + } + + { + struct T { + T(const T&) {} + T(T&&){}; + T& operator=(const T&) { return *this; } + T& operator=(T&&) { return *this; }; + ~T() {} + }; + EXPECT_TRUE(!std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_destructible< + beman::optional::optional>::value); + } +} + +TEST(OptionalTest, Deletion) { + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE( + std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE( + std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = delete; + T& operator=(const T&) = delete; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE( + !std::is_copy_constructible>::value); + EXPECT_TRUE( + !std::is_copy_assignable>::value); + EXPECT_TRUE( + !std::is_move_constructible>::value); + EXPECT_TRUE( + !std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = default; + T& operator=(const T&) = delete; + T& operator=(T&&) = default; + }; + EXPECT_TRUE( + !std::is_copy_constructible>::value); + EXPECT_TRUE( + !std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE( + std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = default; + T(T&&) = delete; + T& operator=(const T&) = default; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE( + std::is_copy_assignable>::value); + } +} + +struct takes_init_and_variadic { + std::vector v; + std::tuple t; + template + takes_init_and_variadic(std::initializer_list l, Args&&... args) + : v(l), t(std::forward(args)...) {} +}; + +TEST(OptionalTest, InPlace) { + beman::optional::optional o1{beman::optional::in_place}; + beman::optional::optional o2(beman::optional::in_place); + EXPECT_TRUE(o1); + EXPECT_TRUE(o1 == 0); + EXPECT_TRUE(o2); + EXPECT_TRUE(o2 == 0); + + beman::optional::optional o3(beman::optional::in_place, 42); + EXPECT_TRUE(o3 == 42); + + beman::optional::optional> o4( + beman::optional::in_place, 0, 1); + EXPECT_TRUE(o4); + EXPECT_TRUE(std::get<0>(*o4) == 0); + EXPECT_TRUE(std::get<1>(*o4) == 1); + + beman::optional::optional> o5(beman::optional::in_place, + {0, 1}); + EXPECT_TRUE(o5); + EXPECT_TRUE((*o5)[0] == 0); + EXPECT_TRUE((*o5)[1] == 1); + + beman::optional::optional o6( + beman::optional::in_place, {0, 1}, 2, 3); + EXPECT_TRUE(o6->v[0] == 0); + EXPECT_TRUE(o6->v[1] == 1); + EXPECT_TRUE(std::get<0>(o6->t) == 2); + EXPECT_TRUE(std::get<1>(o6->t) == 3); +} + +TEST(OptionalTest, MakeOptional) { + auto o1 = beman::optional::make_optional(42); + auto o2 = beman::optional::optional(42); + + constexpr bool is_same = + std::is_same>::value; + EXPECT_TRUE(is_same); + EXPECT_TRUE(o1 == o2); + + auto o3 = beman::optional::make_optional>( + 0, 1, 2, 3); + EXPECT_TRUE(std::get<0>(*o3) == 0); + EXPECT_TRUE(std::get<1>(*o3) == 1); + EXPECT_TRUE(std::get<2>(*o3) == 2); + EXPECT_TRUE(std::get<3>(*o3) == 3); + + auto o4 = beman::optional::make_optional>({0, 1, 2, 3}); + EXPECT_TRUE(o4.value()[0] == 0); + EXPECT_TRUE(o4.value()[1] == 1); + EXPECT_TRUE(o4.value()[2] == 2); + EXPECT_TRUE(o4.value()[3] == 3); + + auto o5 = + beman::optional::make_optional({0, 1}, 2, 3); + EXPECT_TRUE(o5->v[0] == 0); + EXPECT_TRUE(o5->v[1] == 1); + EXPECT_TRUE(std::get<0>(o5->t) == 2); + EXPECT_TRUE(std::get<1>(o5->t) == 3); + + auto i = 42; + auto o6 = beman::optional::make_optional(i); + static_assert(std::is_same>::value); + + EXPECT_TRUE( + (std::is_same>::value)); + EXPECT_TRUE(o6); + EXPECT_TRUE(*o6 == 42); +} + +TEST(OptionalTest, Nullopt) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2{beman::optional::nullopt}; + beman::optional::optional o3(beman::optional::nullopt); + beman::optional::optional o4 = {beman::optional::nullopt}; + + EXPECT_TRUE(!o1); + EXPECT_TRUE(!o2); + EXPECT_TRUE(!o3); + EXPECT_TRUE(!o4); + + EXPECT_TRUE( + !std::is_default_constructible::value); +} + +struct move_detector { + move_detector() = default; + move_detector(move_detector&& rhs) { rhs.been_moved = true; } + bool been_moved = false; +}; + +TEST(OptionalTest, Observers) { + beman::optional::optional o1 = 42; + beman::optional::optional o2; + const beman::optional::optional o3 = 42; + + EXPECT_TRUE(*o1 == 42); + EXPECT_TRUE(*o1 == o1.value()); + EXPECT_TRUE(o2.value_or(42) == 42); + EXPECT_TRUE(o3.value() == 42); + auto success = std::is_same::value; + EXPECT_TRUE(success); + success = std::is_same::value; + EXPECT_TRUE(success); + success = std::is_same::value; + EXPECT_TRUE(success); + + beman::optional::optional o4{beman::optional::in_place}; + move_detector o5 = std::move(o4).value(); + EXPECT_TRUE(o4->been_moved); + EXPECT_TRUE(!o5.been_moved); +} + +TEST(OptionalTest, RelationalOps) { + beman::optional::optional o1{4}; + beman::optional::optional o2{42}; + beman::optional::optional o3{}; + + // SECTION("self simple") + { + EXPECT_TRUE(!(o1 == o2)); + EXPECT_TRUE(o1 == o1); + EXPECT_TRUE(o1 != o2); + EXPECT_TRUE(!(o1 != o1)); + EXPECT_TRUE(o1 < o2); + EXPECT_TRUE(!(o1 < o1)); + EXPECT_TRUE(!(o1 > o2)); + EXPECT_TRUE(!(o1 > o1)); + EXPECT_TRUE(o1 <= o2); + EXPECT_TRUE(o1 <= o1); + EXPECT_TRUE(!(o1 >= o2)); + EXPECT_TRUE(o1 >= o1); + } + // SECTION("nullopt simple") + { + EXPECT_TRUE(!(o1 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o1)); + EXPECT_TRUE(o1 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o1); + EXPECT_TRUE(!(o1 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o1); + EXPECT_TRUE(o1 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o1)); + EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o1); + EXPECT_TRUE(o1 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o1)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + // SECTION("with T simple") + { + EXPECT_TRUE(!(o1 == 1)); + EXPECT_TRUE(!(1 == o1)); + EXPECT_TRUE(o1 != 1); + EXPECT_TRUE(1 != o1); + EXPECT_TRUE(!(o1 < 1)); + EXPECT_TRUE(1 < o1); + EXPECT_TRUE(o1 > 1); + EXPECT_TRUE(!(1 > o1)); + EXPECT_TRUE(!(o1 <= 1)); + EXPECT_TRUE(1 <= o1); + EXPECT_TRUE(o1 >= 1); + EXPECT_TRUE(!(1 >= o1)); + + EXPECT_TRUE(o1 == 4); + EXPECT_TRUE(4 == o1); + EXPECT_TRUE(!(o1 != 4)); + EXPECT_TRUE(!(4 != o1)); + EXPECT_TRUE(!(o1 < 4)); + EXPECT_TRUE(!(4 < o1)); + EXPECT_TRUE(!(o1 > 4)); + EXPECT_TRUE(!(4 > o1)); + EXPECT_TRUE(o1 <= 4); + EXPECT_TRUE(4 <= o1); + EXPECT_TRUE(o1 >= 4); + EXPECT_TRUE(4 >= o1); + } + beman::optional::optional o4{"hello"}; + beman::optional::optional o5{"xyz"}; + + // SECTION("self complex") + { + EXPECT_TRUE(!(o4 == o5)); + EXPECT_TRUE(o4 == o4); + EXPECT_TRUE(o4 != o5); + EXPECT_TRUE(!(o4 != o4)); + EXPECT_TRUE(o4 < o5); + EXPECT_TRUE(!(o4 < o4)); + EXPECT_TRUE(!(o4 > o5)); + EXPECT_TRUE(!(o4 > o4)); + EXPECT_TRUE(o4 <= o5); + EXPECT_TRUE(o4 <= o4); + EXPECT_TRUE(!(o4 >= o5)); + EXPECT_TRUE(o4 >= o4); + } + // SECTION("nullopt complex") + { + EXPECT_TRUE(!(o4 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o4)); + EXPECT_TRUE(o4 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o4); + EXPECT_TRUE(!(o4 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o4); + EXPECT_TRUE(o4 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o4)); + EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o4); + EXPECT_TRUE(o4 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o4)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + + // SECTION("with T complex") + { + EXPECT_TRUE(!(o4 == "a")); + EXPECT_TRUE(!("a" == o4)); + EXPECT_TRUE(o4 != "a"); + EXPECT_TRUE("a" != o4); + EXPECT_TRUE(!(o4 < "a")); + EXPECT_TRUE("a" < o4); + EXPECT_TRUE(o4 > "a"); + EXPECT_TRUE(!("a" > o4)); + EXPECT_TRUE(!(o4 <= "a")); + EXPECT_TRUE("a" <= o4); + EXPECT_TRUE(o4 >= "a"); + EXPECT_TRUE(!("a" >= o4)); + + EXPECT_TRUE(o4 == "hello"); + EXPECT_TRUE("hello" == o4); + EXPECT_TRUE(!(o4 != "hello")); + EXPECT_TRUE(!("hello" != o4)); + EXPECT_TRUE(!(o4 < "hello")); + EXPECT_TRUE(!("hello" < o4)); + EXPECT_TRUE(!(o4 > "hello")); + EXPECT_TRUE(!("hello" > o4)); + EXPECT_TRUE(o4 <= "hello"); + EXPECT_TRUE("hello" <= o4); + EXPECT_TRUE(o4 >= "hello"); + EXPECT_TRUE("hello" >= o4); + } +} + +TEST(OptionalTest, SwapValue) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = 12; + o1.swap(o2); + EXPECT_EQ(o1.value(), 12); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalTest, SwapWNull) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = beman::optional::nullopt; + o1.swap(o2); + EXPECT_TRUE(!o1.has_value()); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalTest, SwapNullIntializedWithValue) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = 42; + o1.swap(o2); + EXPECT_EQ(o1.value(), 42); + EXPECT_TRUE(!o2.has_value()); +} + +TEST(OptionalTest, Emplace) { + beman::optional::optional< + std::pair, std::pair>> + i; + i.emplace(std::piecewise_construct, + std::make_tuple(0, 2), + std::make_tuple(3, 4)); + EXPECT_TRUE(i->first.first == 0); + EXPECT_TRUE(i->first.second == 2); + EXPECT_TRUE(i->second.first == 3); + EXPECT_TRUE(i->second.second == 4); +} + +struct A { + A() { throw std::exception(); } +}; + +TEST(OptionalTest, EmplaceWithExceptionThrown) { + beman::optional::optional a; + EXPECT_ANY_THROW(a.emplace()); +} + +TEST(OptionalTest, RangeTest) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = 42; + EXPECT_EQ(*o2, 42); + for(auto k : o1) { + (void)k; + EXPECT_TRUE(false); + } + for(auto k : o2) { + EXPECT_EQ(k, 42); + } +} + +TEST(ViewMaybeTest, Constructors) { + std::ranges::single_view> s; + std::ranges::single_view> s2{s}; + std::ranges::single_view> s3{std::optional{}}; + + beman::optional::optional> n; + beman::optional::optional> n2{n}; + beman::optional::optional> n3{std::optional{}}; +} + +TEST(ViewMaybeTest, ConceptCheck) { + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(!std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + static_assert(std::ranges::sized_range>); + + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + using ref = std::reference_wrapper; + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); +} + +TEST(ViewMaybeTest, ConceptCheckRef) { + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + using ref = std::reference_wrapper&; + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); +} + +TEST(ViewMaybeTest, BreathingTest) { + beman::optional::optional m; + // ASSERT_TRUE(m.empty()); + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m.data() == nullptr); + + beman::optional::optional m1{1}; + // ASSERT_TRUE(!m1.empty()); + // ASSERT_TRUE(m1.size() == 1); + // ASSERT_TRUE(m1.data() != nullptr); + // ASSERT_TRUE(*(m1.data()) == 1); + + m = m1; + ASSERT_EQ(*std::begin(m), 1); + + m = {}; + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m1.size() == 1); + + beman::optional::optional d0{0}; + // ASSERT_TRUE(!d0.empty()); + + beman::optional::optional d1{1}; + // ASSERT_TRUE(!d1.empty()); + + d0 = d1; + ASSERT_EQ(*std::begin(d0), 1.0); +} + +TEST(ViewMaybeTest, BreathingTestRef) { + beman::optional::optional m; + // ASSERT_TRUE(m.empty()); + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m.data() == nullptr); + + int one = 1; + beman::optional::optional m1{one}; + // ASSERT_TRUE(!m1.empty()); + // ASSERT_TRUE(m1.size() == 1); + // ASSERT_TRUE(m1.data() != nullptr); + // ASSERT_TRUE(*(m1.data()) == 1); + + m = m1; + ASSERT_EQ(*std::begin(m), 1); + + // m = {}; + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m1.size() == 1); + + double zero = 0.0; + beman::optional::optional d0{zero}; + // ASSERT_TRUE(!d0.empty()); + + double one_d = 1.0; + beman::optional::optional d1{one_d}; + // ASSERT_TRUE(!d1.empty()); + + d0 = d1; + ASSERT_EQ(*std::begin(d0), 1.0); +} + +TEST(ViewMaybe, CompTest) { + beman::optional::optional m; + beman::optional::optional m0{0}; + beman::optional::optional m1{1}; + beman::optional::optional m1a{1}; + + ASSERT_EQ(m, m); + ASSERT_EQ(m0, m0); + ASSERT_EQ(m1, m1); + ASSERT_EQ(m1a, m1a); + ASSERT_EQ(m1, m1a); + + ASSERT_NE(m, m0); + ASSERT_NE(m0, m1); + + ASSERT_TRUE(m < m0); + ASSERT_TRUE(m0 < m1); + ASSERT_TRUE(m1 <= m1a); +} + +TEST(ViewMaybe, CompTestRef) { + beman::optional::optional m; + int zero = 0; + int one = 1; + int one_a = 1; + beman::optional::optional m0{zero}; + beman::optional::optional m1{one}; + beman::optional::optional m1a{one_a}; + + ASSERT_EQ(m, m); + ASSERT_EQ(m0, m0); + ASSERT_EQ(m1, m1); + ASSERT_EQ(m1a, m1a); + ASSERT_EQ(m1, m1a); + + ASSERT_NE(m, m0); + ASSERT_NE(m0, m1); + + ASSERT_TRUE(m < m0); + ASSERT_TRUE(m0 > m); + ASSERT_TRUE(m0 < m1); + ASSERT_TRUE(m1a <= m1); +} + +// "and_then" creates a new view by applying a +// transformation to each element in an input +// range, and flattening the resulting range of +// ranges. A.k.a. bind +// (This uses one syntax for constrained lambdas +// in C++20.) +inline constexpr auto and_then = [](auto&& r, auto fun) { + return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | + std::ranges::views::join; +}; + +// "yield_if" takes a bool and a value and +// returns a view of zero or one elements. +inline constexpr auto yield_if = [](bool b, T x) { + return b ? + beman::optional::optional{move(x)} : + beman::optional::nullopt; +}; + + +TEST(ViewMaybeTest, PythTripleTest) { + using std::ranges::views::iota; + auto triples = and_then(iota(1), [](int z) { + return and_then(iota(1, z + 1), [=](int x) { + return and_then(iota(x, z + 1), [=](int y) { + return yield_if(x * x + y * y == z * z, + std::make_tuple(x, y, z)); + }); + }); + }); + + ASSERT_EQ(*std::ranges::begin(triples), std::make_tuple(3, 4, 5)); +} + +using namespace beman; + +TEST(ViewMaybeTest, ValueBase) { + int i = 7; + beman::optional::optional v1{}; + // ASSERT_TRUE(v1.size() == 0); + + beman::optional::optional v2{i}; + // ASSERT_TRUE(v2.size() == 1); + for (auto i : v1) + ASSERT_TRUE(i != i); // tautology so i is used and not warned + + + for (auto i : v2) + ASSERT_EQ(i, 7); + +// ASSERT_EQ(v2[0], 7); // no match for operator[] +// auto x = v2[1000]; + + // int s = 4; + // for (auto&& i : views::maybe(s)) { + // ASSERT_EQ(i, 4); + // i = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 4); +} + +TEST(ViewMaybeTest, RefWrapper) { + int i = 7; + + beman::optional::optional v2{std::ref(i)}; + + for (auto i : v2) + ASSERT_EQ(i, 7); + + // int s = 4; + // for (auto&& i : views::maybe(std::ref(s))) { + // ASSERT_EQ(i, 4); + // i.get() = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 9); +} + + +TEST(ViewMaybeTest, ValueNonDefaultConstruct) { + NoDefault i = 7; + beman::optional::optional v1{}; + beman::optional::optional v2{i}; +} + +TEST(ViewMaybeTest, RefBase) { + int i = 7; + beman::optional::optional v1{}; + // ASSERT_TRUE(v1.size() == 0); + + beman::optional::optional v2{i}; + // ASSERT_TRUE(v2.size() == 1); + for (auto i : v1) + ASSERT_TRUE(i != i); // tautology so i is used and not warned + + for (auto i : v2) { + ASSERT_EQ(i, 7); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(i, 7); + + for (auto&& i : v2) { + ASSERT_EQ(i, 7); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(i, 9); + + int s = 4; + // for (auto&& i : views::maybe(s)) { + // ASSERT_EQ(i, 4); + // i = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 4); + + for (auto&& i : beman::optional::optional(s)) { + ASSERT_EQ(i, 4); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(s, 9); +} + +// TEST(ViewMaybeTest, MonadicAndThen) { +// beman::optional::optional mv{40}; +// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); +// ASSERT_TRUE(r2.empty()); +// ASSERT_TRUE(r2.size() == 0); +// ASSERT_TRUE(r2.data() == nullptr); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).and_then([](int&& i) { +// int k = i; +// i = 0; +// return beman::optional::optional{k + 2}; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); + +// const beman::optional::optional cmv{40}; +// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicTransform) { +// beman::optional::optional mv{40}; +// auto r = mv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.transform([](int& i) { +// i += 2; +// return i; +// }); +// ASSERT_TRUE(!r2.empty()); +// ASSERT_TRUE(r2.size() == 1); +// ASSERT_TRUE(r2.data() != nullptr); +// ASSERT_TRUE(*(r2.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 42); + +// beman::optional::optional empty{}; + +// auto r3 = empty.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.transform([](double d) { return d + 2; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 44.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 44); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 42); + +// auto r6 = std::move(mv).transform([](int&& i) { +// int k = i; +// i = 0; +// return k + 2; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 44); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); + +// const beman::optional::optional cmv{40}; +// auto r7 = cmv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicOrElse) { +// beman::optional::optional o1(42); +// auto r = o1.or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r.data()) == 42); + +// beman::optional::optional o2; +// ASSERT_TRUE(*(o2.or_else([] { return beman::optional::optional(13); })).data() == +// 13); + +// auto r2 = std::move(o1).or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r2.data()) == 42); + +// auto r3 = std::move(o2).or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r3.data()) == 13); +// } + +// TEST(ViewMaybeTest, MonadicAndThenRef) { +// int forty{40}; +// beman::optional::optional mv{forty}; +// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); +// ASSERT_TRUE(r2.empty()); +// ASSERT_TRUE(r2.size() == 0); +// ASSERT_TRUE(r2.data() == nullptr); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).and_then([](int&& i) { +// int k = i; +// i = 0; +// return beman::optional::optional{k + 2}; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); +// ASSERT_EQ(forty, 0); +// forty = 40; + +// const beman::optional::optional cmv{forty}; +// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_EQ(*(r7.data()), 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_EQ(*(r8.data()), 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicTransformRef) { +// int forty{40}; +// beman::optional::optional mv{forty}; +// auto r = mv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_EQ(*(r.data()), 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.transform([](double d) { return d + 2; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).transform([](int&& i) { +// int k = i; +// i = 0; +// return k + 2; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); +// ASSERT_EQ(forty, 0); +// forty = 40; + +// const beman::optional::optional cmv{forty}; +// ASSERT_EQ(*(cmv.data()), 40); +// auto r7 = cmv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r9 = mv.transform([](int& i) { +// int k = i; +// i = 56; +// return k * 2; +// }); +// ASSERT_TRUE(!r9.empty()); +// ASSERT_EQ(r9.size(), 1); +// ASSERT_TRUE(r9.data() != nullptr); +// for (auto r: r9) { +// ASSERT_EQ(r, 80); +// } +// ASSERT_TRUE(!mv.empty()); +// for (auto v: mv) { +// ASSERT_EQ(v, 56); +// } +// ASSERT_EQ(forty, 56); +// forty = 40; +// } + +// TEST(MaybeView, MonadicOrElseRef) { +// int fortytwo{42}; +// int thirteen{13}; +// beman::optional::optional o1(fortytwo); +// auto r = o1.or_else([&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r.data()) == 42); + +// beman::optional::optional o2; +// ASSERT_TRUE(*(o2.or_else([&thirteen] { +// return beman::optional::optional(thirteen); +// })).data() == 13); + +// auto r2 = std::move(o1).or_else( +// [&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r2.data()) == 42); + +// auto r3 = std::move(o2).or_else( +// [&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r3.data()) == 13); +// } diff --git a/src/beman/optional/optional_monadic.t.cpp b/src/beman/optional/optional_monadic.t.cpp new file mode 100644 index 00000000..79a1c6a7 --- /dev/null +++ b/src/beman/optional/optional_monadic.t.cpp @@ -0,0 +1,311 @@ +#include + +#include + +constexpr int get_int(int) { return 42; } +constexpr beman::optional::optional get_opt_int(int) { return 42; } + + +TEST(OptionalMonadicTest, Transform) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 40; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + beman::optional::optional o3 = 42; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o4 = 40; + auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + const beman::optional::optional o5 = 40; + auto o5r = o5.transform([](const int &i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = 42; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = 42; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = 42; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + + // callable which returns a reference + beman::optional::optional o38 = 42; + auto o38r = o38.transform([](int &i) -> const int & { return i; }); + EXPECT_TRUE(o38r); + EXPECT_TRUE(*o38r == 42); + + } + + TEST(OptionalMonadicTest, TransformConstexpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = 42; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = 42; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); + } + +TEST(OptionalMonadicTest, Transform2) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 40; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + beman::optional::optional o3 = 42; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o4 = 40; + auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + const beman::optional::optional o5 = 40; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = 42; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = 42; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = 42; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + } + + TEST(OptionalMonadicTest, TransformConstxpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = 42; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = 42; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); + } + +TEST(OptionalMonadicTest, and_then) + { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 12; + auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42.f); + + // lhs is empty, rhs returns empty + beman::optional::optional o3; + auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o3r); + + // rhs returns empty + beman::optional::optional o4 = 12; + auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o4r); + + struct rval_call_and_then { + beman::optional::optional operator()(int) && { + return beman::optional::optional(42.0); + }; + }; + + // ensure that function object is forwarded + beman::optional::optional o5 = 42; + auto o5r = o5.and_then(rval_call_and_then{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o6 = 42; + auto o6r = + std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o6r.value() == 42); + + // ensure that function object is const-propagated + const beman::optional::optional o7 = 42; + auto o7r = + o7.and_then([](const int &i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o7r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o9 = 42; + auto o9r = + std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o9r == 42); + + const beman::optional::optional o10 = 42; + auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o10r == 42); + + const beman::optional::optional o11 = 42; + auto o11r = + std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o11r == 42); + + beman::optional::optional o16 = beman::optional::nullopt; + auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o16r); + + beman::optional::optional o17 = beman::optional::nullopt; + auto o17r = + std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o17r); + + const beman::optional::optional o18 = beman::optional::nullopt; + auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o18r); + + const beman::optional::optional o19 = beman::optional::nullopt; + auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o19r); + + int i = 3; + beman::optional::optional o20{i}; + std::move(o20).and_then([](int& r){return beman::optional::optional{++r};}); + EXPECT_TRUE(o20); + EXPECT_TRUE(i == 4); + } + +TEST(OptionalMonadicTest, Constexpr_and_then) +{ + constexpr beman::optional::optional o10 = 42; + constexpr auto o10r = o10.and_then(get_opt_int); + EXPECT_TRUE(*o10r == 42); + + constexpr beman::optional::optional o11 = 42; + constexpr auto o11r = std::move(o11).and_then(get_opt_int); + EXPECT_TRUE(*o11r == 42); + + constexpr beman::optional::optional o18 = beman::optional::nullopt; + constexpr auto o18r = o18.and_then(get_opt_int); + EXPECT_TRUE(!o18r); + + constexpr beman::optional::optional o19 = beman::optional::nullopt; + constexpr auto o19r = std::move(o19).and_then(get_opt_int); + EXPECT_TRUE(!o19r); + } + +TEST(OptionalMonadicTest, or_else){ + beman::optional::optional o1 = 42; + EXPECT_TRUE(*(o1.or_else([] { return beman::optional::make_optional(13); })) == 42); + + beman::optional::optional o2; + EXPECT_EQ(*(o2.or_else([] { return beman::optional::make_optional(13); })), 13); + } diff --git a/src/beman/optional/optional_ref.t.cpp b/src/beman/optional/optional_ref.t.cpp new file mode 100644 index 00000000..3591256b --- /dev/null +++ b/src/beman/optional/optional_ref.t.cpp @@ -0,0 +1,560 @@ +#include + +#include + +TEST(OptionalRefTest, TestGTest) { ASSERT_EQ(1, 1); } + +namespace { +struct empty {}; +struct no_default { + no_default() = delete; + no_default(const no_default&) = default; + no_default(no_default&&) = default; + no_default& operator=(const no_default&) = default; + no_default& operator=(no_default&&) = default; + no_default(empty){}; +}; + +struct base { + int i_; + base() : i_(0) {} + base(int i) : i_(i) {} +}; + +struct derived : public base { + int j_; + derived() : base(0), j_(0) {} + derived(int i, int j) : base(i), j_(j) {} +}; +} // namespace + +TEST(OptionalRefTest, Constructors) { + beman::optional::optional i1; + beman::optional::optional i2{beman::optional::nullopt}; + (void)i1; + (void)i2; + + int i = 0; + beman::optional::optional i3 = i; + (void)i3; + + beman::optional::optional e1; + beman::optional::optional e2{beman::optional::nullopt}; + (void)e1; + (void)e2; + + empty e{}; + beman::optional::optional e3 = e; + (void)e3; + + beman::optional::optional nd1; + beman::optional::optional nd2{beman::optional::nullopt}; + (void)nd1; + (void)nd2; + + no_default nd{e}; + + beman::optional::optional nd3 = nd; + (void)nd3; + + beman::optional::optional ie; + beman::optional::optional i4 = ie; + EXPECT_FALSE(i4); + + base b{1}; + derived d(1, 2); + beman::optional::optional b1 = b; + beman::optional::optional b2 = d; + + beman::optional::optional d2 = d; + beman::optional::optional b3 = d2; + beman::optional::optional b4{d2}; + + beman::optional::optional empty; + beman::optional::optional fromEmpty(empty); + beman::optional::optional fromEmpty2 = empty; +} + +TEST(OptionalRefTest, Assignment) { + beman::optional::optional i1; + EXPECT_FALSE(i1); + int i = 5; + i1 = i; + i = 7; + EXPECT_TRUE(i1); + EXPECT_TRUE(*i1 = 7); + + double d; + // i1 = d; // ill-formed by mandate + beman::optional::optional d1 = d; + // i1 = d1; // ill-formed by mandate + beman::optional::optional i2 = i1; + EXPECT_TRUE(i2); + EXPECT_TRUE(*i2 = 7); + + beman::optional::optional empty; + EXPECT_FALSE(empty); + i2 = empty; + EXPECT_FALSE(i2); + int eight = 8; + empty.emplace(eight); + EXPECT_TRUE(empty); + EXPECT_EQ(empty, 8); +} + +TEST(OptionalRefTest, RelationalOps) { + int i1 = 4; + int i2 = 42; + beman::optional::optional o1{i1}; + beman::optional::optional o2{i2}; + beman::optional::optional o3{}; + + // SECTION("self simple") + { + EXPECT_TRUE(!(o1 == o2)); + EXPECT_TRUE(o1 == o1); + EXPECT_TRUE(o1 != o2); + EXPECT_TRUE(!(o1 != o1)); + EXPECT_TRUE(o1 < o2); + EXPECT_TRUE(!(o1 < o1)); + EXPECT_TRUE(!(o1 > o2)); + EXPECT_TRUE(!(o1 > o1)); + EXPECT_TRUE(o1 <= o2); + EXPECT_TRUE(o1 <= o1); + EXPECT_TRUE(!(o1 >= o2)); + EXPECT_TRUE(o1 >= o1); + } + // SECTION("nullopt simple") + { + EXPECT_TRUE(!(o1 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o1)); + EXPECT_TRUE(o1 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o1); + EXPECT_TRUE(!(o1 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o1); + EXPECT_TRUE(o1 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o1)); + EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o1); + EXPECT_TRUE(o1 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o1)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + // SECTION("with T simple") + { + EXPECT_TRUE(!(o1 == 1)); + EXPECT_TRUE(!(1 == o1)); + EXPECT_TRUE(o1 != 1); + EXPECT_TRUE(1 != o1); + EXPECT_TRUE(!(o1 < 1)); + EXPECT_TRUE(1 < o1); + EXPECT_TRUE(o1 > 1); + EXPECT_TRUE(!(1 > o1)); + EXPECT_TRUE(!(o1 <= 1)); + EXPECT_TRUE(1 <= o1); + EXPECT_TRUE(o1 >= 1); + EXPECT_TRUE(!(1 >= o1)); + + EXPECT_TRUE(o1 == 4); + EXPECT_TRUE(4 == o1); + EXPECT_TRUE(!(o1 != 4)); + EXPECT_TRUE(!(4 != o1)); + EXPECT_TRUE(!(o1 < 4)); + EXPECT_TRUE(!(4 < o1)); + EXPECT_TRUE(!(o1 > 4)); + EXPECT_TRUE(!(4 > o1)); + EXPECT_TRUE(o1 <= 4); + EXPECT_TRUE(4 <= o1); + EXPECT_TRUE(o1 >= 4); + EXPECT_TRUE(4 >= o1); + } + std::string s4 = "hello"; + std::string s5 = "xyz"; + beman::optional::optional o4{s4}; + beman::optional::optional o5{s5}; + + // SECTION("self complex") + { + EXPECT_TRUE(!(o4 == o5)); + EXPECT_TRUE(o4 == o4); + EXPECT_TRUE(o4 != o5); + EXPECT_TRUE(!(o4 != o4)); + EXPECT_TRUE(o4 < o5); + EXPECT_TRUE(!(o4 < o4)); + EXPECT_TRUE(!(o4 > o5)); + EXPECT_TRUE(!(o4 > o4)); + EXPECT_TRUE(o4 <= o5); + EXPECT_TRUE(o4 <= o4); + EXPECT_TRUE(!(o4 >= o5)); + EXPECT_TRUE(o4 >= o4); + } + // SECTION("nullopt complex") + { + EXPECT_TRUE(!(o4 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o4)); + EXPECT_TRUE(o4 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o4); + EXPECT_TRUE(!(o4 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o4); + EXPECT_TRUE(o4 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o4)); + EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o4); + EXPECT_TRUE(o4 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o4)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + + // SECTION("with T complex") + { + EXPECT_TRUE(!(o4 == "a")); + EXPECT_TRUE(!("a" == o4)); + EXPECT_TRUE(o4 != "a"); + EXPECT_TRUE("a" != o4); + EXPECT_TRUE(!(o4 < "a")); + EXPECT_TRUE("a" < o4); + EXPECT_TRUE(o4 > "a"); + EXPECT_TRUE(!("a" > o4)); + EXPECT_TRUE(!(o4 <= "a")); + EXPECT_TRUE("a" <= o4); + EXPECT_TRUE(o4 >= "a"); + EXPECT_TRUE(!("a" >= o4)); + + EXPECT_TRUE(o4 == "hello"); + EXPECT_TRUE("hello" == o4); + EXPECT_TRUE(!(o4 != "hello")); + EXPECT_TRUE(!("hello" != o4)); + EXPECT_TRUE(!(o4 < "hello")); + EXPECT_TRUE(!("hello" < o4)); + EXPECT_TRUE(!(o4 > "hello")); + EXPECT_TRUE(!("hello" > o4)); + EXPECT_TRUE(o4 <= "hello"); + EXPECT_TRUE("hello" <= o4); + EXPECT_TRUE(o4 >= "hello"); + EXPECT_TRUE("hello" >= o4); + } +} + +TEST(OptionalRefTest, Triviality) { + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + } + + { + struct T { + T(const T&) {} + T(T&&){}; + T& operator=(const T&) { return *this; } + T& operator=(T&&) { return *this; }; + ~T() {} + }; + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + } +} + +TEST(OptionalRefTest, Deletion) { + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = delete; + T& operator=(const T&) = delete; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = default; + T& operator=(const T&) = delete; + T& operator=(T&&) = default; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = default; + T(T&&) = delete; + T& operator=(const T&) = default; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + } +} + +struct takes_init_and_variadic { + std::vector v; + std::tuple t; + template + takes_init_and_variadic(std::initializer_list l, Args&&... args) : v(l), t(std::forward(args)...) {} +}; + +TEST(OptionalRefTest, MakeOptional) { + int var{42}; + auto o1 = beman::optional::make_optional(var); + auto o2 = beman::optional::optional(var); + + constexpr bool is_same = std::is_same>::value; + EXPECT_TRUE(is_same); + EXPECT_TRUE(o1 == o2); + + std::tuple tvar{0, 1, 2, 3}; + auto o3 = beman::optional::make_optional&>(tvar); + EXPECT_TRUE(std::get<0>(*o3) == 0); + EXPECT_TRUE(std::get<1>(*o3) == 1); + EXPECT_TRUE(std::get<2>(*o3) == 2); + EXPECT_TRUE(std::get<3>(*o3) == 3); + + std::vector ivec{0, 1, 2, 3}; + auto o4 = beman::optional::make_optional&>(ivec); + EXPECT_TRUE(o4.value()[0] == 0); + EXPECT_TRUE(o4.value()[1] == 1); + EXPECT_TRUE(o4.value()[2] == 2); + EXPECT_TRUE(o4.value()[3] == 3); + + takes_init_and_variadic tiv{{0, 1}, 2, 3}; + auto o5 = beman::optional::make_optional(tiv); + EXPECT_TRUE(o5->v[0] == 0); + EXPECT_TRUE(o5->v[1] == 1); + EXPECT_TRUE(std::get<0>(o5->t) == 2); + EXPECT_TRUE(std::get<1>(o5->t) == 3); + + auto i = 42; + auto o6 = beman::optional::make_optional(i); + static_assert(std::is_same_v>); + + EXPECT_TRUE((std::is_same_v>)); + EXPECT_TRUE(o6); + EXPECT_TRUE(*o6 == 42); +} + +TEST(OptionalRefTest, Nullopt) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2{beman::optional::nullopt}; + beman::optional::optional o3(beman::optional::nullopt); + beman::optional::optional o4 = {beman::optional::nullopt}; + + EXPECT_TRUE(!o1); + EXPECT_TRUE(!o2); + EXPECT_TRUE(!o3); + EXPECT_TRUE(!o4); + + EXPECT_TRUE(!std::is_default_constructible::value); +} + +struct move_detector { + move_detector() = default; + move_detector(move_detector&& rhs) { rhs.been_moved = true; } + bool been_moved = false; +}; + +TEST(OptionalRefTest, Observers) { + int var = 42; + beman::optional::optional o1 = var; + beman::optional::optional o2; + const beman::optional::optional o3 = var; + const beman::optional::optional o4; + int var2 = 42; + int var3 = 6*9; + EXPECT_TRUE(*o1 == 42); + EXPECT_TRUE(*o1 == o1.value()); + EXPECT_TRUE(o2.value_or(var2) == 42); + EXPECT_TRUE(o3.value() == 42); + EXPECT_TRUE(o3.value_or(var3) == 42); + EXPECT_TRUE(o4.value_or(var3) == 54); + int j = 99; + EXPECT_TRUE(o4.value_or(j) == 99); + // o4.value_or(j) = 88; + // EXPECT_TRUE(j == 88); + int var99 = 99; + j = 88; + EXPECT_TRUE([&](){beman::optional::optional o(j);return o; }().value_or(var99) == 88); + + EXPECT_TRUE([&](){beman::optional::optional o;return o; }().value_or(var99) == 99); + + + EXPECT_TRUE(o3.value_or([&]()->int&{return var3;}()) == 42); + EXPECT_TRUE(o4.value_or([&]()->int&{return var3;}()) == 54); + + std::string meow{"meow"}; + std::string bark{"bark"}; + beman::optional::optional so1; + beman::optional::optional so2{meow}; + auto t1 = so1.value_or(bark); + auto t2 = so2.value_or(bark); + // auto t3 = so1.value_or("bark"); + // auto t4 = so2.value_or("bark"); + // std::tuple t("meow"); + + auto success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + + struct int_box {int i_;}; + int_box i1{3}; + beman::optional::optional ob1 = i1; + beman::optional::optional ob2; + const beman::optional::optional ob3 = i1; + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + +} + +TEST(OptionalRefTest, MoveCheck) { + int x = 0; + int& y = std::move(beman::optional::optional(x)).value(); + EXPECT_EQ(&y, &x); + + int& z = *std::move(beman::optional::optional(x)); + EXPECT_EQ(&z, &x); + +} + +TEST(OptionalRefTest, SwapValue) { + int var = 42; + int twelve = 12; + beman::optional::optional o1 = var; + beman::optional::optional o2 = twelve; + o1.swap(o2); + EXPECT_EQ(o1.value(), 12); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalRefTest, SwapWNull) { + int var = 42; + + beman::optional::optional o1 = var; + beman::optional::optional o2 = beman::optional::nullopt; + o1.swap(o2); + EXPECT_TRUE(!o1.has_value()); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalRefTest, SwapNullIntializedWithValue) { + int var = 42; + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = var; + o1.swap(o2); + EXPECT_EQ(o1.value(), 42); + EXPECT_TRUE(!o2.has_value()); +} diff --git a/src/beman/optional/optional_ref_monadic.t.cpp b/src/beman/optional/optional_ref_monadic.t.cpp new file mode 100644 index 00000000..9d9f9fda --- /dev/null +++ b/src/beman/optional/optional_ref_monadic.t.cpp @@ -0,0 +1,318 @@ +#include + +#include + +namespace { +inline constexpr int constexpr_fortytwo = 42; +constexpr int get_int(int) { return constexpr_fortytwo; } +constexpr beman::optional::optional get_opt_int(int) { return constexpr_fortytwo; } +} // namespace + +TEST(OptionalRefMonadicTest, Transform) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int forty = 40; + beman::optional::optional o2 = forty; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o3 = fortytwo; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // // ensure that lhs is forwarded + // forty = 40; + // beman::optional::optional o4 = forty; + // auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + forty = 40; + const beman::optional::optional o5 = forty; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + fortytwo = 42; + beman::optional::optional o8 = fortytwo; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = fortytwo; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = fortytwo; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = fortytwo; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + + // callable which returns a reference + beman::optional::optional o38 = fortytwo; + auto o38r = o38.transform([](int& i) -> const int& { return i; }); + EXPECT_TRUE(o38r); + EXPECT_TRUE(*o38r == 42); +} + +TEST(OptionalRefMonadicTest, TransformConstexpr) { + + // test each overload in turn + constexpr beman::optional::optional o16 = constexpr_fortytwo; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = constexpr_fortytwo; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); +} + +TEST(OptionalRefMonadicTest, Transform2) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int forty = 40; + beman::optional::optional o2 = forty; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o3 = fortytwo; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // // ensure that lhs is forwarded + // int forty = 40; + // beman::optional::optional o4 = forty; + // auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + forty = 40; + const beman::optional::optional o5 = forty; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + fortytwo = 42; + beman::optional::optional o8 = fortytwo; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = fortytwo; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = fortytwo; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = fortytwo; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); +} + +TEST(OptionalRefMonadicTest, TransformConstxpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = constexpr_fortytwo; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = constexpr_fortytwo; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); +} + +TEST(OptionalRefMonadicTest, and_then) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int twelve = 12; + beman::optional::optional o2 = twelve; + auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42.f); + + // lhs is empty, rhs returns empty + beman::optional::optional o3; + auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o3r); + + // rhs returns empty + beman::optional::optional o4 = twelve; + auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o4r); + + struct rval_call_and_then { + beman::optional::optional operator()(int) && { return beman::optional::optional(42.0); }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o5 = fortytwo; + auto o5r = o5.and_then(rval_call_and_then{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // // ensure that lhs is forwarded + // beman::optional::optional o6 = fortytwo; + // auto o6r = + // std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o6r.value() == 42); + + // ensure that function object is const-propagated + const beman::optional::optional o7 = fortytwo; + auto o7r = o7.and_then([](const int& i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o7r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = fortytwo; + auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o9 = fortytwo; + auto o9r = std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o9r == 42); + + const beman::optional::optional o10 = fortytwo; + auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o10r == 42); + + const beman::optional::optional o11 = fortytwo; + auto o11r = std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o11r == 42); + + beman::optional::optional o16 = beman::optional::nullopt; + auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o16r); + + beman::optional::optional o17 = beman::optional::nullopt; + auto o17r = std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o17r); + + const beman::optional::optional o18 = beman::optional::nullopt; + auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o18r); + + const beman::optional::optional o19 = beman::optional::nullopt; + auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o19r); + + int i = 3; + beman::optional::optional o20{i}; + std::move(o20).and_then([](int& r) { return beman::optional::optional{++r}; }); + EXPECT_TRUE(o20); + EXPECT_TRUE(i == 4); +} + +TEST(OptionalRefMonadicTest, Constexpr_and_then) { + constexpr beman::optional::optional o10 = constexpr_fortytwo; + constexpr auto o10r = o10.and_then(get_opt_int); + EXPECT_TRUE(*o10r == 42); + + constexpr beman::optional::optional o11 = constexpr_fortytwo; + constexpr auto o11r = std::move(o11).and_then(get_opt_int); + EXPECT_TRUE(*o11r == 42); + + constexpr beman::optional::optional o18 = beman::optional::nullopt; + constexpr auto o18r = o18.and_then(get_opt_int); + EXPECT_TRUE(!o18r); + + constexpr beman::optional::optional o19 = beman::optional::nullopt; + constexpr auto o19r = std::move(o19).and_then(get_opt_int); + EXPECT_TRUE(!o19r); +} + +TEST(OptionalRefMonadicTest, or_else) { + int fortytwo = 42; + int thirteen = 13; + beman::optional::optional o1 = fortytwo; + EXPECT_TRUE(*(o1.or_else([&] { return beman::optional::optional(thirteen); })) == 42); + + beman::optional::optional o2; + EXPECT_EQ(*(o2.or_else([&] { return beman::optional::optional(thirteen); })), 13); +} diff --git a/src/beman/optional/tests/optional.t.cpp b/src/beman/optional/tests/optional.t.cpp new file mode 100644 index 00000000..9da8715d --- /dev/null +++ b/src/beman/optional/tests/optional.t.cpp @@ -0,0 +1,1278 @@ +#include + +#include // test 2nd include OK + +#include +#include +#include + +#include + +TEST(OptionalTest, TestGTest) { ASSERT_EQ(1, 1); } + +namespace { +struct empty {}; +struct no_default { + no_default() = delete; + no_default(const no_default&) = default; + no_default(no_default&&) = default; + no_default& operator=(const no_default&) = default; + no_default& operator=(no_default&&) = default; + no_default(empty){}; +}; + +struct base { + int i_; + base() : i_(0) {} + base(int i) : i_(i) {} +}; + +struct derived : public base { + int j_; + derived() : base(0), j_(0) {} + derived(int i, int j) : base(i), j_(j) {} +}; +} // namespace + +TEST(OptionalTest, Constructors) { + beman::optional::optional i1; + beman::optional::optional i2{beman::optional::nullopt}; + + int i = 0; + beman::optional::optional i3 = i; + (void)i3; + + beman::optional::optional e1; + beman::optional::optional e2{beman::optional::nullopt}; + + empty e{}; + beman::optional::optional e3 = e; + (void)e3; +} + + +TEST(OptionalTest, Constructors2) { + beman::optional::optional o1; + EXPECT_TRUE(!o1); + + beman::optional::optional o2 = beman::optional::nullopt; + EXPECT_TRUE(!o2); + + beman::optional::optional o3 = 42; + EXPECT_TRUE(*o3 == 42); + + beman::optional::optional o4 = o3; + EXPECT_TRUE(*o4 == 42); + + beman::optional::optional o5 = o1; + EXPECT_TRUE(!o5); + + beman::optional::optional o6 = std::move(o3); + EXPECT_TRUE(*o6 == 42); + + beman::optional::optional o7 = 42; + EXPECT_TRUE(*o7 == 42); + + beman::optional::optional o8 = o7; + EXPECT_TRUE(*o8 == 42); + + beman::optional::optional o9 = std::move(o7); + EXPECT_TRUE(*o9 == 42); + + { + beman::optional::optional o; + EXPECT_TRUE(!o); + + beman::optional::optional oo = o; + EXPECT_TRUE(!oo); + } + + { + auto i = 42; + beman::optional::optional o = i; + EXPECT_TRUE(o); + EXPECT_TRUE(*o == 42); + + beman::optional::optional oo = o; + EXPECT_TRUE(oo); + EXPECT_TRUE(*oo == 42); + } + + std::vector v; + v.emplace_back(); + beman::optional::optional> ov = std::move(v); + EXPECT_TRUE(ov->size() == 1); +} + +TEST(OptionalTest, Constructors3) { + beman::optional::optional ie; + beman::optional::optional i4 = ie; + EXPECT_FALSE(i4); + + base b{1}; + derived d(1, 2); + beman::optional::optional b1{b}; + beman::optional::optional b2{d}; + + beman::optional::optional d2{d}; + beman::optional::optional b3 = d2; + beman::optional::optional b4{d2}; +} + +namespace { +class NoDefault { + int v_; + + public: + NoDefault(int v) : v_(v) {} +}; +} // namespace + +TEST(OptionalTest, NonDefaultConstruct) { + NoDefault i = 7; + beman::optional::optional v1{}; + beman::optional::optional v2{i}; +} + +TEST(OptionalTest, AssignmentValue) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = 12; + beman::optional::optional o3; + + o1 = o1; + EXPECT_TRUE(*o1 == 42); + + o1 = o2; + EXPECT_TRUE(*o1 == 12); + + o1 = o3; + EXPECT_TRUE(!o1); + + o1 = 42; + EXPECT_TRUE(*o1 == 42); + + o1 = beman::optional::nullopt; + EXPECT_TRUE(!o1); + + o1 = std::move(o2); + EXPECT_TRUE(*o1 == 12); + + beman::optional::optional o4 = 42; + + o1 = o4; + EXPECT_TRUE(*o1 == 42); + + o1 = std::move(o4); + EXPECT_TRUE(*o1 == 42); +} + +TEST(OptionalTest, Triviality) { + EXPECT_TRUE(std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE( + std::is_trivially_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE( + std::is_trivially_destructible>::value); + } + + { + struct T { + T(const T&) {} + T(T&&){}; + T& operator=(const T&) { return *this; } + T& operator=(T&&) { return *this; }; + ~T() {} + }; + EXPECT_TRUE(!std::is_trivially_copy_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_copy_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_move_constructible< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_move_assignable< + beman::optional::optional>::value); + EXPECT_TRUE(!std::is_trivially_destructible< + beman::optional::optional>::value); + } +} + +TEST(OptionalTest, Deletion) { + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE( + std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE( + std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = delete; + T& operator=(const T&) = delete; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE( + !std::is_copy_constructible>::value); + EXPECT_TRUE( + !std::is_copy_assignable>::value); + EXPECT_TRUE( + !std::is_move_constructible>::value); + EXPECT_TRUE( + !std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = default; + T& operator=(const T&) = delete; + T& operator=(T&&) = default; + }; + EXPECT_TRUE( + !std::is_copy_constructible>::value); + EXPECT_TRUE( + !std::is_copy_assignable>::value); + EXPECT_TRUE( + std::is_move_constructible>::value); + EXPECT_TRUE( + std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = default; + T(T&&) = delete; + T& operator=(const T&) = default; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE( + std::is_copy_constructible>::value); + EXPECT_TRUE( + std::is_copy_assignable>::value); + } +} + +struct takes_init_and_variadic { + std::vector v; + std::tuple t; + template + takes_init_and_variadic(std::initializer_list l, Args&&... args) + : v(l), t(std::forward(args)...) {} +}; + +TEST(OptionalTest, InPlace) { + beman::optional::optional o1{beman::optional::in_place}; + beman::optional::optional o2(beman::optional::in_place); + EXPECT_TRUE(o1); + EXPECT_TRUE(o1 == 0); + EXPECT_TRUE(o2); + EXPECT_TRUE(o2 == 0); + + beman::optional::optional o3(beman::optional::in_place, 42); + EXPECT_TRUE(o3 == 42); + + beman::optional::optional> o4( + beman::optional::in_place, 0, 1); + EXPECT_TRUE(o4); + EXPECT_TRUE(std::get<0>(*o4) == 0); + EXPECT_TRUE(std::get<1>(*o4) == 1); + + beman::optional::optional> o5(beman::optional::in_place, + {0, 1}); + EXPECT_TRUE(o5); + EXPECT_TRUE((*o5)[0] == 0); + EXPECT_TRUE((*o5)[1] == 1); + + beman::optional::optional o6( + beman::optional::in_place, {0, 1}, 2, 3); + EXPECT_TRUE(o6->v[0] == 0); + EXPECT_TRUE(o6->v[1] == 1); + EXPECT_TRUE(std::get<0>(o6->t) == 2); + EXPECT_TRUE(std::get<1>(o6->t) == 3); +} + +TEST(OptionalTest, MakeOptional) { + auto o1 = beman::optional::make_optional(42); + auto o2 = beman::optional::optional(42); + + constexpr bool is_same = + std::is_same>::value; + EXPECT_TRUE(is_same); + EXPECT_TRUE(o1 == o2); + + auto o3 = beman::optional::make_optional>( + 0, 1, 2, 3); + EXPECT_TRUE(std::get<0>(*o3) == 0); + EXPECT_TRUE(std::get<1>(*o3) == 1); + EXPECT_TRUE(std::get<2>(*o3) == 2); + EXPECT_TRUE(std::get<3>(*o3) == 3); + + auto o4 = beman::optional::make_optional>({0, 1, 2, 3}); + EXPECT_TRUE(o4.value()[0] == 0); + EXPECT_TRUE(o4.value()[1] == 1); + EXPECT_TRUE(o4.value()[2] == 2); + EXPECT_TRUE(o4.value()[3] == 3); + + auto o5 = + beman::optional::make_optional({0, 1}, 2, 3); + EXPECT_TRUE(o5->v[0] == 0); + EXPECT_TRUE(o5->v[1] == 1); + EXPECT_TRUE(std::get<0>(o5->t) == 2); + EXPECT_TRUE(std::get<1>(o5->t) == 3); + + auto i = 42; + auto o6 = beman::optional::make_optional(i); + static_assert(std::is_same>::value); + + EXPECT_TRUE( + (std::is_same>::value)); + EXPECT_TRUE(o6); + EXPECT_TRUE(*o6 == 42); +} + +TEST(OptionalTest, Nullopt) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2{beman::optional::nullopt}; + beman::optional::optional o3(beman::optional::nullopt); + beman::optional::optional o4 = {beman::optional::nullopt}; + + EXPECT_TRUE(!o1); + EXPECT_TRUE(!o2); + EXPECT_TRUE(!o3); + EXPECT_TRUE(!o4); + + EXPECT_TRUE( + !std::is_default_constructible::value); +} + +struct move_detector { + move_detector() = default; + move_detector(move_detector&& rhs) { rhs.been_moved = true; } + bool been_moved = false; +}; + +TEST(OptionalTest, Observers) { + beman::optional::optional o1 = 42; + beman::optional::optional o2; + const beman::optional::optional o3 = 42; + + EXPECT_TRUE(*o1 == 42); + EXPECT_TRUE(*o1 == o1.value()); + EXPECT_TRUE(o2.value_or(42) == 42); + EXPECT_TRUE(o3.value() == 42); + auto success = std::is_same::value; + EXPECT_TRUE(success); + success = std::is_same::value; + EXPECT_TRUE(success); + success = std::is_same::value; + EXPECT_TRUE(success); + + beman::optional::optional o4{beman::optional::in_place}; + move_detector o5 = std::move(o4).value(); + EXPECT_TRUE(o4->been_moved); + EXPECT_TRUE(!o5.been_moved); +} + +TEST(OptionalTest, RelationalOps) { + beman::optional::optional o1{4}; + beman::optional::optional o2{42}; + beman::optional::optional o3{}; + + // SECTION("self simple") + { + EXPECT_TRUE(!(o1 == o2)); + EXPECT_TRUE(o1 == o1); + EXPECT_TRUE(o1 != o2); + EXPECT_TRUE(!(o1 != o1)); + EXPECT_TRUE(o1 < o2); + EXPECT_TRUE(!(o1 < o1)); + EXPECT_TRUE(!(o1 > o2)); + EXPECT_TRUE(!(o1 > o1)); + EXPECT_TRUE(o1 <= o2); + EXPECT_TRUE(o1 <= o1); + EXPECT_TRUE(!(o1 >= o2)); + EXPECT_TRUE(o1 >= o1); + } + // SECTION("nullopt simple") + { + EXPECT_TRUE(!(o1 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o1)); + EXPECT_TRUE(o1 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o1); + EXPECT_TRUE(!(o1 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o1); + EXPECT_TRUE(o1 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o1)); + EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o1); + EXPECT_TRUE(o1 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o1)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + // SECTION("with T simple") + { + EXPECT_TRUE(!(o1 == 1)); + EXPECT_TRUE(!(1 == o1)); + EXPECT_TRUE(o1 != 1); + EXPECT_TRUE(1 != o1); + EXPECT_TRUE(!(o1 < 1)); + EXPECT_TRUE(1 < o1); + EXPECT_TRUE(o1 > 1); + EXPECT_TRUE(!(1 > o1)); + EXPECT_TRUE(!(o1 <= 1)); + EXPECT_TRUE(1 <= o1); + EXPECT_TRUE(o1 >= 1); + EXPECT_TRUE(!(1 >= o1)); + + EXPECT_TRUE(o1 == 4); + EXPECT_TRUE(4 == o1); + EXPECT_TRUE(!(o1 != 4)); + EXPECT_TRUE(!(4 != o1)); + EXPECT_TRUE(!(o1 < 4)); + EXPECT_TRUE(!(4 < o1)); + EXPECT_TRUE(!(o1 > 4)); + EXPECT_TRUE(!(4 > o1)); + EXPECT_TRUE(o1 <= 4); + EXPECT_TRUE(4 <= o1); + EXPECT_TRUE(o1 >= 4); + EXPECT_TRUE(4 >= o1); + } + beman::optional::optional o4{"hello"}; + beman::optional::optional o5{"xyz"}; + + // SECTION("self complex") + { + EXPECT_TRUE(!(o4 == o5)); + EXPECT_TRUE(o4 == o4); + EXPECT_TRUE(o4 != o5); + EXPECT_TRUE(!(o4 != o4)); + EXPECT_TRUE(o4 < o5); + EXPECT_TRUE(!(o4 < o4)); + EXPECT_TRUE(!(o4 > o5)); + EXPECT_TRUE(!(o4 > o4)); + EXPECT_TRUE(o4 <= o5); + EXPECT_TRUE(o4 <= o4); + EXPECT_TRUE(!(o4 >= o5)); + EXPECT_TRUE(o4 >= o4); + } + // SECTION("nullopt complex") + { + EXPECT_TRUE(!(o4 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o4)); + EXPECT_TRUE(o4 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o4); + EXPECT_TRUE(!(o4 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o4); + EXPECT_TRUE(o4 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o4)); + EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o4); + EXPECT_TRUE(o4 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o4)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + + // SECTION("with T complex") + { + EXPECT_TRUE(!(o4 == "a")); + EXPECT_TRUE(!("a" == o4)); + EXPECT_TRUE(o4 != "a"); + EXPECT_TRUE("a" != o4); + EXPECT_TRUE(!(o4 < "a")); + EXPECT_TRUE("a" < o4); + EXPECT_TRUE(o4 > "a"); + EXPECT_TRUE(!("a" > o4)); + EXPECT_TRUE(!(o4 <= "a")); + EXPECT_TRUE("a" <= o4); + EXPECT_TRUE(o4 >= "a"); + EXPECT_TRUE(!("a" >= o4)); + + EXPECT_TRUE(o4 == "hello"); + EXPECT_TRUE("hello" == o4); + EXPECT_TRUE(!(o4 != "hello")); + EXPECT_TRUE(!("hello" != o4)); + EXPECT_TRUE(!(o4 < "hello")); + EXPECT_TRUE(!("hello" < o4)); + EXPECT_TRUE(!(o4 > "hello")); + EXPECT_TRUE(!("hello" > o4)); + EXPECT_TRUE(o4 <= "hello"); + EXPECT_TRUE("hello" <= o4); + EXPECT_TRUE(o4 >= "hello"); + EXPECT_TRUE("hello" >= o4); + } +} + +TEST(OptionalTest, SwapValue) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = 12; + o1.swap(o2); + EXPECT_EQ(o1.value(), 12); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalTest, SwapWNull) { + beman::optional::optional o1 = 42; + beman::optional::optional o2 = beman::optional::nullopt; + o1.swap(o2); + EXPECT_TRUE(!o1.has_value()); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalTest, SwapNullIntializedWithValue) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = 42; + o1.swap(o2); + EXPECT_EQ(o1.value(), 42); + EXPECT_TRUE(!o2.has_value()); +} + +TEST(OptionalTest, Emplace) { + beman::optional::optional< + std::pair, std::pair>> + i; + i.emplace(std::piecewise_construct, + std::make_tuple(0, 2), + std::make_tuple(3, 4)); + EXPECT_TRUE(i->first.first == 0); + EXPECT_TRUE(i->first.second == 2); + EXPECT_TRUE(i->second.first == 3); + EXPECT_TRUE(i->second.second == 4); +} + +struct A { + A() { throw std::exception(); } +}; + +TEST(OptionalTest, EmplaceWithExceptionThrown) { + beman::optional::optional a; + EXPECT_ANY_THROW(a.emplace()); +} + +TEST(OptionalTest, RangeTest) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = 42; + EXPECT_EQ(*o2, 42); + for(auto k : o1) { + (void)k; + EXPECT_TRUE(false); + } + for(auto k : o2) { + EXPECT_EQ(k, 42); + } +} + +TEST(ViewMaybeTest, Constructors) { + std::ranges::single_view> s; + std::ranges::single_view> s2{s}; + std::ranges::single_view> s3{std::optional{}}; + + beman::optional::optional> n; + beman::optional::optional> n2{n}; + beman::optional::optional> n3{std::optional{}}; +} + +TEST(ViewMaybeTest, ConceptCheck) { + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(!std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + static_assert(std::ranges::sized_range>); + + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + using ref = std::reference_wrapper; + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); +} + +TEST(ViewMaybeTest, ConceptCheckRef) { + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + using ref = std::reference_wrapper&; + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); +} + +TEST(ViewMaybeTest, BreathingTest) { + beman::optional::optional m; + // ASSERT_TRUE(m.empty()); + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m.data() == nullptr); + + beman::optional::optional m1{1}; + // ASSERT_TRUE(!m1.empty()); + // ASSERT_TRUE(m1.size() == 1); + // ASSERT_TRUE(m1.data() != nullptr); + // ASSERT_TRUE(*(m1.data()) == 1); + + m = m1; + ASSERT_EQ(*std::begin(m), 1); + + m = {}; + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m1.size() == 1); + + beman::optional::optional d0{0}; + // ASSERT_TRUE(!d0.empty()); + + beman::optional::optional d1{1}; + // ASSERT_TRUE(!d1.empty()); + + d0 = d1; + ASSERT_EQ(*std::begin(d0), 1.0); +} + +TEST(ViewMaybeTest, BreathingTestRef) { + beman::optional::optional m; + // ASSERT_TRUE(m.empty()); + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m.data() == nullptr); + + int one = 1; + beman::optional::optional m1{one}; + // ASSERT_TRUE(!m1.empty()); + // ASSERT_TRUE(m1.size() == 1); + // ASSERT_TRUE(m1.data() != nullptr); + // ASSERT_TRUE(*(m1.data()) == 1); + + m = m1; + ASSERT_EQ(*std::begin(m), 1); + + // m = {}; + // ASSERT_TRUE(m.size() == 0); + // ASSERT_TRUE(m1.size() == 1); + + double zero = 0.0; + beman::optional::optional d0{zero}; + // ASSERT_TRUE(!d0.empty()); + + double one_d = 1.0; + beman::optional::optional d1{one_d}; + // ASSERT_TRUE(!d1.empty()); + + d0 = d1; + ASSERT_EQ(*std::begin(d0), 1.0); +} + +TEST(ViewMaybe, CompTest) { + beman::optional::optional m; + beman::optional::optional m0{0}; + beman::optional::optional m1{1}; + beman::optional::optional m1a{1}; + + ASSERT_EQ(m, m); + ASSERT_EQ(m0, m0); + ASSERT_EQ(m1, m1); + ASSERT_EQ(m1a, m1a); + ASSERT_EQ(m1, m1a); + + ASSERT_NE(m, m0); + ASSERT_NE(m0, m1); + + ASSERT_TRUE(m < m0); + ASSERT_TRUE(m0 < m1); + ASSERT_TRUE(m1 <= m1a); +} + +TEST(ViewMaybe, CompTestRef) { + beman::optional::optional m; + int zero = 0; + int one = 1; + int one_a = 1; + beman::optional::optional m0{zero}; + beman::optional::optional m1{one}; + beman::optional::optional m1a{one_a}; + + ASSERT_EQ(m, m); + ASSERT_EQ(m0, m0); + ASSERT_EQ(m1, m1); + ASSERT_EQ(m1a, m1a); + ASSERT_EQ(m1, m1a); + + ASSERT_NE(m, m0); + ASSERT_NE(m0, m1); + + ASSERT_TRUE(m < m0); + ASSERT_TRUE(m0 > m); + ASSERT_TRUE(m0 < m1); + ASSERT_TRUE(m1a <= m1); +} + +// "and_then" creates a new view by applying a +// transformation to each element in an input +// range, and flattening the resulting range of +// ranges. A.k.a. bind +// (This uses one syntax for constrained lambdas +// in C++20.) +inline constexpr auto and_then = [](auto&& r, auto fun) { + return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | + std::ranges::views::join; +}; + +// "yield_if" takes a bool and a value and +// returns a view of zero or one elements. +inline constexpr auto yield_if = [](bool b, T x) { + return b ? + beman::optional::optional{move(x)} : + beman::optional::nullopt; +}; + + +TEST(ViewMaybeTest, PythTripleTest) { + using std::ranges::views::iota; + auto triples = and_then(iota(1), [](int z) { + return and_then(iota(1, z + 1), [=](int x) { + return and_then(iota(x, z + 1), [=](int y) { + return yield_if(x * x + y * y == z * z, + std::make_tuple(x, y, z)); + }); + }); + }); + + ASSERT_EQ(*std::ranges::begin(triples), std::make_tuple(3, 4, 5)); +} + +using namespace beman; + +TEST(ViewMaybeTest, ValueBase) { + int i = 7; + beman::optional::optional v1{}; + // ASSERT_TRUE(v1.size() == 0); + + beman::optional::optional v2{i}; + // ASSERT_TRUE(v2.size() == 1); + for (auto i : v1) + ASSERT_TRUE(i != i); // tautology so i is used and not warned + + + for (auto i : v2) + ASSERT_EQ(i, 7); + +// ASSERT_EQ(v2[0], 7); // no match for operator[] +// auto x = v2[1000]; + + // int s = 4; + // for (auto&& i : views::maybe(s)) { + // ASSERT_EQ(i, 4); + // i = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 4); +} + +TEST(ViewMaybeTest, RefWrapper) { + int i = 7; + + beman::optional::optional v2{std::ref(i)}; + + for (auto i : v2) + ASSERT_EQ(i, 7); + + // int s = 4; + // for (auto&& i : views::maybe(std::ref(s))) { + // ASSERT_EQ(i, 4); + // i.get() = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 9); +} + + +TEST(ViewMaybeTest, ValueNonDefaultConstruct) { + NoDefault i = 7; + beman::optional::optional v1{}; + beman::optional::optional v2{i}; +} + +TEST(ViewMaybeTest, RefBase) { + int i = 7; + beman::optional::optional v1{}; + // ASSERT_TRUE(v1.size() == 0); + + beman::optional::optional v2{i}; + // ASSERT_TRUE(v2.size() == 1); + for (auto i : v1) + ASSERT_TRUE(i != i); // tautology so i is used and not warned + + for (auto i : v2) { + ASSERT_EQ(i, 7); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(i, 7); + + for (auto&& i : v2) { + ASSERT_EQ(i, 7); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(i, 9); + + int s = 4; + // for (auto&& i : views::maybe(s)) { + // ASSERT_EQ(i, 4); + // i = 9; + // ASSERT_EQ(i, 9); + // } + // ASSERT_EQ(s, 4); + + for (auto&& i : beman::optional::optional(s)) { + ASSERT_EQ(i, 4); + i = 9; + ASSERT_EQ(i, 9); + } + ASSERT_EQ(s, 9); +} + +// TEST(ViewMaybeTest, MonadicAndThen) { +// beman::optional::optional mv{40}; +// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); +// ASSERT_TRUE(r2.empty()); +// ASSERT_TRUE(r2.size() == 0); +// ASSERT_TRUE(r2.data() == nullptr); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).and_then([](int&& i) { +// int k = i; +// i = 0; +// return beman::optional::optional{k + 2}; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); + +// const beman::optional::optional cmv{40}; +// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicTransform) { +// beman::optional::optional mv{40}; +// auto r = mv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.transform([](int& i) { +// i += 2; +// return i; +// }); +// ASSERT_TRUE(!r2.empty()); +// ASSERT_TRUE(r2.size() == 1); +// ASSERT_TRUE(r2.data() != nullptr); +// ASSERT_TRUE(*(r2.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 42); + +// beman::optional::optional empty{}; + +// auto r3 = empty.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.transform([](double d) { return d + 2; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 44.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 44); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 42); + +// auto r6 = std::move(mv).transform([](int&& i) { +// int k = i; +// i = 0; +// return k + 2; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 44); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); + +// const beman::optional::optional cmv{40}; +// auto r7 = cmv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicOrElse) { +// beman::optional::optional o1(42); +// auto r = o1.or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r.data()) == 42); + +// beman::optional::optional o2; +// ASSERT_TRUE(*(o2.or_else([] { return beman::optional::optional(13); })).data() == +// 13); + +// auto r2 = std::move(o1).or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r2.data()) == 42); + +// auto r3 = std::move(o2).or_else([] { return beman::optional::optional(13); }); +// ASSERT_TRUE(*(r3.data()) == 13); +// } + +// TEST(ViewMaybeTest, MonadicAndThenRef) { +// int forty{40}; +// beman::optional::optional mv{forty}; +// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_TRUE(*(r.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); +// ASSERT_TRUE(r2.empty()); +// ASSERT_TRUE(r2.size() == 0); +// ASSERT_TRUE(r2.data() == nullptr); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).and_then([](int&& i) { +// int k = i; +// i = 0; +// return beman::optional::optional{k + 2}; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); +// ASSERT_EQ(forty, 0); +// forty = 40; + +// const beman::optional::optional cmv{forty}; +// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_EQ(*(r7.data()), 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_EQ(*(r8.data()), 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); +// } + +// TEST(MaybeView, MonadicTransformRef) { +// int forty{40}; +// beman::optional::optional mv{forty}; +// auto r = mv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r.empty()); +// ASSERT_TRUE(r.size() == 1); +// ASSERT_TRUE(r.data() != nullptr); +// ASSERT_EQ(*(r.data()), 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// beman::optional::optional empty{}; + +// auto r3 = empty.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(r3.empty()); +// ASSERT_TRUE(r3.size() == 0); +// ASSERT_TRUE(r3.data() == nullptr); +// ASSERT_TRUE(empty.empty()); + +// auto r4 = mv.transform([](double d) { return d + 2; }); +// ASSERT_TRUE(!r4.empty()); +// ASSERT_TRUE(r4.size() == 1); +// ASSERT_TRUE(*(r4.data()) == 42.0); +// static_assert(std::is_same_v>); + +// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r5.empty()); +// ASSERT_TRUE(r5.size() == 1); +// ASSERT_TRUE(r5.data() != nullptr); +// ASSERT_TRUE(*(r5.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 40); + +// auto r6 = std::move(mv).transform([](int&& i) { +// int k = i; +// i = 0; +// return k + 2; +// }); +// ASSERT_TRUE(!r6.empty()); +// ASSERT_TRUE(r6.size() == 1); +// ASSERT_TRUE(r6.data() != nullptr); +// ASSERT_TRUE(*(r6.data()) == 42); +// ASSERT_TRUE(!mv.empty()); +// ASSERT_TRUE(*(mv.data()) == 0); +// ASSERT_EQ(forty, 0); +// forty = 40; + +// const beman::optional::optional cmv{forty}; +// ASSERT_EQ(*(cmv.data()), 40); +// auto r7 = cmv.transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r7.empty()); +// ASSERT_TRUE(r7.size() == 1); +// ASSERT_TRUE(r7.data() != nullptr); +// ASSERT_TRUE(*(r7.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); +// ASSERT_TRUE(!r8.empty()); +// ASSERT_TRUE(r8.size() == 1); +// ASSERT_TRUE(r8.data() != nullptr); +// ASSERT_TRUE(*(r8.data()) == 42); +// ASSERT_TRUE(!cmv.empty()); +// ASSERT_TRUE(*(cmv.data()) == 40); + +// auto r9 = mv.transform([](int& i) { +// int k = i; +// i = 56; +// return k * 2; +// }); +// ASSERT_TRUE(!r9.empty()); +// ASSERT_EQ(r9.size(), 1); +// ASSERT_TRUE(r9.data() != nullptr); +// for (auto r: r9) { +// ASSERT_EQ(r, 80); +// } +// ASSERT_TRUE(!mv.empty()); +// for (auto v: mv) { +// ASSERT_EQ(v, 56); +// } +// ASSERT_EQ(forty, 56); +// forty = 40; +// } + +// TEST(MaybeView, MonadicOrElseRef) { +// int fortytwo{42}; +// int thirteen{13}; +// beman::optional::optional o1(fortytwo); +// auto r = o1.or_else([&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r.data()) == 42); + +// beman::optional::optional o2; +// ASSERT_TRUE(*(o2.or_else([&thirteen] { +// return beman::optional::optional(thirteen); +// })).data() == 13); + +// auto r2 = std::move(o1).or_else( +// [&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r2.data()) == 42); + +// auto r3 = std::move(o2).or_else( +// [&thirteen] { return beman::optional::optional(thirteen); }); +// ASSERT_TRUE(*(r3.data()) == 13); +// } diff --git a/src/beman/optional/tests/optional_monadic.t.cpp b/src/beman/optional/tests/optional_monadic.t.cpp new file mode 100644 index 00000000..79a1c6a7 --- /dev/null +++ b/src/beman/optional/tests/optional_monadic.t.cpp @@ -0,0 +1,311 @@ +#include + +#include + +constexpr int get_int(int) { return 42; } +constexpr beman::optional::optional get_opt_int(int) { return 42; } + + +TEST(OptionalMonadicTest, Transform) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 40; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + beman::optional::optional o3 = 42; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o4 = 40; + auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + const beman::optional::optional o5 = 40; + auto o5r = o5.transform([](const int &i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = 42; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = 42; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = 42; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + + // callable which returns a reference + beman::optional::optional o38 = 42; + auto o38r = o38.transform([](int &i) -> const int & { return i; }); + EXPECT_TRUE(o38r); + EXPECT_TRUE(*o38r == 42); + + } + + TEST(OptionalMonadicTest, TransformConstexpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = 42; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = 42; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); + } + +TEST(OptionalMonadicTest, Transform2) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 40; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + beman::optional::optional o3 = 42; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o4 = 40; + auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + const beman::optional::optional o5 = 40; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = 42; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = 42; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = 42; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + } + + TEST(OptionalMonadicTest, TransformConstxpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = 42; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = 42; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); + } + +TEST(OptionalMonadicTest, and_then) + { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + beman::optional::optional o2 = 12; + auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42.f); + + // lhs is empty, rhs returns empty + beman::optional::optional o3; + auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o3r); + + // rhs returns empty + beman::optional::optional o4 = 12; + auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o4r); + + struct rval_call_and_then { + beman::optional::optional operator()(int) && { + return beman::optional::optional(42.0); + }; + }; + + // ensure that function object is forwarded + beman::optional::optional o5 = 42; + auto o5r = o5.and_then(rval_call_and_then{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // ensure that lhs is forwarded + beman::optional::optional o6 = 42; + auto o6r = + std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o6r.value() == 42); + + // ensure that function object is const-propagated + const beman::optional::optional o7 = 42; + auto o7r = + o7.and_then([](const int &i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o7r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = 42; + auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o9 = 42; + auto o9r = + std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o9r == 42); + + const beman::optional::optional o10 = 42; + auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o10r == 42); + + const beman::optional::optional o11 = 42; + auto o11r = + std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o11r == 42); + + beman::optional::optional o16 = beman::optional::nullopt; + auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o16r); + + beman::optional::optional o17 = beman::optional::nullopt; + auto o17r = + std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o17r); + + const beman::optional::optional o18 = beman::optional::nullopt; + auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o18r); + + const beman::optional::optional o19 = beman::optional::nullopt; + auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o19r); + + int i = 3; + beman::optional::optional o20{i}; + std::move(o20).and_then([](int& r){return beman::optional::optional{++r};}); + EXPECT_TRUE(o20); + EXPECT_TRUE(i == 4); + } + +TEST(OptionalMonadicTest, Constexpr_and_then) +{ + constexpr beman::optional::optional o10 = 42; + constexpr auto o10r = o10.and_then(get_opt_int); + EXPECT_TRUE(*o10r == 42); + + constexpr beman::optional::optional o11 = 42; + constexpr auto o11r = std::move(o11).and_then(get_opt_int); + EXPECT_TRUE(*o11r == 42); + + constexpr beman::optional::optional o18 = beman::optional::nullopt; + constexpr auto o18r = o18.and_then(get_opt_int); + EXPECT_TRUE(!o18r); + + constexpr beman::optional::optional o19 = beman::optional::nullopt; + constexpr auto o19r = std::move(o19).and_then(get_opt_int); + EXPECT_TRUE(!o19r); + } + +TEST(OptionalMonadicTest, or_else){ + beman::optional::optional o1 = 42; + EXPECT_TRUE(*(o1.or_else([] { return beman::optional::make_optional(13); })) == 42); + + beman::optional::optional o2; + EXPECT_EQ(*(o2.or_else([] { return beman::optional::make_optional(13); })), 13); + } diff --git a/src/beman/optional/tests/optional_range_support.t.cpp b/src/beman/optional/tests/optional_range_support.t.cpp new file mode 100644 index 00000000..3e34ed14 --- /dev/null +++ b/src/beman/optional/tests/optional_range_support.t.cpp @@ -0,0 +1,9 @@ +#include + +#include +#include +#include +#include +#include +#include + diff --git a/src/beman/optional/tests/optional_ref.t.cpp b/src/beman/optional/tests/optional_ref.t.cpp new file mode 100644 index 00000000..3591256b --- /dev/null +++ b/src/beman/optional/tests/optional_ref.t.cpp @@ -0,0 +1,560 @@ +#include + +#include + +TEST(OptionalRefTest, TestGTest) { ASSERT_EQ(1, 1); } + +namespace { +struct empty {}; +struct no_default { + no_default() = delete; + no_default(const no_default&) = default; + no_default(no_default&&) = default; + no_default& operator=(const no_default&) = default; + no_default& operator=(no_default&&) = default; + no_default(empty){}; +}; + +struct base { + int i_; + base() : i_(0) {} + base(int i) : i_(i) {} +}; + +struct derived : public base { + int j_; + derived() : base(0), j_(0) {} + derived(int i, int j) : base(i), j_(j) {} +}; +} // namespace + +TEST(OptionalRefTest, Constructors) { + beman::optional::optional i1; + beman::optional::optional i2{beman::optional::nullopt}; + (void)i1; + (void)i2; + + int i = 0; + beman::optional::optional i3 = i; + (void)i3; + + beman::optional::optional e1; + beman::optional::optional e2{beman::optional::nullopt}; + (void)e1; + (void)e2; + + empty e{}; + beman::optional::optional e3 = e; + (void)e3; + + beman::optional::optional nd1; + beman::optional::optional nd2{beman::optional::nullopt}; + (void)nd1; + (void)nd2; + + no_default nd{e}; + + beman::optional::optional nd3 = nd; + (void)nd3; + + beman::optional::optional ie; + beman::optional::optional i4 = ie; + EXPECT_FALSE(i4); + + base b{1}; + derived d(1, 2); + beman::optional::optional b1 = b; + beman::optional::optional b2 = d; + + beman::optional::optional d2 = d; + beman::optional::optional b3 = d2; + beman::optional::optional b4{d2}; + + beman::optional::optional empty; + beman::optional::optional fromEmpty(empty); + beman::optional::optional fromEmpty2 = empty; +} + +TEST(OptionalRefTest, Assignment) { + beman::optional::optional i1; + EXPECT_FALSE(i1); + int i = 5; + i1 = i; + i = 7; + EXPECT_TRUE(i1); + EXPECT_TRUE(*i1 = 7); + + double d; + // i1 = d; // ill-formed by mandate + beman::optional::optional d1 = d; + // i1 = d1; // ill-formed by mandate + beman::optional::optional i2 = i1; + EXPECT_TRUE(i2); + EXPECT_TRUE(*i2 = 7); + + beman::optional::optional empty; + EXPECT_FALSE(empty); + i2 = empty; + EXPECT_FALSE(i2); + int eight = 8; + empty.emplace(eight); + EXPECT_TRUE(empty); + EXPECT_EQ(empty, 8); +} + +TEST(OptionalRefTest, RelationalOps) { + int i1 = 4; + int i2 = 42; + beman::optional::optional o1{i1}; + beman::optional::optional o2{i2}; + beman::optional::optional o3{}; + + // SECTION("self simple") + { + EXPECT_TRUE(!(o1 == o2)); + EXPECT_TRUE(o1 == o1); + EXPECT_TRUE(o1 != o2); + EXPECT_TRUE(!(o1 != o1)); + EXPECT_TRUE(o1 < o2); + EXPECT_TRUE(!(o1 < o1)); + EXPECT_TRUE(!(o1 > o2)); + EXPECT_TRUE(!(o1 > o1)); + EXPECT_TRUE(o1 <= o2); + EXPECT_TRUE(o1 <= o1); + EXPECT_TRUE(!(o1 >= o2)); + EXPECT_TRUE(o1 >= o1); + } + // SECTION("nullopt simple") + { + EXPECT_TRUE(!(o1 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o1)); + EXPECT_TRUE(o1 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o1); + EXPECT_TRUE(!(o1 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o1); + EXPECT_TRUE(o1 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o1)); + EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o1); + EXPECT_TRUE(o1 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o1)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + // SECTION("with T simple") + { + EXPECT_TRUE(!(o1 == 1)); + EXPECT_TRUE(!(1 == o1)); + EXPECT_TRUE(o1 != 1); + EXPECT_TRUE(1 != o1); + EXPECT_TRUE(!(o1 < 1)); + EXPECT_TRUE(1 < o1); + EXPECT_TRUE(o1 > 1); + EXPECT_TRUE(!(1 > o1)); + EXPECT_TRUE(!(o1 <= 1)); + EXPECT_TRUE(1 <= o1); + EXPECT_TRUE(o1 >= 1); + EXPECT_TRUE(!(1 >= o1)); + + EXPECT_TRUE(o1 == 4); + EXPECT_TRUE(4 == o1); + EXPECT_TRUE(!(o1 != 4)); + EXPECT_TRUE(!(4 != o1)); + EXPECT_TRUE(!(o1 < 4)); + EXPECT_TRUE(!(4 < o1)); + EXPECT_TRUE(!(o1 > 4)); + EXPECT_TRUE(!(4 > o1)); + EXPECT_TRUE(o1 <= 4); + EXPECT_TRUE(4 <= o1); + EXPECT_TRUE(o1 >= 4); + EXPECT_TRUE(4 >= o1); + } + std::string s4 = "hello"; + std::string s5 = "xyz"; + beman::optional::optional o4{s4}; + beman::optional::optional o5{s5}; + + // SECTION("self complex") + { + EXPECT_TRUE(!(o4 == o5)); + EXPECT_TRUE(o4 == o4); + EXPECT_TRUE(o4 != o5); + EXPECT_TRUE(!(o4 != o4)); + EXPECT_TRUE(o4 < o5); + EXPECT_TRUE(!(o4 < o4)); + EXPECT_TRUE(!(o4 > o5)); + EXPECT_TRUE(!(o4 > o4)); + EXPECT_TRUE(o4 <= o5); + EXPECT_TRUE(o4 <= o4); + EXPECT_TRUE(!(o4 >= o5)); + EXPECT_TRUE(o4 >= o4); + } + // SECTION("nullopt complex") + { + EXPECT_TRUE(!(o4 == beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt == o4)); + EXPECT_TRUE(o4 != beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt != o4); + EXPECT_TRUE(!(o4 < beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt < o4); + EXPECT_TRUE(o4 > beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt > o4)); + EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); + EXPECT_TRUE(beman::optional::nullopt <= o4); + EXPECT_TRUE(o4 >= beman::optional::nullopt); + EXPECT_TRUE(!(beman::optional::nullopt >= o4)); + + EXPECT_TRUE(o3 == beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt == o3); + EXPECT_TRUE(!(o3 != beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt != o3)); + EXPECT_TRUE(!(o3 < beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt < o3)); + EXPECT_TRUE(!(o3 > beman::optional::nullopt)); + EXPECT_TRUE(!(beman::optional::nullopt > o3)); + EXPECT_TRUE(o3 <= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt <= o3); + EXPECT_TRUE(o3 >= beman::optional::nullopt); + EXPECT_TRUE(beman::optional::nullopt >= o3); + } + + // SECTION("with T complex") + { + EXPECT_TRUE(!(o4 == "a")); + EXPECT_TRUE(!("a" == o4)); + EXPECT_TRUE(o4 != "a"); + EXPECT_TRUE("a" != o4); + EXPECT_TRUE(!(o4 < "a")); + EXPECT_TRUE("a" < o4); + EXPECT_TRUE(o4 > "a"); + EXPECT_TRUE(!("a" > o4)); + EXPECT_TRUE(!(o4 <= "a")); + EXPECT_TRUE("a" <= o4); + EXPECT_TRUE(o4 >= "a"); + EXPECT_TRUE(!("a" >= o4)); + + EXPECT_TRUE(o4 == "hello"); + EXPECT_TRUE("hello" == o4); + EXPECT_TRUE(!(o4 != "hello")); + EXPECT_TRUE(!("hello" != o4)); + EXPECT_TRUE(!(o4 < "hello")); + EXPECT_TRUE(!("hello" < o4)); + EXPECT_TRUE(!(o4 > "hello")); + EXPECT_TRUE(!("hello" > o4)); + EXPECT_TRUE(o4 <= "hello"); + EXPECT_TRUE("hello" <= o4); + EXPECT_TRUE(o4 >= "hello"); + EXPECT_TRUE("hello" >= o4); + } +} + +TEST(OptionalRefTest, Triviality) { + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + } + + { + struct T { + T(const T&) {} + T(T&&){}; + T& operator=(const T&) { return *this; } + T& operator=(T&&) { return *this; }; + ~T() {} + }; + EXPECT_TRUE(std::is_trivially_copy_constructible>::value); + EXPECT_TRUE(std::is_trivially_copy_assignable>::value); + EXPECT_TRUE(std::is_trivially_move_constructible>::value); + EXPECT_TRUE(std::is_trivially_move_assignable>::value); + EXPECT_TRUE(std::is_trivially_destructible>::value); + } +} + +TEST(OptionalRefTest, Deletion) { + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + + { + struct T { + T(const T&) = default; + T(T&&) = default; + T& operator=(const T&) = default; + T& operator=(T&&) = default; + ~T() = default; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + EXPECT_TRUE(std::is_destructible>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = delete; + T& operator=(const T&) = delete; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = delete; + T(T&&) = default; + T& operator=(const T&) = delete; + T& operator=(T&&) = default; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + EXPECT_TRUE(std::is_move_constructible>::value); + EXPECT_TRUE(std::is_move_assignable>::value); + } + + { + struct T { + T(const T&) = default; + T(T&&) = delete; + T& operator=(const T&) = default; + T& operator=(T&&) = delete; + }; + EXPECT_TRUE(std::is_copy_constructible>::value); + EXPECT_TRUE(std::is_copy_assignable>::value); + } +} + +struct takes_init_and_variadic { + std::vector v; + std::tuple t; + template + takes_init_and_variadic(std::initializer_list l, Args&&... args) : v(l), t(std::forward(args)...) {} +}; + +TEST(OptionalRefTest, MakeOptional) { + int var{42}; + auto o1 = beman::optional::make_optional(var); + auto o2 = beman::optional::optional(var); + + constexpr bool is_same = std::is_same>::value; + EXPECT_TRUE(is_same); + EXPECT_TRUE(o1 == o2); + + std::tuple tvar{0, 1, 2, 3}; + auto o3 = beman::optional::make_optional&>(tvar); + EXPECT_TRUE(std::get<0>(*o3) == 0); + EXPECT_TRUE(std::get<1>(*o3) == 1); + EXPECT_TRUE(std::get<2>(*o3) == 2); + EXPECT_TRUE(std::get<3>(*o3) == 3); + + std::vector ivec{0, 1, 2, 3}; + auto o4 = beman::optional::make_optional&>(ivec); + EXPECT_TRUE(o4.value()[0] == 0); + EXPECT_TRUE(o4.value()[1] == 1); + EXPECT_TRUE(o4.value()[2] == 2); + EXPECT_TRUE(o4.value()[3] == 3); + + takes_init_and_variadic tiv{{0, 1}, 2, 3}; + auto o5 = beman::optional::make_optional(tiv); + EXPECT_TRUE(o5->v[0] == 0); + EXPECT_TRUE(o5->v[1] == 1); + EXPECT_TRUE(std::get<0>(o5->t) == 2); + EXPECT_TRUE(std::get<1>(o5->t) == 3); + + auto i = 42; + auto o6 = beman::optional::make_optional(i); + static_assert(std::is_same_v>); + + EXPECT_TRUE((std::is_same_v>)); + EXPECT_TRUE(o6); + EXPECT_TRUE(*o6 == 42); +} + +TEST(OptionalRefTest, Nullopt) { + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2{beman::optional::nullopt}; + beman::optional::optional o3(beman::optional::nullopt); + beman::optional::optional o4 = {beman::optional::nullopt}; + + EXPECT_TRUE(!o1); + EXPECT_TRUE(!o2); + EXPECT_TRUE(!o3); + EXPECT_TRUE(!o4); + + EXPECT_TRUE(!std::is_default_constructible::value); +} + +struct move_detector { + move_detector() = default; + move_detector(move_detector&& rhs) { rhs.been_moved = true; } + bool been_moved = false; +}; + +TEST(OptionalRefTest, Observers) { + int var = 42; + beman::optional::optional o1 = var; + beman::optional::optional o2; + const beman::optional::optional o3 = var; + const beman::optional::optional o4; + int var2 = 42; + int var3 = 6*9; + EXPECT_TRUE(*o1 == 42); + EXPECT_TRUE(*o1 == o1.value()); + EXPECT_TRUE(o2.value_or(var2) == 42); + EXPECT_TRUE(o3.value() == 42); + EXPECT_TRUE(o3.value_or(var3) == 42); + EXPECT_TRUE(o4.value_or(var3) == 54); + int j = 99; + EXPECT_TRUE(o4.value_or(j) == 99); + // o4.value_or(j) = 88; + // EXPECT_TRUE(j == 88); + int var99 = 99; + j = 88; + EXPECT_TRUE([&](){beman::optional::optional o(j);return o; }().value_or(var99) == 88); + + EXPECT_TRUE([&](){beman::optional::optional o;return o; }().value_or(var99) == 99); + + + EXPECT_TRUE(o3.value_or([&]()->int&{return var3;}()) == 42); + EXPECT_TRUE(o4.value_or([&]()->int&{return var3;}()) == 54); + + std::string meow{"meow"}; + std::string bark{"bark"}; + beman::optional::optional so1; + beman::optional::optional so2{meow}; + auto t1 = so1.value_or(bark); + auto t2 = so2.value_or(bark); + // auto t3 = so1.value_or("bark"); + // auto t4 = so2.value_or("bark"); + // std::tuple t("meow"); + + auto success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + success = std::is_same::value; + static_assert(std::is_same::value); + EXPECT_TRUE(success); + + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + success = std::is_same()), int*>::value; + static_assert(std::is_same()), int*>::value); + EXPECT_TRUE(success); + + struct int_box {int i_;}; + int_box i1{3}; + beman::optional::optional ob1 = i1; + beman::optional::optional ob2; + const beman::optional::optional ob3 = i1; + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + success = std::is_samei_), int>::value; + static_assert(std::is_samei_), int>::value); + EXPECT_TRUE(success); + +} + +TEST(OptionalRefTest, MoveCheck) { + int x = 0; + int& y = std::move(beman::optional::optional(x)).value(); + EXPECT_EQ(&y, &x); + + int& z = *std::move(beman::optional::optional(x)); + EXPECT_EQ(&z, &x); + +} + +TEST(OptionalRefTest, SwapValue) { + int var = 42; + int twelve = 12; + beman::optional::optional o1 = var; + beman::optional::optional o2 = twelve; + o1.swap(o2); + EXPECT_EQ(o1.value(), 12); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalRefTest, SwapWNull) { + int var = 42; + + beman::optional::optional o1 = var; + beman::optional::optional o2 = beman::optional::nullopt; + o1.swap(o2); + EXPECT_TRUE(!o1.has_value()); + EXPECT_EQ(o2.value(), 42); +} + +TEST(OptionalRefTest, SwapNullIntializedWithValue) { + int var = 42; + beman::optional::optional o1 = beman::optional::nullopt; + beman::optional::optional o2 = var; + o1.swap(o2); + EXPECT_EQ(o1.value(), 42); + EXPECT_TRUE(!o2.has_value()); +} diff --git a/src/beman/optional/tests/optional_ref_monadic.t.cpp b/src/beman/optional/tests/optional_ref_monadic.t.cpp new file mode 100644 index 00000000..9d9f9fda --- /dev/null +++ b/src/beman/optional/tests/optional_ref_monadic.t.cpp @@ -0,0 +1,318 @@ +#include + +#include + +namespace { +inline constexpr int constexpr_fortytwo = 42; +constexpr int get_int(int) { return constexpr_fortytwo; } +constexpr beman::optional::optional get_opt_int(int) { return constexpr_fortytwo; } +} // namespace + +TEST(OptionalRefMonadicTest, Transform) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int forty = 40; + beman::optional::optional o2 = forty; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o3 = fortytwo; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // // ensure that lhs is forwarded + // forty = 40; + // beman::optional::optional o4 = forty; + // auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + forty = 40; + const beman::optional::optional o5 = forty; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + fortytwo = 42; + beman::optional::optional o8 = fortytwo; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = fortytwo; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = fortytwo; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = fortytwo; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); + + // callable which returns a reference + beman::optional::optional o38 = fortytwo; + auto o38r = o38.transform([](int& i) -> const int& { return i; }); + EXPECT_TRUE(o38r); + EXPECT_TRUE(*o38r == 42); +} + +TEST(OptionalRefMonadicTest, TransformConstexpr) { + + // test each overload in turn + constexpr beman::optional::optional o16 = constexpr_fortytwo; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = constexpr_fortytwo; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); +} + +TEST(OptionalRefMonadicTest, Transform2) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int forty = 40; + beman::optional::optional o2 = forty; + auto o2r = o2.transform([](int i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42); + + struct rval_call_transform { + double operator()(int) && { return 42.0; }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o3 = fortytwo; + auto o3r = o3.transform(rval_call_transform{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o3r.value() == 42); + + // // ensure that lhs is forwarded + // int forty = 40; + // beman::optional::optional o4 = forty; + // auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o4r.value() == 42); + + // ensure that lhs is const-propagated + forty = 40; + const beman::optional::optional o5 = forty; + auto o5r = o5.transform([](const int& i) { return i + 2; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // test each overload in turn + fortytwo = 42; + beman::optional::optional o8 = fortytwo; + auto o8r = o8.transform([](int) { return 42; }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o12 = fortytwo; + auto o12r = std::move(o12).transform([](int) { return 42; }); + EXPECT_TRUE(*o12r == 42); + + const beman::optional::optional o16 = fortytwo; + auto o16r = o16.transform([](int) { return 42; }); + EXPECT_TRUE(*o16r == 42); + + const beman::optional::optional o20 = fortytwo; + auto o20r = std::move(o20).transform([](int) { return 42; }); + EXPECT_TRUE(*o20r == 42); + + beman::optional::optional o24 = beman::optional::nullopt; + auto o24r = o24.transform([](int) { return 42; }); + EXPECT_TRUE(!o24r); + + beman::optional::optional o28 = beman::optional::nullopt; + auto o28r = std::move(o28).transform([](int) { return 42; }); + EXPECT_TRUE(!o28r); + + const beman::optional::optional o32 = beman::optional::nullopt; + auto o32r = o32.transform([](int) { return 42; }); + EXPECT_TRUE(!o32r); + + const beman::optional::optional o36 = beman::optional::nullopt; + auto o36r = std::move(o36).transform([](int) { return 42; }); + EXPECT_TRUE(!o36r); +} + +TEST(OptionalRefMonadicTest, TransformConstxpr) { + // test each overload in turn + constexpr beman::optional::optional o16 = constexpr_fortytwo; + constexpr auto o16r = o16.transform(get_int); + static_assert(*o16r == 42); + + constexpr beman::optional::optional o20 = constexpr_fortytwo; + constexpr auto o20r = std::move(o20).transform(get_int); + static_assert(*o20r == 42); + + constexpr beman::optional::optional o32 = beman::optional::nullopt; + constexpr auto o32r = o32.transform(get_int); + static_assert(!o32r); + constexpr beman::optional::optional o36 = beman::optional::nullopt; + constexpr auto o36r = std::move(o36).transform(get_int); + static_assert(!o36r); +} + +TEST(OptionalRefMonadicTest, and_then) { + // lhs is empty + beman::optional::optional o1; + auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o1r); + + // lhs has value + int twelve = 12; + beman::optional::optional o2 = twelve; + auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o2r.value() == 42.f); + + // lhs is empty, rhs returns empty + beman::optional::optional o3; + auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o3r); + + // rhs returns empty + beman::optional::optional o4 = twelve; + auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(!o4r); + + struct rval_call_and_then { + beman::optional::optional operator()(int) && { return beman::optional::optional(42.0); }; + }; + + // ensure that function object is forwarded + int fortytwo = 42; + beman::optional::optional o5 = fortytwo; + auto o5r = o5.and_then(rval_call_and_then{}); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o5r.value() == 42); + + // // ensure that lhs is forwarded + // beman::optional::optional o6 = fortytwo; + // auto o6r = + // std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); + // static_assert((std::is_same>::value)); + // EXPECT_TRUE(o6r.value() == 42); + + // ensure that function object is const-propagated + const beman::optional::optional o7 = fortytwo; + auto o7r = o7.and_then([](const int& i) { return beman::optional::optional(i); }); + static_assert((std::is_same>::value)); + EXPECT_TRUE(o7r.value() == 42); + + // test each overload in turn + beman::optional::optional o8 = fortytwo; + auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o8r == 42); + + beman::optional::optional o9 = fortytwo; + auto o9r = std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o9r == 42); + + const beman::optional::optional o10 = fortytwo; + auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o10r == 42); + + const beman::optional::optional o11 = fortytwo; + auto o11r = std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(*o11r == 42); + + beman::optional::optional o16 = beman::optional::nullopt; + auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o16r); + + beman::optional::optional o17 = beman::optional::nullopt; + auto o17r = std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o17r); + + const beman::optional::optional o18 = beman::optional::nullopt; + auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o18r); + + const beman::optional::optional o19 = beman::optional::nullopt; + auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); + EXPECT_TRUE(!o19r); + + int i = 3; + beman::optional::optional o20{i}; + std::move(o20).and_then([](int& r) { return beman::optional::optional{++r}; }); + EXPECT_TRUE(o20); + EXPECT_TRUE(i == 4); +} + +TEST(OptionalRefMonadicTest, Constexpr_and_then) { + constexpr beman::optional::optional o10 = constexpr_fortytwo; + constexpr auto o10r = o10.and_then(get_opt_int); + EXPECT_TRUE(*o10r == 42); + + constexpr beman::optional::optional o11 = constexpr_fortytwo; + constexpr auto o11r = std::move(o11).and_then(get_opt_int); + EXPECT_TRUE(*o11r == 42); + + constexpr beman::optional::optional o18 = beman::optional::nullopt; + constexpr auto o18r = o18.and_then(get_opt_int); + EXPECT_TRUE(!o18r); + + constexpr beman::optional::optional o19 = beman::optional::nullopt; + constexpr auto o19r = std::move(o19).and_then(get_opt_int); + EXPECT_TRUE(!o19r); +} + +TEST(OptionalRefMonadicTest, or_else) { + int fortytwo = 42; + int thirteen = 13; + beman::optional::optional o1 = fortytwo; + EXPECT_TRUE(*(o1.or_else([&] { return beman::optional::optional(thirteen); })) == 42); + + beman::optional::optional o2; + EXPECT_EQ(*(o2.or_else([&] { return beman::optional::optional(thirteen); })), 13); +} From 2b113048be77a8144f2b54ae9fbee883f73f8ac9 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Thu, 13 Jun 2024 15:08:18 +0300 Subject: [PATCH 04/20] Add missing implementation: define format_kind for clang --- include/Beman/Optional26/optional.hpp | 22 ++- .../tests/optional_range_support.t.cpp | 157 ++++++++++++++++++ 2 files changed, 170 insertions(+), 9 deletions(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index 3ae72598..a97577fe 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -222,8 +222,12 @@ template inline constexpr bool ranges::enable_borrowed_range> = true; // Since P3168R1: Give std::optional Range Support. -// template -// inline constexpr auto format_kind> = range_format::disabled; +// Note: At 13.06.2024, gcc and msvc do not implement P2585R1: "Improve default container formatting". +// TODO @neatudarius: always enable once supported by other compilers. +#if defined(__clang__) +template +inline constexpr auto format_kind> = range_format::disabled; +#endif } // namespace std @@ -316,9 +320,9 @@ class optional { } public: - using value_type = T; + using value_type = T; // Since P3168R1: Give std::optional Range Support. - using iterator = T*; // see [optional.iterators] + using iterator = T*; // see [optional.iterators] using const_iterator = const T*; // see [optional.iterators] constexpr optional() noexcept @@ -689,9 +693,9 @@ class optional { // Since P3168R1: Give std::optional Range Support. // [optional.iterators], iterator support - constexpr iterator begin() noexcept { return has_value() ? std::addressof(value_) : nullptr; }; + constexpr iterator begin() noexcept { return has_value() ? std::addressof(value_) : nullptr; }; constexpr const_iterator begin() const noexcept { return has_value() ? std::addressof(value_) : nullptr; }; - constexpr iterator end() noexcept { return begin() + has_value(); } + constexpr iterator end() noexcept { return begin() + has_value(); } constexpr const_iterator end() const noexcept { return begin() + has_value(); } /// Returns a pointer to the stored value @@ -940,7 +944,7 @@ class optional { // Note: P3168 and P2988 may have different flows inside LEWG/LWG. // Implementation of the range support for optional reflects P3168R1 for now. // [optional.iterators], iterator support - using iterator = T*; // see [optional.iterators] + using iterator = T*; // see [optional.iterators] using const_iterator = const T*; // see [optional.iterators] // [optional.ctor], constructors @@ -1075,9 +1079,9 @@ class optional { // Note: P3168 and P2988 may have different flows inside LEWG/LWG. // Implementation of the range support for optional reflects P3168R1 for now. // [optional.iterators], iterator support - constexpr iterator begin() noexcept { return has_value() ? value_ : nullptr; }; + constexpr iterator begin() noexcept { return has_value() ? value_ : nullptr; }; constexpr const_iterator begin() const noexcept { return has_value() ? value_ : nullptr; }; - constexpr iterator end() noexcept { return begin() + has_value(); } + constexpr iterator end() noexcept { return begin() + has_value(); } constexpr const_iterator end() const noexcept { return begin() + has_value(); } // \rSec3[optional.observe]{Observers} diff --git a/src/beman/optional/tests/optional_range_support.t.cpp b/src/beman/optional/tests/optional_range_support.t.cpp index 3e34ed14..a08f56f1 100644 --- a/src/beman/optional/tests/optional_range_support.t.cpp +++ b/src/beman/optional/tests/optional_range_support.t.cpp @@ -7,3 +7,160 @@ #include #include +namespace test { +struct empty {}; +struct no_default_ctor { + no_default_ctor() = delete; + no_default_ctor(const no_default_ctor&) = default; + no_default_ctor(no_default_ctor&&) = default; + no_default_ctor& operator=(const no_default_ctor&) = default; + no_default_ctor& operator=(no_default_ctor&&) = default; + no_default_ctor(empty){}; +}; + +struct base { + int i_; + base() : i_(0) {} + base(int i) : i_(i) {} +}; + +struct derived : public base { + int j_; + derived() : base(0), j_(0) {} + derived(int i, int j) : base(i), j_(j) {} +}; +} + +TEST(RangeSupportTest, BeginOnEmptyOptional) { + EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); +} + +TEST(RangeSupportTest, BeginOnNonEmptyOptional) { + beman::optional::optional opt_int = 26; + EXPECT_EQ(opt_int.begin(), &*opt_int); + + beman::optional::optional opt_empty = test::empty{}; + EXPECT_EQ(opt_empty.begin(), &*opt_empty); + + beman::optional::optional opt_no_default_ctor = test::no_default_ctor{test::empty{}}; + EXPECT_EQ(opt_no_default_ctor.begin(), &*opt_no_default_ctor); + + beman::optional::optional opt_base = test::base{}; + EXPECT_EQ(opt_base.begin(), &*opt_base); + + beman::optional::optional opt_derived = test::derived{}; + EXPECT_EQ(opt_derived.begin(), &*opt_derived); +} + +TEST(RangeSupportTest, EndOnEmptyOptional) { + EXPECT_EQ(beman::optional::optional {}.end(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.end(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.end(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.end(), nullptr); + + EXPECT_EQ(beman::optional::optional {}.end(), nullptr); +} + + +TEST(RangeSupportTest, EndOnNonEmptyOptional) { + beman::optional::optional opt_int = 0XCAFEBABE; + EXPECT_EQ(opt_int.end(), opt_int.begin() + 1); + + beman::optional::optional opt_empty = test::empty{}; + EXPECT_EQ(opt_empty.end(), opt_empty.begin() + 1); + + beman::optional::optional opt_no_default_ctor = test::no_default_ctor{test::empty{}}; + EXPECT_EQ(opt_no_default_ctor.end(), opt_no_default_ctor.begin() + 1); + + beman::optional::optional opt_base = test::base{}; + EXPECT_EQ(opt_base.end(), opt_base.begin() + 1); + + beman::optional::optional opt_derived = test::derived{}; + EXPECT_EQ(opt_derived.end(), opt_derived.begin() + 1); +} + +TEST(RangeSupportTest, LoopOverEmptyRange) { + beman::optional::optional empty; + ASSERT_FALSE(empty.has_value()); + + for(auto _ : empty) { + ASSERT_TRUE(false) << "Should not be reached: expected not to loop over empty optional"; + } +} + +TEST(RangeSupportTest, LoopOverNonEmptyRange) { + const auto expected_value = 0xCAFEBABE; + beman::optional::optional empty{expected_value}; + ASSERT_TRUE(empty.has_value()); + + bool entered_loop = false; + for(auto i : empty) { + EXPECT_EQ(i, expected_value); + entered_loop = true; + } + EXPECT_TRUE(entered_loop); +} + +TEST(RangeSupportTest, ConceptCheck) { + // enable_view_for_optional + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(!std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + static_assert(std::ranges::sized_range>); + + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); + + using ref = std::reference_wrapper; + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); + static_assert(std::ranges::random_access_range>); +} + +// TODO iterator tests + +TEST(RangeSupportTest, FormatOptionalIsStillDisabled) { +// Since P3168R1: Give std::optional Range Support. +// Note: At 13.06.2024, gcc and msvc do not implement P2585R1: "Improve default container formatting". +// TODO @neatudarius: always enable once supported by other compilers. +#if defined(__clang__) + EXPECT_EQ(std::format_kind>, std::range_format::disabled); + + // Next line shold not compile: formatter is not defined for std::optional and bemans::optional::optional. + // EXPECT_EQ(std::format("{}", beman::optional::optional {}), ""); +#endif +} + From 8fff6ed885d4100371bb02b1dcc4a099f175a6e7 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Thu, 13 Jun 2024 15:10:07 +0300 Subject: [PATCH 05/20] Run linter --- .../tests/optional_range_support.t.cpp | 50 +++++++++---------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/beman/optional/tests/optional_range_support.t.cpp b/src/beman/optional/tests/optional_range_support.t.cpp index a08f56f1..9fc96305 100644 --- a/src/beman/optional/tests/optional_range_support.t.cpp +++ b/src/beman/optional/tests/optional_range_support.t.cpp @@ -10,12 +10,12 @@ namespace test { struct empty {}; struct no_default_ctor { - no_default_ctor() = delete; + no_default_ctor() = delete; no_default_ctor(const no_default_ctor&) = default; no_default_ctor(no_default_ctor&&) = default; no_default_ctor& operator=(const no_default_ctor&) = default; no_default_ctor& operator=(no_default_ctor&&) = default; - no_default_ctor(empty){}; + no_default_ctor(empty) {}; }; struct base { @@ -29,18 +29,18 @@ struct derived : public base { derived() : base(0), j_(0) {} derived(int i, int j) : base(i), j_(j) {} }; -} +} // namespace test TEST(RangeSupportTest, BeginOnEmptyOptional) { - EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.begin(), nullptr); + EXPECT_EQ(beman::optional::optional{}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional{}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional{}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional{}.begin(), nullptr); + + EXPECT_EQ(beman::optional::optional{}.begin(), nullptr); } TEST(RangeSupportTest, BeginOnNonEmptyOptional) { @@ -61,17 +61,16 @@ TEST(RangeSupportTest, BeginOnNonEmptyOptional) { } TEST(RangeSupportTest, EndOnEmptyOptional) { - EXPECT_EQ(beman::optional::optional {}.end(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.end(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.end(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.end(), nullptr); - - EXPECT_EQ(beman::optional::optional {}.end(), nullptr); -} + EXPECT_EQ(beman::optional::optional{}.end(), nullptr); + EXPECT_EQ(beman::optional::optional{}.end(), nullptr); + + EXPECT_EQ(beman::optional::optional{}.end(), nullptr); + + EXPECT_EQ(beman::optional::optional{}.end(), nullptr); + + EXPECT_EQ(beman::optional::optional{}.end(), nullptr); +} TEST(RangeSupportTest, EndOnNonEmptyOptional) { beman::optional::optional opt_int = 0XCAFEBABE; @@ -94,18 +93,18 @@ TEST(RangeSupportTest, LoopOverEmptyRange) { beman::optional::optional empty; ASSERT_FALSE(empty.has_value()); - for(auto _ : empty) { + for (auto _ : empty) { ASSERT_TRUE(false) << "Should not be reached: expected not to loop over empty optional"; } } TEST(RangeSupportTest, LoopOverNonEmptyRange) { - const auto expected_value = 0xCAFEBABE; + const auto expected_value = 0xCAFEBABE; beman::optional::optional empty{expected_value}; ASSERT_TRUE(empty.has_value()); bool entered_loop = false; - for(auto i : empty) { + for (auto i : empty) { EXPECT_EQ(i, expected_value); entered_loop = true; } @@ -163,4 +162,3 @@ TEST(RangeSupportTest, FormatOptionalIsStillDisabled) { // EXPECT_EQ(std::format("{}", beman::optional::optional {}), ""); #endif } - From 7a30db74b2c73aa83e915c1b88e5ad869166a667 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Thu, 13 Jun 2024 19:32:45 +0300 Subject: [PATCH 06/20] Add more tests for optional range support --- include/Beman/Optional26/optional.hpp | 7 + .../tests/optional_range_support.t.cpp | 288 +++++++++++++++--- 2 files changed, 249 insertions(+), 46 deletions(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index a97577fe..6bcfa02c 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -209,15 +209,22 @@ namespace std { template inline constexpr bool ranges::enable_view> = true; +// Since ${PAPER_NUMBER}: ${PAPER_TITLE}. +// Note: P3168 and P2988 may have different flows inside LEWG/LWG. +// Implementation of the range support for optional reflects P3168R1 for now. +// [optional.iterators], iterator support template inline constexpr bool ranges::enable_view> = true; +// TODO: document why this is needed. template inline constexpr bool ranges::enable_borrowed_range> = true; +// TODO: document why this is needed. template inline constexpr bool ranges::enable_borrowed_range>> = true; +// TODO: document why this is needed. template inline constexpr bool ranges::enable_borrowed_range> = true; diff --git a/src/beman/optional/tests/optional_range_support.t.cpp b/src/beman/optional/tests/optional_range_support.t.cpp index 9fc96305..db09e388 100644 --- a/src/beman/optional/tests/optional_range_support.t.cpp +++ b/src/beman/optional/tests/optional_range_support.t.cpp @@ -1,14 +1,24 @@ #include +#include #include #include #include #include #include +#include +#include #include namespace test { +/** + * Empty class helper. + **/ struct empty {}; + +/** + * No default constructor class helper. + **/ struct no_default_ctor { no_default_ctor() = delete; no_default_ctor(const no_default_ctor&) = default; @@ -18,12 +28,18 @@ struct no_default_ctor { no_default_ctor(empty) {}; }; +/** + * Base class helper. + **/ struct base { int i_; base() : i_(0) {} base(int i) : i_(i) {} }; +/** + * Derived class helper. + **/ struct derived : public base { int j_; derived() : base(0), j_(0) {} @@ -89,6 +105,90 @@ TEST(RangeSupportTest, EndOnNonEmptyOptional) { EXPECT_EQ(opt_derived.end(), opt_derived.begin() + 1); } +TEST(RangeSupportTest, RangeConceptsCheck) { + { + // std::optional is not (yet) a range. + static_assert(!std::ranges::range>); + } + + { + // beman::optional::optional is a range. + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(!std::ranges::borrowed_range>); // borrowed_range is disabled for + // non-pointers + static_assert(std::ranges::random_access_range>); + static_assert(std::ranges::sized_range>); + } + + { + // beman::optional::optional is a range. + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert( + std::ranges::borrowed_range>); // borrowed_range is enabled for pointers + static_assert(std::ranges::random_access_range>); + } +} + +TEST(RangeSupportTest, IteratorConceptsCheck) { + { + // beman::optional::optional::iterator is an iterator type. + static_assert(std::input_iterator::iterator>); + static_assert(std::forward_iterator::iterator>); + static_assert(std::bidirectional_iterator::iterator>); + static_assert(std::random_access_iterator::iterator>); + static_assert(std::contiguous_iterator::iterator>); + + // beman::optional::optional::const_iterator is an iterator type. + static_assert(std::input_iterator::const_iterator>); + static_assert(std::forward_iterator::const_iterator>); + static_assert(std::bidirectional_iterator::const_iterator>); + static_assert(std::random_access_iterator::const_iterator>); + static_assert(std::contiguous_iterator::const_iterator>); + } + + { + // beman::optional::optional::iterator is an iterator type. + static_assert(std::input_iterator::iterator>); + static_assert(std::forward_iterator::iterator>); + static_assert(std::bidirectional_iterator::iterator>); + static_assert(std::random_access_iterator::iterator>); + static_assert(std::contiguous_iterator::iterator>); + + // beman::optional::optional::const_iterator is an iterator type. + static_assert(std::input_iterator::const_iterator>); + static_assert(std::forward_iterator::const_iterator>); + static_assert(std::bidirectional_iterator::const_iterator>); + static_assert(std::random_access_iterator::const_iterator>); + static_assert(std::contiguous_iterator::const_iterator>); + } +} + +TEST(RangeSupportTest, FormatOptionalIsStillDisabled) { +// Since P3168R1: Give std::optional Range Support. +// Note: At 13.06.2024, gcc and msvc do not implement P2585R1: "Improve default container formatting". +// TODO @neatudarius: always enable once supported by other compilers. +#if defined(__clang__) + EXPECT_EQ(std::format_kind>, std::range_format::disabled); + + // Next line shold not compile: formatter is not defined for std::optional and bemans::optional::optional. + // EXPECT_EQ(std::format("{}", beman::optional::optional {}), ""); +#endif +} + TEST(RangeSupportTest, LoopOverEmptyRange) { beman::optional::optional empty; ASSERT_FALSE(empty.has_value()); @@ -111,54 +211,150 @@ TEST(RangeSupportTest, LoopOverNonEmptyRange) { EXPECT_TRUE(entered_loop); } -TEST(RangeSupportTest, ConceptCheck) { - // enable_view_for_optional - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(!std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - static_assert(std::ranges::sized_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); +TEST(RangeSupportTest, LoopOptionalAccess) { + // Example from P3168R1: should access the value from an optional object. + const int expected_value = 0xCAFEBABE; + const auto get_optional = [&]() -> beman::optional::optional { return expected_value; }; + ASSERT_TRUE(get_optional().has_value()); + + for (auto&& opt : get_optional()) { + EXPECT_EQ(opt, expected_value); // usage of opt here is safe + } } -// TODO iterator tests +TEST(RangeSupportTest, LoopOptionalAssignment) { + // Example from P3168R1: should mutate the value from an optional object. + const int initial_expected_value = 0xCAFEBABE; + const int expected_value = 0xDEADBEEF; + const auto get_optional = [&]() -> beman::optional::optional { return initial_expected_value; }; + ASSERT_TRUE(get_optional().has_value()); + ASSERT_TRUE(get_optional().value() == initial_expected_value); + + auto opt_int = get_optional(); + for (auto&& opt : opt_int) { + EXPECT_EQ(opt, initial_expected_value); + opt = expected_value; // usage of opt here is safe + } + ASSERT_TRUE(opt_int.has_value()); + EXPECT_EQ(opt_int.value(), expected_value); +} -TEST(RangeSupportTest, FormatOptionalIsStillDisabled) { -// Since P3168R1: Give std::optional Range Support. -// Note: At 13.06.2024, gcc and msvc do not implement P2585R1: "Improve default container formatting". -// TODO @neatudarius: always enable once supported by other compilers. -#if defined(__clang__) - EXPECT_EQ(std::format_kind>, std::range_format::disabled); +TEST(RangeSupportTest, RangeChainExampleWithVector) { + // Example from P3168R1: start from a vector of values, apply multiple range operations involving optional values. + std::vector v{2, 3, 4, 5, 6, 7, 8, 9, 1}; + const auto test = [](int i) -> beman::optional::optional { + switch (i) { + case 1: + case 3: + case 7: + case 9: + return i; + default: + return {}; + } + }; + + auto&& r = + v // starting vector + | std::ranges::views::transform(test) // generates {nullopt, 3, nullopt, 7, nullopt, nullopt, nullopt, 9, 1} + | std::ranges::views::filter([](auto x) { + return bool(x); + }) // generates {optional{3}, optional{7}, optional{9}, optional{1}} + | std::ranges::views::transform([](auto x) { return *x; }) // generates {3, 5, 7, 9} + | std::ranges::views::transform([](int i) { + // std::cout << i << "\n"; // do not actually do it in tests + return i; + }) // print + identity transform + ; + + ASSERT_TRUE(std::ranges::equal(r, std::vector{3, 7, 9, 1})); +} - // Next line shold not compile: formatter is not defined for std::optional and bemans::optional::optional. - // EXPECT_EQ(std::format("{}", beman::optional::optional {}), ""); -#endif +TEST(RangeSupportTest, RangeChainExampleWithSets) { + // Example from P3168R1: start from a set of values, apply multiple range operations involving optional values. + std::unordered_set s{1, 3, 7, 9}; + const auto flt = [&](int i) -> beman::optional::optional { + if (s.contains(i)) { + return i; + } else { + return {}; + } + }; + + for (auto i : std::ranges::views::iota(1, 10) | std::ranges::views::transform(flt)) { + for (auto j : i) { // no need to transform + for (auto k : std::ranges::views::iota(0, j)) { + // std::cout << '\a'; // do not actually log in tests + std::ignore = k; + } + // std::cout << '\n'; // do not actually log in tests + } + } +} + +TEST(RangeSupportTest, PythagoreanTriples) { + // Example from P3168R1: generate an infinite sequence of Pythagorean triples. + // (x, y, z) is a Pythagorean triple if 1 <= x <= y <= z and x^2 + y^2 = z^2. + constexpr auto yield_if = [](bool b, T x) -> beman::optional::optional { + return b ? beman::optional::optional{std::move(x)} : beman::optional::nullopt; + }; + constexpr auto and_then = [](T&& r, auto fun) { + return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | std::ranges::views::join; + }; + auto triples = and_then(std::ranges::views::iota(1), [=](int z) { + return and_then(std::ranges::views::iota(1, z + 1), [=](int x) { + return and_then(std::ranges::views::iota(x, z + 1), + [=](int y) { return yield_if(x * x + y * y == z * z, std::make_tuple(x, y, z)); }); + }); + }); + + { + // Generate first 10 Pythagorean triples. + // https://mathworld.wolfram.com/PythagoreanTriple.html + auto&& r = triples | std::ranges::views::take(10); + EXPECT_TRUE(std::ranges::equal(r, + std::vector{ + std::tuple{3, 4, 5}, + std::tuple{6, 8, 10}, + std::tuple{5, 12, 13}, + std::tuple{9, 12, 15}, + std::tuple{8, 15, 17}, + std::tuple{12, 16, 20}, + std::tuple{7, 24, 25}, + std::tuple{15, 20, 25}, + std::tuple{10, 24, 26}, + std::tuple{20, 21, 29}, + })); + } + + { + // Generate the nth Pythagorean triple (x, y, z) where: + // 1 <= x <= y <= z <= max_value and x^2 + y^2 = z^2 + + // Generate the nth Pythagorean triple with brute force. + auto bruteforce_generate_nth = [](int n, int max_value) -> std::tuple { + int count = 0; // Count the number of Pythagorean triples. + for (int z = 1; z <= max_value; ++z) { + for (int x = 1; x <= max_value; ++x) { + for (int y = 1; y <= max_value; ++y) { + if (!(x <= y && y <= z) || x * x + y * y != z * z) { + continue; + } + + if (++count == n) { + return std::make_tuple(x, y, z); + } + } + } + } + + return {}; // Should not reach here. + }; + constexpr const std::tuple k100th_triple = {26, 168, 170}; // The 100th Pythagorean triple with x, y, z <= 200. + ASSERT_EQ(bruteforce_generate_nth(100, 200), k100th_triple); + + // Generate the 100th Pythagorean triple with ranges. + auto&& r = triples | std::ranges::views::drop(99) | std::ranges::views::take(1); + EXPECT_TRUE(std::ranges::equal(r, std::vector{k100th_triple})); + } } From cebf476e51f6f411f498d1ccf353367213d643b0 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 09:15:50 +0300 Subject: [PATCH 07/20] rename src/Beman --- .../tests/optional_range_support.t.cpp | 9 - src/beman/optional/optional.t.cpp | 1278 ----------------- src/beman/optional/optional_monadic.t.cpp | 311 ---- src/beman/optional/optional_ref.t.cpp | 560 -------- src/beman/optional/optional_ref_monadic.t.cpp | 318 ---- src/beman/optional/tests/optional.t.cpp | 1278 ----------------- .../optional/tests/optional_monadic.t.cpp | 311 ---- src/beman/optional/tests/optional_ref.t.cpp | 560 -------- .../optional/tests/optional_ref_monadic.t.cpp | 318 ---- src/{Beman => tmp}/CMakeLists.txt | 0 src/{Beman => tmp}/optional/CMakeLists.txt | 0 src/{Beman => tmp}/optional/optional.cpp | 0 src/{Beman => tmp}/optional/optional.t.cpp | 0 .../optional/optional_monadic.t.cpp | 0 .../optional/optional_ref.t.cpp | 0 .../optional/optional_ref_monadic.t.cpp | 0 .../optional/tests/optional.t.cpp | 0 .../optional/tests/optional_monadic.t.cpp | 0 .../tests/optional_range_support.t.cpp | 0 .../optional/tests/optional_ref.t.cpp | 0 .../optional/tests/optional_ref_monadic.t.cpp | 0 21 files changed, 4943 deletions(-) delete mode 100644 src/Beman/optional/tests/optional_range_support.t.cpp delete mode 100644 src/beman/optional/optional.t.cpp delete mode 100644 src/beman/optional/optional_monadic.t.cpp delete mode 100644 src/beman/optional/optional_ref.t.cpp delete mode 100644 src/beman/optional/optional_ref_monadic.t.cpp delete mode 100644 src/beman/optional/tests/optional.t.cpp delete mode 100644 src/beman/optional/tests/optional_monadic.t.cpp delete mode 100644 src/beman/optional/tests/optional_ref.t.cpp delete mode 100644 src/beman/optional/tests/optional_ref_monadic.t.cpp rename src/{Beman => tmp}/CMakeLists.txt (100%) rename src/{Beman => tmp}/optional/CMakeLists.txt (100%) rename src/{Beman => tmp}/optional/optional.cpp (100%) rename src/{Beman => tmp}/optional/optional.t.cpp (100%) rename src/{Beman => tmp}/optional/optional_monadic.t.cpp (100%) rename src/{Beman => tmp}/optional/optional_ref.t.cpp (100%) rename src/{Beman => tmp}/optional/optional_ref_monadic.t.cpp (100%) rename src/{Beman => tmp}/optional/tests/optional.t.cpp (100%) rename src/{Beman => tmp}/optional/tests/optional_monadic.t.cpp (100%) rename src/{beman => tmp}/optional/tests/optional_range_support.t.cpp (100%) rename src/{Beman => tmp}/optional/tests/optional_ref.t.cpp (100%) rename src/{Beman => tmp}/optional/tests/optional_ref_monadic.t.cpp (100%) diff --git a/src/Beman/optional/tests/optional_range_support.t.cpp b/src/Beman/optional/tests/optional_range_support.t.cpp deleted file mode 100644 index 3e34ed14..00000000 --- a/src/Beman/optional/tests/optional_range_support.t.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - diff --git a/src/beman/optional/optional.t.cpp b/src/beman/optional/optional.t.cpp deleted file mode 100644 index 9da8715d..00000000 --- a/src/beman/optional/optional.t.cpp +++ /dev/null @@ -1,1278 +0,0 @@ -#include - -#include // test 2nd include OK - -#include -#include -#include - -#include - -TEST(OptionalTest, TestGTest) { ASSERT_EQ(1, 1); } - -namespace { -struct empty {}; -struct no_default { - no_default() = delete; - no_default(const no_default&) = default; - no_default(no_default&&) = default; - no_default& operator=(const no_default&) = default; - no_default& operator=(no_default&&) = default; - no_default(empty){}; -}; - -struct base { - int i_; - base() : i_(0) {} - base(int i) : i_(i) {} -}; - -struct derived : public base { - int j_; - derived() : base(0), j_(0) {} - derived(int i, int j) : base(i), j_(j) {} -}; -} // namespace - -TEST(OptionalTest, Constructors) { - beman::optional::optional i1; - beman::optional::optional i2{beman::optional::nullopt}; - - int i = 0; - beman::optional::optional i3 = i; - (void)i3; - - beman::optional::optional e1; - beman::optional::optional e2{beman::optional::nullopt}; - - empty e{}; - beman::optional::optional e3 = e; - (void)e3; -} - - -TEST(OptionalTest, Constructors2) { - beman::optional::optional o1; - EXPECT_TRUE(!o1); - - beman::optional::optional o2 = beman::optional::nullopt; - EXPECT_TRUE(!o2); - - beman::optional::optional o3 = 42; - EXPECT_TRUE(*o3 == 42); - - beman::optional::optional o4 = o3; - EXPECT_TRUE(*o4 == 42); - - beman::optional::optional o5 = o1; - EXPECT_TRUE(!o5); - - beman::optional::optional o6 = std::move(o3); - EXPECT_TRUE(*o6 == 42); - - beman::optional::optional o7 = 42; - EXPECT_TRUE(*o7 == 42); - - beman::optional::optional o8 = o7; - EXPECT_TRUE(*o8 == 42); - - beman::optional::optional o9 = std::move(o7); - EXPECT_TRUE(*o9 == 42); - - { - beman::optional::optional o; - EXPECT_TRUE(!o); - - beman::optional::optional oo = o; - EXPECT_TRUE(!oo); - } - - { - auto i = 42; - beman::optional::optional o = i; - EXPECT_TRUE(o); - EXPECT_TRUE(*o == 42); - - beman::optional::optional oo = o; - EXPECT_TRUE(oo); - EXPECT_TRUE(*oo == 42); - } - - std::vector v; - v.emplace_back(); - beman::optional::optional> ov = std::move(v); - EXPECT_TRUE(ov->size() == 1); -} - -TEST(OptionalTest, Constructors3) { - beman::optional::optional ie; - beman::optional::optional i4 = ie; - EXPECT_FALSE(i4); - - base b{1}; - derived d(1, 2); - beman::optional::optional b1{b}; - beman::optional::optional b2{d}; - - beman::optional::optional d2{d}; - beman::optional::optional b3 = d2; - beman::optional::optional b4{d2}; -} - -namespace { -class NoDefault { - int v_; - - public: - NoDefault(int v) : v_(v) {} -}; -} // namespace - -TEST(OptionalTest, NonDefaultConstruct) { - NoDefault i = 7; - beman::optional::optional v1{}; - beman::optional::optional v2{i}; -} - -TEST(OptionalTest, AssignmentValue) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = 12; - beman::optional::optional o3; - - o1 = o1; - EXPECT_TRUE(*o1 == 42); - - o1 = o2; - EXPECT_TRUE(*o1 == 12); - - o1 = o3; - EXPECT_TRUE(!o1); - - o1 = 42; - EXPECT_TRUE(*o1 == 42); - - o1 = beman::optional::nullopt; - EXPECT_TRUE(!o1); - - o1 = std::move(o2); - EXPECT_TRUE(*o1 == 12); - - beman::optional::optional o4 = 42; - - o1 = o4; - EXPECT_TRUE(*o1 == 42); - - o1 = std::move(o4); - EXPECT_TRUE(*o1 == 42); -} - -TEST(OptionalTest, Triviality) { - EXPECT_TRUE(std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE( - std::is_trivially_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE( - std::is_trivially_destructible>::value); - } - - { - struct T { - T(const T&) {} - T(T&&){}; - T& operator=(const T&) { return *this; } - T& operator=(T&&) { return *this; }; - ~T() {} - }; - EXPECT_TRUE(!std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_destructible< - beman::optional::optional>::value); - } -} - -TEST(OptionalTest, Deletion) { - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE( - std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE( - std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = delete; - T& operator=(const T&) = delete; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE( - !std::is_copy_constructible>::value); - EXPECT_TRUE( - !std::is_copy_assignable>::value); - EXPECT_TRUE( - !std::is_move_constructible>::value); - EXPECT_TRUE( - !std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = default; - T& operator=(const T&) = delete; - T& operator=(T&&) = default; - }; - EXPECT_TRUE( - !std::is_copy_constructible>::value); - EXPECT_TRUE( - !std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE( - std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = default; - T(T&&) = delete; - T& operator=(const T&) = default; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE( - std::is_copy_assignable>::value); - } -} - -struct takes_init_and_variadic { - std::vector v; - std::tuple t; - template - takes_init_and_variadic(std::initializer_list l, Args&&... args) - : v(l), t(std::forward(args)...) {} -}; - -TEST(OptionalTest, InPlace) { - beman::optional::optional o1{beman::optional::in_place}; - beman::optional::optional o2(beman::optional::in_place); - EXPECT_TRUE(o1); - EXPECT_TRUE(o1 == 0); - EXPECT_TRUE(o2); - EXPECT_TRUE(o2 == 0); - - beman::optional::optional o3(beman::optional::in_place, 42); - EXPECT_TRUE(o3 == 42); - - beman::optional::optional> o4( - beman::optional::in_place, 0, 1); - EXPECT_TRUE(o4); - EXPECT_TRUE(std::get<0>(*o4) == 0); - EXPECT_TRUE(std::get<1>(*o4) == 1); - - beman::optional::optional> o5(beman::optional::in_place, - {0, 1}); - EXPECT_TRUE(o5); - EXPECT_TRUE((*o5)[0] == 0); - EXPECT_TRUE((*o5)[1] == 1); - - beman::optional::optional o6( - beman::optional::in_place, {0, 1}, 2, 3); - EXPECT_TRUE(o6->v[0] == 0); - EXPECT_TRUE(o6->v[1] == 1); - EXPECT_TRUE(std::get<0>(o6->t) == 2); - EXPECT_TRUE(std::get<1>(o6->t) == 3); -} - -TEST(OptionalTest, MakeOptional) { - auto o1 = beman::optional::make_optional(42); - auto o2 = beman::optional::optional(42); - - constexpr bool is_same = - std::is_same>::value; - EXPECT_TRUE(is_same); - EXPECT_TRUE(o1 == o2); - - auto o3 = beman::optional::make_optional>( - 0, 1, 2, 3); - EXPECT_TRUE(std::get<0>(*o3) == 0); - EXPECT_TRUE(std::get<1>(*o3) == 1); - EXPECT_TRUE(std::get<2>(*o3) == 2); - EXPECT_TRUE(std::get<3>(*o3) == 3); - - auto o4 = beman::optional::make_optional>({0, 1, 2, 3}); - EXPECT_TRUE(o4.value()[0] == 0); - EXPECT_TRUE(o4.value()[1] == 1); - EXPECT_TRUE(o4.value()[2] == 2); - EXPECT_TRUE(o4.value()[3] == 3); - - auto o5 = - beman::optional::make_optional({0, 1}, 2, 3); - EXPECT_TRUE(o5->v[0] == 0); - EXPECT_TRUE(o5->v[1] == 1); - EXPECT_TRUE(std::get<0>(o5->t) == 2); - EXPECT_TRUE(std::get<1>(o5->t) == 3); - - auto i = 42; - auto o6 = beman::optional::make_optional(i); - static_assert(std::is_same>::value); - - EXPECT_TRUE( - (std::is_same>::value)); - EXPECT_TRUE(o6); - EXPECT_TRUE(*o6 == 42); -} - -TEST(OptionalTest, Nullopt) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2{beman::optional::nullopt}; - beman::optional::optional o3(beman::optional::nullopt); - beman::optional::optional o4 = {beman::optional::nullopt}; - - EXPECT_TRUE(!o1); - EXPECT_TRUE(!o2); - EXPECT_TRUE(!o3); - EXPECT_TRUE(!o4); - - EXPECT_TRUE( - !std::is_default_constructible::value); -} - -struct move_detector { - move_detector() = default; - move_detector(move_detector&& rhs) { rhs.been_moved = true; } - bool been_moved = false; -}; - -TEST(OptionalTest, Observers) { - beman::optional::optional o1 = 42; - beman::optional::optional o2; - const beman::optional::optional o3 = 42; - - EXPECT_TRUE(*o1 == 42); - EXPECT_TRUE(*o1 == o1.value()); - EXPECT_TRUE(o2.value_or(42) == 42); - EXPECT_TRUE(o3.value() == 42); - auto success = std::is_same::value; - EXPECT_TRUE(success); - success = std::is_same::value; - EXPECT_TRUE(success); - success = std::is_same::value; - EXPECT_TRUE(success); - - beman::optional::optional o4{beman::optional::in_place}; - move_detector o5 = std::move(o4).value(); - EXPECT_TRUE(o4->been_moved); - EXPECT_TRUE(!o5.been_moved); -} - -TEST(OptionalTest, RelationalOps) { - beman::optional::optional o1{4}; - beman::optional::optional o2{42}; - beman::optional::optional o3{}; - - // SECTION("self simple") - { - EXPECT_TRUE(!(o1 == o2)); - EXPECT_TRUE(o1 == o1); - EXPECT_TRUE(o1 != o2); - EXPECT_TRUE(!(o1 != o1)); - EXPECT_TRUE(o1 < o2); - EXPECT_TRUE(!(o1 < o1)); - EXPECT_TRUE(!(o1 > o2)); - EXPECT_TRUE(!(o1 > o1)); - EXPECT_TRUE(o1 <= o2); - EXPECT_TRUE(o1 <= o1); - EXPECT_TRUE(!(o1 >= o2)); - EXPECT_TRUE(o1 >= o1); - } - // SECTION("nullopt simple") - { - EXPECT_TRUE(!(o1 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o1)); - EXPECT_TRUE(o1 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o1); - EXPECT_TRUE(!(o1 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o1); - EXPECT_TRUE(o1 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o1)); - EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o1); - EXPECT_TRUE(o1 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o1)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - // SECTION("with T simple") - { - EXPECT_TRUE(!(o1 == 1)); - EXPECT_TRUE(!(1 == o1)); - EXPECT_TRUE(o1 != 1); - EXPECT_TRUE(1 != o1); - EXPECT_TRUE(!(o1 < 1)); - EXPECT_TRUE(1 < o1); - EXPECT_TRUE(o1 > 1); - EXPECT_TRUE(!(1 > o1)); - EXPECT_TRUE(!(o1 <= 1)); - EXPECT_TRUE(1 <= o1); - EXPECT_TRUE(o1 >= 1); - EXPECT_TRUE(!(1 >= o1)); - - EXPECT_TRUE(o1 == 4); - EXPECT_TRUE(4 == o1); - EXPECT_TRUE(!(o1 != 4)); - EXPECT_TRUE(!(4 != o1)); - EXPECT_TRUE(!(o1 < 4)); - EXPECT_TRUE(!(4 < o1)); - EXPECT_TRUE(!(o1 > 4)); - EXPECT_TRUE(!(4 > o1)); - EXPECT_TRUE(o1 <= 4); - EXPECT_TRUE(4 <= o1); - EXPECT_TRUE(o1 >= 4); - EXPECT_TRUE(4 >= o1); - } - beman::optional::optional o4{"hello"}; - beman::optional::optional o5{"xyz"}; - - // SECTION("self complex") - { - EXPECT_TRUE(!(o4 == o5)); - EXPECT_TRUE(o4 == o4); - EXPECT_TRUE(o4 != o5); - EXPECT_TRUE(!(o4 != o4)); - EXPECT_TRUE(o4 < o5); - EXPECT_TRUE(!(o4 < o4)); - EXPECT_TRUE(!(o4 > o5)); - EXPECT_TRUE(!(o4 > o4)); - EXPECT_TRUE(o4 <= o5); - EXPECT_TRUE(o4 <= o4); - EXPECT_TRUE(!(o4 >= o5)); - EXPECT_TRUE(o4 >= o4); - } - // SECTION("nullopt complex") - { - EXPECT_TRUE(!(o4 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o4)); - EXPECT_TRUE(o4 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o4); - EXPECT_TRUE(!(o4 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o4); - EXPECT_TRUE(o4 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o4)); - EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o4); - EXPECT_TRUE(o4 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o4)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - - // SECTION("with T complex") - { - EXPECT_TRUE(!(o4 == "a")); - EXPECT_TRUE(!("a" == o4)); - EXPECT_TRUE(o4 != "a"); - EXPECT_TRUE("a" != o4); - EXPECT_TRUE(!(o4 < "a")); - EXPECT_TRUE("a" < o4); - EXPECT_TRUE(o4 > "a"); - EXPECT_TRUE(!("a" > o4)); - EXPECT_TRUE(!(o4 <= "a")); - EXPECT_TRUE("a" <= o4); - EXPECT_TRUE(o4 >= "a"); - EXPECT_TRUE(!("a" >= o4)); - - EXPECT_TRUE(o4 == "hello"); - EXPECT_TRUE("hello" == o4); - EXPECT_TRUE(!(o4 != "hello")); - EXPECT_TRUE(!("hello" != o4)); - EXPECT_TRUE(!(o4 < "hello")); - EXPECT_TRUE(!("hello" < o4)); - EXPECT_TRUE(!(o4 > "hello")); - EXPECT_TRUE(!("hello" > o4)); - EXPECT_TRUE(o4 <= "hello"); - EXPECT_TRUE("hello" <= o4); - EXPECT_TRUE(o4 >= "hello"); - EXPECT_TRUE("hello" >= o4); - } -} - -TEST(OptionalTest, SwapValue) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = 12; - o1.swap(o2); - EXPECT_EQ(o1.value(), 12); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalTest, SwapWNull) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = beman::optional::nullopt; - o1.swap(o2); - EXPECT_TRUE(!o1.has_value()); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalTest, SwapNullIntializedWithValue) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = 42; - o1.swap(o2); - EXPECT_EQ(o1.value(), 42); - EXPECT_TRUE(!o2.has_value()); -} - -TEST(OptionalTest, Emplace) { - beman::optional::optional< - std::pair, std::pair>> - i; - i.emplace(std::piecewise_construct, - std::make_tuple(0, 2), - std::make_tuple(3, 4)); - EXPECT_TRUE(i->first.first == 0); - EXPECT_TRUE(i->first.second == 2); - EXPECT_TRUE(i->second.first == 3); - EXPECT_TRUE(i->second.second == 4); -} - -struct A { - A() { throw std::exception(); } -}; - -TEST(OptionalTest, EmplaceWithExceptionThrown) { - beman::optional::optional a; - EXPECT_ANY_THROW(a.emplace()); -} - -TEST(OptionalTest, RangeTest) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = 42; - EXPECT_EQ(*o2, 42); - for(auto k : o1) { - (void)k; - EXPECT_TRUE(false); - } - for(auto k : o2) { - EXPECT_EQ(k, 42); - } -} - -TEST(ViewMaybeTest, Constructors) { - std::ranges::single_view> s; - std::ranges::single_view> s2{s}; - std::ranges::single_view> s3{std::optional{}}; - - beman::optional::optional> n; - beman::optional::optional> n2{n}; - beman::optional::optional> n3{std::optional{}}; -} - -TEST(ViewMaybeTest, ConceptCheck) { - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(!std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - static_assert(std::ranges::sized_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); -} - -TEST(ViewMaybeTest, ConceptCheckRef) { - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper&; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); -} - -TEST(ViewMaybeTest, BreathingTest) { - beman::optional::optional m; - // ASSERT_TRUE(m.empty()); - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m.data() == nullptr); - - beman::optional::optional m1{1}; - // ASSERT_TRUE(!m1.empty()); - // ASSERT_TRUE(m1.size() == 1); - // ASSERT_TRUE(m1.data() != nullptr); - // ASSERT_TRUE(*(m1.data()) == 1); - - m = m1; - ASSERT_EQ(*std::begin(m), 1); - - m = {}; - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m1.size() == 1); - - beman::optional::optional d0{0}; - // ASSERT_TRUE(!d0.empty()); - - beman::optional::optional d1{1}; - // ASSERT_TRUE(!d1.empty()); - - d0 = d1; - ASSERT_EQ(*std::begin(d0), 1.0); -} - -TEST(ViewMaybeTest, BreathingTestRef) { - beman::optional::optional m; - // ASSERT_TRUE(m.empty()); - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m.data() == nullptr); - - int one = 1; - beman::optional::optional m1{one}; - // ASSERT_TRUE(!m1.empty()); - // ASSERT_TRUE(m1.size() == 1); - // ASSERT_TRUE(m1.data() != nullptr); - // ASSERT_TRUE(*(m1.data()) == 1); - - m = m1; - ASSERT_EQ(*std::begin(m), 1); - - // m = {}; - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m1.size() == 1); - - double zero = 0.0; - beman::optional::optional d0{zero}; - // ASSERT_TRUE(!d0.empty()); - - double one_d = 1.0; - beman::optional::optional d1{one_d}; - // ASSERT_TRUE(!d1.empty()); - - d0 = d1; - ASSERT_EQ(*std::begin(d0), 1.0); -} - -TEST(ViewMaybe, CompTest) { - beman::optional::optional m; - beman::optional::optional m0{0}; - beman::optional::optional m1{1}; - beman::optional::optional m1a{1}; - - ASSERT_EQ(m, m); - ASSERT_EQ(m0, m0); - ASSERT_EQ(m1, m1); - ASSERT_EQ(m1a, m1a); - ASSERT_EQ(m1, m1a); - - ASSERT_NE(m, m0); - ASSERT_NE(m0, m1); - - ASSERT_TRUE(m < m0); - ASSERT_TRUE(m0 < m1); - ASSERT_TRUE(m1 <= m1a); -} - -TEST(ViewMaybe, CompTestRef) { - beman::optional::optional m; - int zero = 0; - int one = 1; - int one_a = 1; - beman::optional::optional m0{zero}; - beman::optional::optional m1{one}; - beman::optional::optional m1a{one_a}; - - ASSERT_EQ(m, m); - ASSERT_EQ(m0, m0); - ASSERT_EQ(m1, m1); - ASSERT_EQ(m1a, m1a); - ASSERT_EQ(m1, m1a); - - ASSERT_NE(m, m0); - ASSERT_NE(m0, m1); - - ASSERT_TRUE(m < m0); - ASSERT_TRUE(m0 > m); - ASSERT_TRUE(m0 < m1); - ASSERT_TRUE(m1a <= m1); -} - -// "and_then" creates a new view by applying a -// transformation to each element in an input -// range, and flattening the resulting range of -// ranges. A.k.a. bind -// (This uses one syntax for constrained lambdas -// in C++20.) -inline constexpr auto and_then = [](auto&& r, auto fun) { - return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | - std::ranges::views::join; -}; - -// "yield_if" takes a bool and a value and -// returns a view of zero or one elements. -inline constexpr auto yield_if = [](bool b, T x) { - return b ? - beman::optional::optional{move(x)} : - beman::optional::nullopt; -}; - - -TEST(ViewMaybeTest, PythTripleTest) { - using std::ranges::views::iota; - auto triples = and_then(iota(1), [](int z) { - return and_then(iota(1, z + 1), [=](int x) { - return and_then(iota(x, z + 1), [=](int y) { - return yield_if(x * x + y * y == z * z, - std::make_tuple(x, y, z)); - }); - }); - }); - - ASSERT_EQ(*std::ranges::begin(triples), std::make_tuple(3, 4, 5)); -} - -using namespace beman; - -TEST(ViewMaybeTest, ValueBase) { - int i = 7; - beman::optional::optional v1{}; - // ASSERT_TRUE(v1.size() == 0); - - beman::optional::optional v2{i}; - // ASSERT_TRUE(v2.size() == 1); - for (auto i : v1) - ASSERT_TRUE(i != i); // tautology so i is used and not warned - - - for (auto i : v2) - ASSERT_EQ(i, 7); - -// ASSERT_EQ(v2[0], 7); // no match for operator[] -// auto x = v2[1000]; - - // int s = 4; - // for (auto&& i : views::maybe(s)) { - // ASSERT_EQ(i, 4); - // i = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 4); -} - -TEST(ViewMaybeTest, RefWrapper) { - int i = 7; - - beman::optional::optional v2{std::ref(i)}; - - for (auto i : v2) - ASSERT_EQ(i, 7); - - // int s = 4; - // for (auto&& i : views::maybe(std::ref(s))) { - // ASSERT_EQ(i, 4); - // i.get() = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 9); -} - - -TEST(ViewMaybeTest, ValueNonDefaultConstruct) { - NoDefault i = 7; - beman::optional::optional v1{}; - beman::optional::optional v2{i}; -} - -TEST(ViewMaybeTest, RefBase) { - int i = 7; - beman::optional::optional v1{}; - // ASSERT_TRUE(v1.size() == 0); - - beman::optional::optional v2{i}; - // ASSERT_TRUE(v2.size() == 1); - for (auto i : v1) - ASSERT_TRUE(i != i); // tautology so i is used and not warned - - for (auto i : v2) { - ASSERT_EQ(i, 7); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(i, 7); - - for (auto&& i : v2) { - ASSERT_EQ(i, 7); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(i, 9); - - int s = 4; - // for (auto&& i : views::maybe(s)) { - // ASSERT_EQ(i, 4); - // i = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 4); - - for (auto&& i : beman::optional::optional(s)) { - ASSERT_EQ(i, 4); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(s, 9); -} - -// TEST(ViewMaybeTest, MonadicAndThen) { -// beman::optional::optional mv{40}; -// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); -// ASSERT_TRUE(r2.empty()); -// ASSERT_TRUE(r2.size() == 0); -// ASSERT_TRUE(r2.data() == nullptr); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).and_then([](int&& i) { -// int k = i; -// i = 0; -// return beman::optional::optional{k + 2}; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); - -// const beman::optional::optional cmv{40}; -// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicTransform) { -// beman::optional::optional mv{40}; -// auto r = mv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.transform([](int& i) { -// i += 2; -// return i; -// }); -// ASSERT_TRUE(!r2.empty()); -// ASSERT_TRUE(r2.size() == 1); -// ASSERT_TRUE(r2.data() != nullptr); -// ASSERT_TRUE(*(r2.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 42); - -// beman::optional::optional empty{}; - -// auto r3 = empty.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.transform([](double d) { return d + 2; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 44.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 44); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 42); - -// auto r6 = std::move(mv).transform([](int&& i) { -// int k = i; -// i = 0; -// return k + 2; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 44); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); - -// const beman::optional::optional cmv{40}; -// auto r7 = cmv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicOrElse) { -// beman::optional::optional o1(42); -// auto r = o1.or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r.data()) == 42); - -// beman::optional::optional o2; -// ASSERT_TRUE(*(o2.or_else([] { return beman::optional::optional(13); })).data() == -// 13); - -// auto r2 = std::move(o1).or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r2.data()) == 42); - -// auto r3 = std::move(o2).or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r3.data()) == 13); -// } - -// TEST(ViewMaybeTest, MonadicAndThenRef) { -// int forty{40}; -// beman::optional::optional mv{forty}; -// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); -// ASSERT_TRUE(r2.empty()); -// ASSERT_TRUE(r2.size() == 0); -// ASSERT_TRUE(r2.data() == nullptr); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).and_then([](int&& i) { -// int k = i; -// i = 0; -// return beman::optional::optional{k + 2}; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); -// ASSERT_EQ(forty, 0); -// forty = 40; - -// const beman::optional::optional cmv{forty}; -// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_EQ(*(r7.data()), 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_EQ(*(r8.data()), 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicTransformRef) { -// int forty{40}; -// beman::optional::optional mv{forty}; -// auto r = mv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_EQ(*(r.data()), 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.transform([](double d) { return d + 2; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).transform([](int&& i) { -// int k = i; -// i = 0; -// return k + 2; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); -// ASSERT_EQ(forty, 0); -// forty = 40; - -// const beman::optional::optional cmv{forty}; -// ASSERT_EQ(*(cmv.data()), 40); -// auto r7 = cmv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r9 = mv.transform([](int& i) { -// int k = i; -// i = 56; -// return k * 2; -// }); -// ASSERT_TRUE(!r9.empty()); -// ASSERT_EQ(r9.size(), 1); -// ASSERT_TRUE(r9.data() != nullptr); -// for (auto r: r9) { -// ASSERT_EQ(r, 80); -// } -// ASSERT_TRUE(!mv.empty()); -// for (auto v: mv) { -// ASSERT_EQ(v, 56); -// } -// ASSERT_EQ(forty, 56); -// forty = 40; -// } - -// TEST(MaybeView, MonadicOrElseRef) { -// int fortytwo{42}; -// int thirteen{13}; -// beman::optional::optional o1(fortytwo); -// auto r = o1.or_else([&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r.data()) == 42); - -// beman::optional::optional o2; -// ASSERT_TRUE(*(o2.or_else([&thirteen] { -// return beman::optional::optional(thirteen); -// })).data() == 13); - -// auto r2 = std::move(o1).or_else( -// [&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r2.data()) == 42); - -// auto r3 = std::move(o2).or_else( -// [&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r3.data()) == 13); -// } diff --git a/src/beman/optional/optional_monadic.t.cpp b/src/beman/optional/optional_monadic.t.cpp deleted file mode 100644 index 79a1c6a7..00000000 --- a/src/beman/optional/optional_monadic.t.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include - -#include - -constexpr int get_int(int) { return 42; } -constexpr beman::optional::optional get_opt_int(int) { return 42; } - - -TEST(OptionalMonadicTest, Transform) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 40; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - beman::optional::optional o3 = 42; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o4 = 40; - auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - const beman::optional::optional o5 = 40; - auto o5r = o5.transform([](const int &i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = 42; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = 42; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = 42; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - - // callable which returns a reference - beman::optional::optional o38 = 42; - auto o38r = o38.transform([](int &i) -> const int & { return i; }); - EXPECT_TRUE(o38r); - EXPECT_TRUE(*o38r == 42); - - } - - TEST(OptionalMonadicTest, TransformConstexpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = 42; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = 42; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); - } - -TEST(OptionalMonadicTest, Transform2) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 40; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - beman::optional::optional o3 = 42; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o4 = 40; - auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - const beman::optional::optional o5 = 40; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = 42; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = 42; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = 42; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - } - - TEST(OptionalMonadicTest, TransformConstxpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = 42; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = 42; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); - } - -TEST(OptionalMonadicTest, and_then) - { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 12; - auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42.f); - - // lhs is empty, rhs returns empty - beman::optional::optional o3; - auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o3r); - - // rhs returns empty - beman::optional::optional o4 = 12; - auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o4r); - - struct rval_call_and_then { - beman::optional::optional operator()(int) && { - return beman::optional::optional(42.0); - }; - }; - - // ensure that function object is forwarded - beman::optional::optional o5 = 42; - auto o5r = o5.and_then(rval_call_and_then{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o6 = 42; - auto o6r = - std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o6r.value() == 42); - - // ensure that function object is const-propagated - const beman::optional::optional o7 = 42; - auto o7r = - o7.and_then([](const int &i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o7r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o9 = 42; - auto o9r = - std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o9r == 42); - - const beman::optional::optional o10 = 42; - auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o10r == 42); - - const beman::optional::optional o11 = 42; - auto o11r = - std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o11r == 42); - - beman::optional::optional o16 = beman::optional::nullopt; - auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o16r); - - beman::optional::optional o17 = beman::optional::nullopt; - auto o17r = - std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o17r); - - const beman::optional::optional o18 = beman::optional::nullopt; - auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o18r); - - const beman::optional::optional o19 = beman::optional::nullopt; - auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o19r); - - int i = 3; - beman::optional::optional o20{i}; - std::move(o20).and_then([](int& r){return beman::optional::optional{++r};}); - EXPECT_TRUE(o20); - EXPECT_TRUE(i == 4); - } - -TEST(OptionalMonadicTest, Constexpr_and_then) -{ - constexpr beman::optional::optional o10 = 42; - constexpr auto o10r = o10.and_then(get_opt_int); - EXPECT_TRUE(*o10r == 42); - - constexpr beman::optional::optional o11 = 42; - constexpr auto o11r = std::move(o11).and_then(get_opt_int); - EXPECT_TRUE(*o11r == 42); - - constexpr beman::optional::optional o18 = beman::optional::nullopt; - constexpr auto o18r = o18.and_then(get_opt_int); - EXPECT_TRUE(!o18r); - - constexpr beman::optional::optional o19 = beman::optional::nullopt; - constexpr auto o19r = std::move(o19).and_then(get_opt_int); - EXPECT_TRUE(!o19r); - } - -TEST(OptionalMonadicTest, or_else){ - beman::optional::optional o1 = 42; - EXPECT_TRUE(*(o1.or_else([] { return beman::optional::make_optional(13); })) == 42); - - beman::optional::optional o2; - EXPECT_EQ(*(o2.or_else([] { return beman::optional::make_optional(13); })), 13); - } diff --git a/src/beman/optional/optional_ref.t.cpp b/src/beman/optional/optional_ref.t.cpp deleted file mode 100644 index 3591256b..00000000 --- a/src/beman/optional/optional_ref.t.cpp +++ /dev/null @@ -1,560 +0,0 @@ -#include - -#include - -TEST(OptionalRefTest, TestGTest) { ASSERT_EQ(1, 1); } - -namespace { -struct empty {}; -struct no_default { - no_default() = delete; - no_default(const no_default&) = default; - no_default(no_default&&) = default; - no_default& operator=(const no_default&) = default; - no_default& operator=(no_default&&) = default; - no_default(empty){}; -}; - -struct base { - int i_; - base() : i_(0) {} - base(int i) : i_(i) {} -}; - -struct derived : public base { - int j_; - derived() : base(0), j_(0) {} - derived(int i, int j) : base(i), j_(j) {} -}; -} // namespace - -TEST(OptionalRefTest, Constructors) { - beman::optional::optional i1; - beman::optional::optional i2{beman::optional::nullopt}; - (void)i1; - (void)i2; - - int i = 0; - beman::optional::optional i3 = i; - (void)i3; - - beman::optional::optional e1; - beman::optional::optional e2{beman::optional::nullopt}; - (void)e1; - (void)e2; - - empty e{}; - beman::optional::optional e3 = e; - (void)e3; - - beman::optional::optional nd1; - beman::optional::optional nd2{beman::optional::nullopt}; - (void)nd1; - (void)nd2; - - no_default nd{e}; - - beman::optional::optional nd3 = nd; - (void)nd3; - - beman::optional::optional ie; - beman::optional::optional i4 = ie; - EXPECT_FALSE(i4); - - base b{1}; - derived d(1, 2); - beman::optional::optional b1 = b; - beman::optional::optional b2 = d; - - beman::optional::optional d2 = d; - beman::optional::optional b3 = d2; - beman::optional::optional b4{d2}; - - beman::optional::optional empty; - beman::optional::optional fromEmpty(empty); - beman::optional::optional fromEmpty2 = empty; -} - -TEST(OptionalRefTest, Assignment) { - beman::optional::optional i1; - EXPECT_FALSE(i1); - int i = 5; - i1 = i; - i = 7; - EXPECT_TRUE(i1); - EXPECT_TRUE(*i1 = 7); - - double d; - // i1 = d; // ill-formed by mandate - beman::optional::optional d1 = d; - // i1 = d1; // ill-formed by mandate - beman::optional::optional i2 = i1; - EXPECT_TRUE(i2); - EXPECT_TRUE(*i2 = 7); - - beman::optional::optional empty; - EXPECT_FALSE(empty); - i2 = empty; - EXPECT_FALSE(i2); - int eight = 8; - empty.emplace(eight); - EXPECT_TRUE(empty); - EXPECT_EQ(empty, 8); -} - -TEST(OptionalRefTest, RelationalOps) { - int i1 = 4; - int i2 = 42; - beman::optional::optional o1{i1}; - beman::optional::optional o2{i2}; - beman::optional::optional o3{}; - - // SECTION("self simple") - { - EXPECT_TRUE(!(o1 == o2)); - EXPECT_TRUE(o1 == o1); - EXPECT_TRUE(o1 != o2); - EXPECT_TRUE(!(o1 != o1)); - EXPECT_TRUE(o1 < o2); - EXPECT_TRUE(!(o1 < o1)); - EXPECT_TRUE(!(o1 > o2)); - EXPECT_TRUE(!(o1 > o1)); - EXPECT_TRUE(o1 <= o2); - EXPECT_TRUE(o1 <= o1); - EXPECT_TRUE(!(o1 >= o2)); - EXPECT_TRUE(o1 >= o1); - } - // SECTION("nullopt simple") - { - EXPECT_TRUE(!(o1 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o1)); - EXPECT_TRUE(o1 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o1); - EXPECT_TRUE(!(o1 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o1); - EXPECT_TRUE(o1 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o1)); - EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o1); - EXPECT_TRUE(o1 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o1)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - // SECTION("with T simple") - { - EXPECT_TRUE(!(o1 == 1)); - EXPECT_TRUE(!(1 == o1)); - EXPECT_TRUE(o1 != 1); - EXPECT_TRUE(1 != o1); - EXPECT_TRUE(!(o1 < 1)); - EXPECT_TRUE(1 < o1); - EXPECT_TRUE(o1 > 1); - EXPECT_TRUE(!(1 > o1)); - EXPECT_TRUE(!(o1 <= 1)); - EXPECT_TRUE(1 <= o1); - EXPECT_TRUE(o1 >= 1); - EXPECT_TRUE(!(1 >= o1)); - - EXPECT_TRUE(o1 == 4); - EXPECT_TRUE(4 == o1); - EXPECT_TRUE(!(o1 != 4)); - EXPECT_TRUE(!(4 != o1)); - EXPECT_TRUE(!(o1 < 4)); - EXPECT_TRUE(!(4 < o1)); - EXPECT_TRUE(!(o1 > 4)); - EXPECT_TRUE(!(4 > o1)); - EXPECT_TRUE(o1 <= 4); - EXPECT_TRUE(4 <= o1); - EXPECT_TRUE(o1 >= 4); - EXPECT_TRUE(4 >= o1); - } - std::string s4 = "hello"; - std::string s5 = "xyz"; - beman::optional::optional o4{s4}; - beman::optional::optional o5{s5}; - - // SECTION("self complex") - { - EXPECT_TRUE(!(o4 == o5)); - EXPECT_TRUE(o4 == o4); - EXPECT_TRUE(o4 != o5); - EXPECT_TRUE(!(o4 != o4)); - EXPECT_TRUE(o4 < o5); - EXPECT_TRUE(!(o4 < o4)); - EXPECT_TRUE(!(o4 > o5)); - EXPECT_TRUE(!(o4 > o4)); - EXPECT_TRUE(o4 <= o5); - EXPECT_TRUE(o4 <= o4); - EXPECT_TRUE(!(o4 >= o5)); - EXPECT_TRUE(o4 >= o4); - } - // SECTION("nullopt complex") - { - EXPECT_TRUE(!(o4 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o4)); - EXPECT_TRUE(o4 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o4); - EXPECT_TRUE(!(o4 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o4); - EXPECT_TRUE(o4 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o4)); - EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o4); - EXPECT_TRUE(o4 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o4)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - - // SECTION("with T complex") - { - EXPECT_TRUE(!(o4 == "a")); - EXPECT_TRUE(!("a" == o4)); - EXPECT_TRUE(o4 != "a"); - EXPECT_TRUE("a" != o4); - EXPECT_TRUE(!(o4 < "a")); - EXPECT_TRUE("a" < o4); - EXPECT_TRUE(o4 > "a"); - EXPECT_TRUE(!("a" > o4)); - EXPECT_TRUE(!(o4 <= "a")); - EXPECT_TRUE("a" <= o4); - EXPECT_TRUE(o4 >= "a"); - EXPECT_TRUE(!("a" >= o4)); - - EXPECT_TRUE(o4 == "hello"); - EXPECT_TRUE("hello" == o4); - EXPECT_TRUE(!(o4 != "hello")); - EXPECT_TRUE(!("hello" != o4)); - EXPECT_TRUE(!(o4 < "hello")); - EXPECT_TRUE(!("hello" < o4)); - EXPECT_TRUE(!(o4 > "hello")); - EXPECT_TRUE(!("hello" > o4)); - EXPECT_TRUE(o4 <= "hello"); - EXPECT_TRUE("hello" <= o4); - EXPECT_TRUE(o4 >= "hello"); - EXPECT_TRUE("hello" >= o4); - } -} - -TEST(OptionalRefTest, Triviality) { - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - } - - { - struct T { - T(const T&) {} - T(T&&){}; - T& operator=(const T&) { return *this; } - T& operator=(T&&) { return *this; }; - ~T() {} - }; - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - } -} - -TEST(OptionalRefTest, Deletion) { - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = delete; - T& operator=(const T&) = delete; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = default; - T& operator=(const T&) = delete; - T& operator=(T&&) = default; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = default; - T(T&&) = delete; - T& operator=(const T&) = default; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - } -} - -struct takes_init_and_variadic { - std::vector v; - std::tuple t; - template - takes_init_and_variadic(std::initializer_list l, Args&&... args) : v(l), t(std::forward(args)...) {} -}; - -TEST(OptionalRefTest, MakeOptional) { - int var{42}; - auto o1 = beman::optional::make_optional(var); - auto o2 = beman::optional::optional(var); - - constexpr bool is_same = std::is_same>::value; - EXPECT_TRUE(is_same); - EXPECT_TRUE(o1 == o2); - - std::tuple tvar{0, 1, 2, 3}; - auto o3 = beman::optional::make_optional&>(tvar); - EXPECT_TRUE(std::get<0>(*o3) == 0); - EXPECT_TRUE(std::get<1>(*o3) == 1); - EXPECT_TRUE(std::get<2>(*o3) == 2); - EXPECT_TRUE(std::get<3>(*o3) == 3); - - std::vector ivec{0, 1, 2, 3}; - auto o4 = beman::optional::make_optional&>(ivec); - EXPECT_TRUE(o4.value()[0] == 0); - EXPECT_TRUE(o4.value()[1] == 1); - EXPECT_TRUE(o4.value()[2] == 2); - EXPECT_TRUE(o4.value()[3] == 3); - - takes_init_and_variadic tiv{{0, 1}, 2, 3}; - auto o5 = beman::optional::make_optional(tiv); - EXPECT_TRUE(o5->v[0] == 0); - EXPECT_TRUE(o5->v[1] == 1); - EXPECT_TRUE(std::get<0>(o5->t) == 2); - EXPECT_TRUE(std::get<1>(o5->t) == 3); - - auto i = 42; - auto o6 = beman::optional::make_optional(i); - static_assert(std::is_same_v>); - - EXPECT_TRUE((std::is_same_v>)); - EXPECT_TRUE(o6); - EXPECT_TRUE(*o6 == 42); -} - -TEST(OptionalRefTest, Nullopt) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2{beman::optional::nullopt}; - beman::optional::optional o3(beman::optional::nullopt); - beman::optional::optional o4 = {beman::optional::nullopt}; - - EXPECT_TRUE(!o1); - EXPECT_TRUE(!o2); - EXPECT_TRUE(!o3); - EXPECT_TRUE(!o4); - - EXPECT_TRUE(!std::is_default_constructible::value); -} - -struct move_detector { - move_detector() = default; - move_detector(move_detector&& rhs) { rhs.been_moved = true; } - bool been_moved = false; -}; - -TEST(OptionalRefTest, Observers) { - int var = 42; - beman::optional::optional o1 = var; - beman::optional::optional o2; - const beman::optional::optional o3 = var; - const beman::optional::optional o4; - int var2 = 42; - int var3 = 6*9; - EXPECT_TRUE(*o1 == 42); - EXPECT_TRUE(*o1 == o1.value()); - EXPECT_TRUE(o2.value_or(var2) == 42); - EXPECT_TRUE(o3.value() == 42); - EXPECT_TRUE(o3.value_or(var3) == 42); - EXPECT_TRUE(o4.value_or(var3) == 54); - int j = 99; - EXPECT_TRUE(o4.value_or(j) == 99); - // o4.value_or(j) = 88; - // EXPECT_TRUE(j == 88); - int var99 = 99; - j = 88; - EXPECT_TRUE([&](){beman::optional::optional o(j);return o; }().value_or(var99) == 88); - - EXPECT_TRUE([&](){beman::optional::optional o;return o; }().value_or(var99) == 99); - - - EXPECT_TRUE(o3.value_or([&]()->int&{return var3;}()) == 42); - EXPECT_TRUE(o4.value_or([&]()->int&{return var3;}()) == 54); - - std::string meow{"meow"}; - std::string bark{"bark"}; - beman::optional::optional so1; - beman::optional::optional so2{meow}; - auto t1 = so1.value_or(bark); - auto t2 = so2.value_or(bark); - // auto t3 = so1.value_or("bark"); - // auto t4 = so2.value_or("bark"); - // std::tuple t("meow"); - - auto success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - - struct int_box {int i_;}; - int_box i1{3}; - beman::optional::optional ob1 = i1; - beman::optional::optional ob2; - const beman::optional::optional ob3 = i1; - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - -} - -TEST(OptionalRefTest, MoveCheck) { - int x = 0; - int& y = std::move(beman::optional::optional(x)).value(); - EXPECT_EQ(&y, &x); - - int& z = *std::move(beman::optional::optional(x)); - EXPECT_EQ(&z, &x); - -} - -TEST(OptionalRefTest, SwapValue) { - int var = 42; - int twelve = 12; - beman::optional::optional o1 = var; - beman::optional::optional o2 = twelve; - o1.swap(o2); - EXPECT_EQ(o1.value(), 12); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalRefTest, SwapWNull) { - int var = 42; - - beman::optional::optional o1 = var; - beman::optional::optional o2 = beman::optional::nullopt; - o1.swap(o2); - EXPECT_TRUE(!o1.has_value()); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalRefTest, SwapNullIntializedWithValue) { - int var = 42; - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = var; - o1.swap(o2); - EXPECT_EQ(o1.value(), 42); - EXPECT_TRUE(!o2.has_value()); -} diff --git a/src/beman/optional/optional_ref_monadic.t.cpp b/src/beman/optional/optional_ref_monadic.t.cpp deleted file mode 100644 index 9d9f9fda..00000000 --- a/src/beman/optional/optional_ref_monadic.t.cpp +++ /dev/null @@ -1,318 +0,0 @@ -#include - -#include - -namespace { -inline constexpr int constexpr_fortytwo = 42; -constexpr int get_int(int) { return constexpr_fortytwo; } -constexpr beman::optional::optional get_opt_int(int) { return constexpr_fortytwo; } -} // namespace - -TEST(OptionalRefMonadicTest, Transform) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int forty = 40; - beman::optional::optional o2 = forty; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o3 = fortytwo; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // // ensure that lhs is forwarded - // forty = 40; - // beman::optional::optional o4 = forty; - // auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - forty = 40; - const beman::optional::optional o5 = forty; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - fortytwo = 42; - beman::optional::optional o8 = fortytwo; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = fortytwo; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = fortytwo; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = fortytwo; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - - // callable which returns a reference - beman::optional::optional o38 = fortytwo; - auto o38r = o38.transform([](int& i) -> const int& { return i; }); - EXPECT_TRUE(o38r); - EXPECT_TRUE(*o38r == 42); -} - -TEST(OptionalRefMonadicTest, TransformConstexpr) { - - // test each overload in turn - constexpr beman::optional::optional o16 = constexpr_fortytwo; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = constexpr_fortytwo; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); -} - -TEST(OptionalRefMonadicTest, Transform2) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int forty = 40; - beman::optional::optional o2 = forty; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o3 = fortytwo; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // // ensure that lhs is forwarded - // int forty = 40; - // beman::optional::optional o4 = forty; - // auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - forty = 40; - const beman::optional::optional o5 = forty; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - fortytwo = 42; - beman::optional::optional o8 = fortytwo; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = fortytwo; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = fortytwo; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = fortytwo; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); -} - -TEST(OptionalRefMonadicTest, TransformConstxpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = constexpr_fortytwo; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = constexpr_fortytwo; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); -} - -TEST(OptionalRefMonadicTest, and_then) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int twelve = 12; - beman::optional::optional o2 = twelve; - auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42.f); - - // lhs is empty, rhs returns empty - beman::optional::optional o3; - auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o3r); - - // rhs returns empty - beman::optional::optional o4 = twelve; - auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o4r); - - struct rval_call_and_then { - beman::optional::optional operator()(int) && { return beman::optional::optional(42.0); }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o5 = fortytwo; - auto o5r = o5.and_then(rval_call_and_then{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // // ensure that lhs is forwarded - // beman::optional::optional o6 = fortytwo; - // auto o6r = - // std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o6r.value() == 42); - - // ensure that function object is const-propagated - const beman::optional::optional o7 = fortytwo; - auto o7r = o7.and_then([](const int& i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o7r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = fortytwo; - auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o9 = fortytwo; - auto o9r = std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o9r == 42); - - const beman::optional::optional o10 = fortytwo; - auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o10r == 42); - - const beman::optional::optional o11 = fortytwo; - auto o11r = std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o11r == 42); - - beman::optional::optional o16 = beman::optional::nullopt; - auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o16r); - - beman::optional::optional o17 = beman::optional::nullopt; - auto o17r = std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o17r); - - const beman::optional::optional o18 = beman::optional::nullopt; - auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o18r); - - const beman::optional::optional o19 = beman::optional::nullopt; - auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o19r); - - int i = 3; - beman::optional::optional o20{i}; - std::move(o20).and_then([](int& r) { return beman::optional::optional{++r}; }); - EXPECT_TRUE(o20); - EXPECT_TRUE(i == 4); -} - -TEST(OptionalRefMonadicTest, Constexpr_and_then) { - constexpr beman::optional::optional o10 = constexpr_fortytwo; - constexpr auto o10r = o10.and_then(get_opt_int); - EXPECT_TRUE(*o10r == 42); - - constexpr beman::optional::optional o11 = constexpr_fortytwo; - constexpr auto o11r = std::move(o11).and_then(get_opt_int); - EXPECT_TRUE(*o11r == 42); - - constexpr beman::optional::optional o18 = beman::optional::nullopt; - constexpr auto o18r = o18.and_then(get_opt_int); - EXPECT_TRUE(!o18r); - - constexpr beman::optional::optional o19 = beman::optional::nullopt; - constexpr auto o19r = std::move(o19).and_then(get_opt_int); - EXPECT_TRUE(!o19r); -} - -TEST(OptionalRefMonadicTest, or_else) { - int fortytwo = 42; - int thirteen = 13; - beman::optional::optional o1 = fortytwo; - EXPECT_TRUE(*(o1.or_else([&] { return beman::optional::optional(thirteen); })) == 42); - - beman::optional::optional o2; - EXPECT_EQ(*(o2.or_else([&] { return beman::optional::optional(thirteen); })), 13); -} diff --git a/src/beman/optional/tests/optional.t.cpp b/src/beman/optional/tests/optional.t.cpp deleted file mode 100644 index 9da8715d..00000000 --- a/src/beman/optional/tests/optional.t.cpp +++ /dev/null @@ -1,1278 +0,0 @@ -#include - -#include // test 2nd include OK - -#include -#include -#include - -#include - -TEST(OptionalTest, TestGTest) { ASSERT_EQ(1, 1); } - -namespace { -struct empty {}; -struct no_default { - no_default() = delete; - no_default(const no_default&) = default; - no_default(no_default&&) = default; - no_default& operator=(const no_default&) = default; - no_default& operator=(no_default&&) = default; - no_default(empty){}; -}; - -struct base { - int i_; - base() : i_(0) {} - base(int i) : i_(i) {} -}; - -struct derived : public base { - int j_; - derived() : base(0), j_(0) {} - derived(int i, int j) : base(i), j_(j) {} -}; -} // namespace - -TEST(OptionalTest, Constructors) { - beman::optional::optional i1; - beman::optional::optional i2{beman::optional::nullopt}; - - int i = 0; - beman::optional::optional i3 = i; - (void)i3; - - beman::optional::optional e1; - beman::optional::optional e2{beman::optional::nullopt}; - - empty e{}; - beman::optional::optional e3 = e; - (void)e3; -} - - -TEST(OptionalTest, Constructors2) { - beman::optional::optional o1; - EXPECT_TRUE(!o1); - - beman::optional::optional o2 = beman::optional::nullopt; - EXPECT_TRUE(!o2); - - beman::optional::optional o3 = 42; - EXPECT_TRUE(*o3 == 42); - - beman::optional::optional o4 = o3; - EXPECT_TRUE(*o4 == 42); - - beman::optional::optional o5 = o1; - EXPECT_TRUE(!o5); - - beman::optional::optional o6 = std::move(o3); - EXPECT_TRUE(*o6 == 42); - - beman::optional::optional o7 = 42; - EXPECT_TRUE(*o7 == 42); - - beman::optional::optional o8 = o7; - EXPECT_TRUE(*o8 == 42); - - beman::optional::optional o9 = std::move(o7); - EXPECT_TRUE(*o9 == 42); - - { - beman::optional::optional o; - EXPECT_TRUE(!o); - - beman::optional::optional oo = o; - EXPECT_TRUE(!oo); - } - - { - auto i = 42; - beman::optional::optional o = i; - EXPECT_TRUE(o); - EXPECT_TRUE(*o == 42); - - beman::optional::optional oo = o; - EXPECT_TRUE(oo); - EXPECT_TRUE(*oo == 42); - } - - std::vector v; - v.emplace_back(); - beman::optional::optional> ov = std::move(v); - EXPECT_TRUE(ov->size() == 1); -} - -TEST(OptionalTest, Constructors3) { - beman::optional::optional ie; - beman::optional::optional i4 = ie; - EXPECT_FALSE(i4); - - base b{1}; - derived d(1, 2); - beman::optional::optional b1{b}; - beman::optional::optional b2{d}; - - beman::optional::optional d2{d}; - beman::optional::optional b3 = d2; - beman::optional::optional b4{d2}; -} - -namespace { -class NoDefault { - int v_; - - public: - NoDefault(int v) : v_(v) {} -}; -} // namespace - -TEST(OptionalTest, NonDefaultConstruct) { - NoDefault i = 7; - beman::optional::optional v1{}; - beman::optional::optional v2{i}; -} - -TEST(OptionalTest, AssignmentValue) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = 12; - beman::optional::optional o3; - - o1 = o1; - EXPECT_TRUE(*o1 == 42); - - o1 = o2; - EXPECT_TRUE(*o1 == 12); - - o1 = o3; - EXPECT_TRUE(!o1); - - o1 = 42; - EXPECT_TRUE(*o1 == 42); - - o1 = beman::optional::nullopt; - EXPECT_TRUE(!o1); - - o1 = std::move(o2); - EXPECT_TRUE(*o1 == 12); - - beman::optional::optional o4 = 42; - - o1 = o4; - EXPECT_TRUE(*o1 == 42); - - o1 = std::move(o4); - EXPECT_TRUE(*o1 == 42); -} - -TEST(OptionalTest, Triviality) { - EXPECT_TRUE(std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE( - std::is_trivially_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE( - std::is_trivially_destructible>::value); - } - - { - struct T { - T(const T&) {} - T(T&&){}; - T& operator=(const T&) { return *this; } - T& operator=(T&&) { return *this; }; - ~T() {} - }; - EXPECT_TRUE(!std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_destructible< - beman::optional::optional>::value); - } -} - -TEST(OptionalTest, Deletion) { - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE( - std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE( - std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = delete; - T& operator=(const T&) = delete; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE( - !std::is_copy_constructible>::value); - EXPECT_TRUE( - !std::is_copy_assignable>::value); - EXPECT_TRUE( - !std::is_move_constructible>::value); - EXPECT_TRUE( - !std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = default; - T& operator=(const T&) = delete; - T& operator=(T&&) = default; - }; - EXPECT_TRUE( - !std::is_copy_constructible>::value); - EXPECT_TRUE( - !std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE( - std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = default; - T(T&&) = delete; - T& operator=(const T&) = default; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE( - std::is_copy_assignable>::value); - } -} - -struct takes_init_and_variadic { - std::vector v; - std::tuple t; - template - takes_init_and_variadic(std::initializer_list l, Args&&... args) - : v(l), t(std::forward(args)...) {} -}; - -TEST(OptionalTest, InPlace) { - beman::optional::optional o1{beman::optional::in_place}; - beman::optional::optional o2(beman::optional::in_place); - EXPECT_TRUE(o1); - EXPECT_TRUE(o1 == 0); - EXPECT_TRUE(o2); - EXPECT_TRUE(o2 == 0); - - beman::optional::optional o3(beman::optional::in_place, 42); - EXPECT_TRUE(o3 == 42); - - beman::optional::optional> o4( - beman::optional::in_place, 0, 1); - EXPECT_TRUE(o4); - EXPECT_TRUE(std::get<0>(*o4) == 0); - EXPECT_TRUE(std::get<1>(*o4) == 1); - - beman::optional::optional> o5(beman::optional::in_place, - {0, 1}); - EXPECT_TRUE(o5); - EXPECT_TRUE((*o5)[0] == 0); - EXPECT_TRUE((*o5)[1] == 1); - - beman::optional::optional o6( - beman::optional::in_place, {0, 1}, 2, 3); - EXPECT_TRUE(o6->v[0] == 0); - EXPECT_TRUE(o6->v[1] == 1); - EXPECT_TRUE(std::get<0>(o6->t) == 2); - EXPECT_TRUE(std::get<1>(o6->t) == 3); -} - -TEST(OptionalTest, MakeOptional) { - auto o1 = beman::optional::make_optional(42); - auto o2 = beman::optional::optional(42); - - constexpr bool is_same = - std::is_same>::value; - EXPECT_TRUE(is_same); - EXPECT_TRUE(o1 == o2); - - auto o3 = beman::optional::make_optional>( - 0, 1, 2, 3); - EXPECT_TRUE(std::get<0>(*o3) == 0); - EXPECT_TRUE(std::get<1>(*o3) == 1); - EXPECT_TRUE(std::get<2>(*o3) == 2); - EXPECT_TRUE(std::get<3>(*o3) == 3); - - auto o4 = beman::optional::make_optional>({0, 1, 2, 3}); - EXPECT_TRUE(o4.value()[0] == 0); - EXPECT_TRUE(o4.value()[1] == 1); - EXPECT_TRUE(o4.value()[2] == 2); - EXPECT_TRUE(o4.value()[3] == 3); - - auto o5 = - beman::optional::make_optional({0, 1}, 2, 3); - EXPECT_TRUE(o5->v[0] == 0); - EXPECT_TRUE(o5->v[1] == 1); - EXPECT_TRUE(std::get<0>(o5->t) == 2); - EXPECT_TRUE(std::get<1>(o5->t) == 3); - - auto i = 42; - auto o6 = beman::optional::make_optional(i); - static_assert(std::is_same>::value); - - EXPECT_TRUE( - (std::is_same>::value)); - EXPECT_TRUE(o6); - EXPECT_TRUE(*o6 == 42); -} - -TEST(OptionalTest, Nullopt) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2{beman::optional::nullopt}; - beman::optional::optional o3(beman::optional::nullopt); - beman::optional::optional o4 = {beman::optional::nullopt}; - - EXPECT_TRUE(!o1); - EXPECT_TRUE(!o2); - EXPECT_TRUE(!o3); - EXPECT_TRUE(!o4); - - EXPECT_TRUE( - !std::is_default_constructible::value); -} - -struct move_detector { - move_detector() = default; - move_detector(move_detector&& rhs) { rhs.been_moved = true; } - bool been_moved = false; -}; - -TEST(OptionalTest, Observers) { - beman::optional::optional o1 = 42; - beman::optional::optional o2; - const beman::optional::optional o3 = 42; - - EXPECT_TRUE(*o1 == 42); - EXPECT_TRUE(*o1 == o1.value()); - EXPECT_TRUE(o2.value_or(42) == 42); - EXPECT_TRUE(o3.value() == 42); - auto success = std::is_same::value; - EXPECT_TRUE(success); - success = std::is_same::value; - EXPECT_TRUE(success); - success = std::is_same::value; - EXPECT_TRUE(success); - - beman::optional::optional o4{beman::optional::in_place}; - move_detector o5 = std::move(o4).value(); - EXPECT_TRUE(o4->been_moved); - EXPECT_TRUE(!o5.been_moved); -} - -TEST(OptionalTest, RelationalOps) { - beman::optional::optional o1{4}; - beman::optional::optional o2{42}; - beman::optional::optional o3{}; - - // SECTION("self simple") - { - EXPECT_TRUE(!(o1 == o2)); - EXPECT_TRUE(o1 == o1); - EXPECT_TRUE(o1 != o2); - EXPECT_TRUE(!(o1 != o1)); - EXPECT_TRUE(o1 < o2); - EXPECT_TRUE(!(o1 < o1)); - EXPECT_TRUE(!(o1 > o2)); - EXPECT_TRUE(!(o1 > o1)); - EXPECT_TRUE(o1 <= o2); - EXPECT_TRUE(o1 <= o1); - EXPECT_TRUE(!(o1 >= o2)); - EXPECT_TRUE(o1 >= o1); - } - // SECTION("nullopt simple") - { - EXPECT_TRUE(!(o1 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o1)); - EXPECT_TRUE(o1 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o1); - EXPECT_TRUE(!(o1 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o1); - EXPECT_TRUE(o1 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o1)); - EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o1); - EXPECT_TRUE(o1 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o1)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - // SECTION("with T simple") - { - EXPECT_TRUE(!(o1 == 1)); - EXPECT_TRUE(!(1 == o1)); - EXPECT_TRUE(o1 != 1); - EXPECT_TRUE(1 != o1); - EXPECT_TRUE(!(o1 < 1)); - EXPECT_TRUE(1 < o1); - EXPECT_TRUE(o1 > 1); - EXPECT_TRUE(!(1 > o1)); - EXPECT_TRUE(!(o1 <= 1)); - EXPECT_TRUE(1 <= o1); - EXPECT_TRUE(o1 >= 1); - EXPECT_TRUE(!(1 >= o1)); - - EXPECT_TRUE(o1 == 4); - EXPECT_TRUE(4 == o1); - EXPECT_TRUE(!(o1 != 4)); - EXPECT_TRUE(!(4 != o1)); - EXPECT_TRUE(!(o1 < 4)); - EXPECT_TRUE(!(4 < o1)); - EXPECT_TRUE(!(o1 > 4)); - EXPECT_TRUE(!(4 > o1)); - EXPECT_TRUE(o1 <= 4); - EXPECT_TRUE(4 <= o1); - EXPECT_TRUE(o1 >= 4); - EXPECT_TRUE(4 >= o1); - } - beman::optional::optional o4{"hello"}; - beman::optional::optional o5{"xyz"}; - - // SECTION("self complex") - { - EXPECT_TRUE(!(o4 == o5)); - EXPECT_TRUE(o4 == o4); - EXPECT_TRUE(o4 != o5); - EXPECT_TRUE(!(o4 != o4)); - EXPECT_TRUE(o4 < o5); - EXPECT_TRUE(!(o4 < o4)); - EXPECT_TRUE(!(o4 > o5)); - EXPECT_TRUE(!(o4 > o4)); - EXPECT_TRUE(o4 <= o5); - EXPECT_TRUE(o4 <= o4); - EXPECT_TRUE(!(o4 >= o5)); - EXPECT_TRUE(o4 >= o4); - } - // SECTION("nullopt complex") - { - EXPECT_TRUE(!(o4 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o4)); - EXPECT_TRUE(o4 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o4); - EXPECT_TRUE(!(o4 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o4); - EXPECT_TRUE(o4 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o4)); - EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o4); - EXPECT_TRUE(o4 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o4)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - - // SECTION("with T complex") - { - EXPECT_TRUE(!(o4 == "a")); - EXPECT_TRUE(!("a" == o4)); - EXPECT_TRUE(o4 != "a"); - EXPECT_TRUE("a" != o4); - EXPECT_TRUE(!(o4 < "a")); - EXPECT_TRUE("a" < o4); - EXPECT_TRUE(o4 > "a"); - EXPECT_TRUE(!("a" > o4)); - EXPECT_TRUE(!(o4 <= "a")); - EXPECT_TRUE("a" <= o4); - EXPECT_TRUE(o4 >= "a"); - EXPECT_TRUE(!("a" >= o4)); - - EXPECT_TRUE(o4 == "hello"); - EXPECT_TRUE("hello" == o4); - EXPECT_TRUE(!(o4 != "hello")); - EXPECT_TRUE(!("hello" != o4)); - EXPECT_TRUE(!(o4 < "hello")); - EXPECT_TRUE(!("hello" < o4)); - EXPECT_TRUE(!(o4 > "hello")); - EXPECT_TRUE(!("hello" > o4)); - EXPECT_TRUE(o4 <= "hello"); - EXPECT_TRUE("hello" <= o4); - EXPECT_TRUE(o4 >= "hello"); - EXPECT_TRUE("hello" >= o4); - } -} - -TEST(OptionalTest, SwapValue) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = 12; - o1.swap(o2); - EXPECT_EQ(o1.value(), 12); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalTest, SwapWNull) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = beman::optional::nullopt; - o1.swap(o2); - EXPECT_TRUE(!o1.has_value()); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalTest, SwapNullIntializedWithValue) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = 42; - o1.swap(o2); - EXPECT_EQ(o1.value(), 42); - EXPECT_TRUE(!o2.has_value()); -} - -TEST(OptionalTest, Emplace) { - beman::optional::optional< - std::pair, std::pair>> - i; - i.emplace(std::piecewise_construct, - std::make_tuple(0, 2), - std::make_tuple(3, 4)); - EXPECT_TRUE(i->first.first == 0); - EXPECT_TRUE(i->first.second == 2); - EXPECT_TRUE(i->second.first == 3); - EXPECT_TRUE(i->second.second == 4); -} - -struct A { - A() { throw std::exception(); } -}; - -TEST(OptionalTest, EmplaceWithExceptionThrown) { - beman::optional::optional a; - EXPECT_ANY_THROW(a.emplace()); -} - -TEST(OptionalTest, RangeTest) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = 42; - EXPECT_EQ(*o2, 42); - for(auto k : o1) { - (void)k; - EXPECT_TRUE(false); - } - for(auto k : o2) { - EXPECT_EQ(k, 42); - } -} - -TEST(ViewMaybeTest, Constructors) { - std::ranges::single_view> s; - std::ranges::single_view> s2{s}; - std::ranges::single_view> s3{std::optional{}}; - - beman::optional::optional> n; - beman::optional::optional> n2{n}; - beman::optional::optional> n3{std::optional{}}; -} - -TEST(ViewMaybeTest, ConceptCheck) { - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(!std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - static_assert(std::ranges::sized_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); -} - -TEST(ViewMaybeTest, ConceptCheckRef) { - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper&; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); -} - -TEST(ViewMaybeTest, BreathingTest) { - beman::optional::optional m; - // ASSERT_TRUE(m.empty()); - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m.data() == nullptr); - - beman::optional::optional m1{1}; - // ASSERT_TRUE(!m1.empty()); - // ASSERT_TRUE(m1.size() == 1); - // ASSERT_TRUE(m1.data() != nullptr); - // ASSERT_TRUE(*(m1.data()) == 1); - - m = m1; - ASSERT_EQ(*std::begin(m), 1); - - m = {}; - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m1.size() == 1); - - beman::optional::optional d0{0}; - // ASSERT_TRUE(!d0.empty()); - - beman::optional::optional d1{1}; - // ASSERT_TRUE(!d1.empty()); - - d0 = d1; - ASSERT_EQ(*std::begin(d0), 1.0); -} - -TEST(ViewMaybeTest, BreathingTestRef) { - beman::optional::optional m; - // ASSERT_TRUE(m.empty()); - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m.data() == nullptr); - - int one = 1; - beman::optional::optional m1{one}; - // ASSERT_TRUE(!m1.empty()); - // ASSERT_TRUE(m1.size() == 1); - // ASSERT_TRUE(m1.data() != nullptr); - // ASSERT_TRUE(*(m1.data()) == 1); - - m = m1; - ASSERT_EQ(*std::begin(m), 1); - - // m = {}; - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m1.size() == 1); - - double zero = 0.0; - beman::optional::optional d0{zero}; - // ASSERT_TRUE(!d0.empty()); - - double one_d = 1.0; - beman::optional::optional d1{one_d}; - // ASSERT_TRUE(!d1.empty()); - - d0 = d1; - ASSERT_EQ(*std::begin(d0), 1.0); -} - -TEST(ViewMaybe, CompTest) { - beman::optional::optional m; - beman::optional::optional m0{0}; - beman::optional::optional m1{1}; - beman::optional::optional m1a{1}; - - ASSERT_EQ(m, m); - ASSERT_EQ(m0, m0); - ASSERT_EQ(m1, m1); - ASSERT_EQ(m1a, m1a); - ASSERT_EQ(m1, m1a); - - ASSERT_NE(m, m0); - ASSERT_NE(m0, m1); - - ASSERT_TRUE(m < m0); - ASSERT_TRUE(m0 < m1); - ASSERT_TRUE(m1 <= m1a); -} - -TEST(ViewMaybe, CompTestRef) { - beman::optional::optional m; - int zero = 0; - int one = 1; - int one_a = 1; - beman::optional::optional m0{zero}; - beman::optional::optional m1{one}; - beman::optional::optional m1a{one_a}; - - ASSERT_EQ(m, m); - ASSERT_EQ(m0, m0); - ASSERT_EQ(m1, m1); - ASSERT_EQ(m1a, m1a); - ASSERT_EQ(m1, m1a); - - ASSERT_NE(m, m0); - ASSERT_NE(m0, m1); - - ASSERT_TRUE(m < m0); - ASSERT_TRUE(m0 > m); - ASSERT_TRUE(m0 < m1); - ASSERT_TRUE(m1a <= m1); -} - -// "and_then" creates a new view by applying a -// transformation to each element in an input -// range, and flattening the resulting range of -// ranges. A.k.a. bind -// (This uses one syntax for constrained lambdas -// in C++20.) -inline constexpr auto and_then = [](auto&& r, auto fun) { - return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | - std::ranges::views::join; -}; - -// "yield_if" takes a bool and a value and -// returns a view of zero or one elements. -inline constexpr auto yield_if = [](bool b, T x) { - return b ? - beman::optional::optional{move(x)} : - beman::optional::nullopt; -}; - - -TEST(ViewMaybeTest, PythTripleTest) { - using std::ranges::views::iota; - auto triples = and_then(iota(1), [](int z) { - return and_then(iota(1, z + 1), [=](int x) { - return and_then(iota(x, z + 1), [=](int y) { - return yield_if(x * x + y * y == z * z, - std::make_tuple(x, y, z)); - }); - }); - }); - - ASSERT_EQ(*std::ranges::begin(triples), std::make_tuple(3, 4, 5)); -} - -using namespace beman; - -TEST(ViewMaybeTest, ValueBase) { - int i = 7; - beman::optional::optional v1{}; - // ASSERT_TRUE(v1.size() == 0); - - beman::optional::optional v2{i}; - // ASSERT_TRUE(v2.size() == 1); - for (auto i : v1) - ASSERT_TRUE(i != i); // tautology so i is used and not warned - - - for (auto i : v2) - ASSERT_EQ(i, 7); - -// ASSERT_EQ(v2[0], 7); // no match for operator[] -// auto x = v2[1000]; - - // int s = 4; - // for (auto&& i : views::maybe(s)) { - // ASSERT_EQ(i, 4); - // i = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 4); -} - -TEST(ViewMaybeTest, RefWrapper) { - int i = 7; - - beman::optional::optional v2{std::ref(i)}; - - for (auto i : v2) - ASSERT_EQ(i, 7); - - // int s = 4; - // for (auto&& i : views::maybe(std::ref(s))) { - // ASSERT_EQ(i, 4); - // i.get() = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 9); -} - - -TEST(ViewMaybeTest, ValueNonDefaultConstruct) { - NoDefault i = 7; - beman::optional::optional v1{}; - beman::optional::optional v2{i}; -} - -TEST(ViewMaybeTest, RefBase) { - int i = 7; - beman::optional::optional v1{}; - // ASSERT_TRUE(v1.size() == 0); - - beman::optional::optional v2{i}; - // ASSERT_TRUE(v2.size() == 1); - for (auto i : v1) - ASSERT_TRUE(i != i); // tautology so i is used and not warned - - for (auto i : v2) { - ASSERT_EQ(i, 7); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(i, 7); - - for (auto&& i : v2) { - ASSERT_EQ(i, 7); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(i, 9); - - int s = 4; - // for (auto&& i : views::maybe(s)) { - // ASSERT_EQ(i, 4); - // i = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 4); - - for (auto&& i : beman::optional::optional(s)) { - ASSERT_EQ(i, 4); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(s, 9); -} - -// TEST(ViewMaybeTest, MonadicAndThen) { -// beman::optional::optional mv{40}; -// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); -// ASSERT_TRUE(r2.empty()); -// ASSERT_TRUE(r2.size() == 0); -// ASSERT_TRUE(r2.data() == nullptr); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).and_then([](int&& i) { -// int k = i; -// i = 0; -// return beman::optional::optional{k + 2}; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); - -// const beman::optional::optional cmv{40}; -// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicTransform) { -// beman::optional::optional mv{40}; -// auto r = mv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.transform([](int& i) { -// i += 2; -// return i; -// }); -// ASSERT_TRUE(!r2.empty()); -// ASSERT_TRUE(r2.size() == 1); -// ASSERT_TRUE(r2.data() != nullptr); -// ASSERT_TRUE(*(r2.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 42); - -// beman::optional::optional empty{}; - -// auto r3 = empty.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.transform([](double d) { return d + 2; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 44.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 44); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 42); - -// auto r6 = std::move(mv).transform([](int&& i) { -// int k = i; -// i = 0; -// return k + 2; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 44); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); - -// const beman::optional::optional cmv{40}; -// auto r7 = cmv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicOrElse) { -// beman::optional::optional o1(42); -// auto r = o1.or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r.data()) == 42); - -// beman::optional::optional o2; -// ASSERT_TRUE(*(o2.or_else([] { return beman::optional::optional(13); })).data() == -// 13); - -// auto r2 = std::move(o1).or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r2.data()) == 42); - -// auto r3 = std::move(o2).or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r3.data()) == 13); -// } - -// TEST(ViewMaybeTest, MonadicAndThenRef) { -// int forty{40}; -// beman::optional::optional mv{forty}; -// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); -// ASSERT_TRUE(r2.empty()); -// ASSERT_TRUE(r2.size() == 0); -// ASSERT_TRUE(r2.data() == nullptr); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).and_then([](int&& i) { -// int k = i; -// i = 0; -// return beman::optional::optional{k + 2}; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); -// ASSERT_EQ(forty, 0); -// forty = 40; - -// const beman::optional::optional cmv{forty}; -// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_EQ(*(r7.data()), 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_EQ(*(r8.data()), 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicTransformRef) { -// int forty{40}; -// beman::optional::optional mv{forty}; -// auto r = mv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_EQ(*(r.data()), 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.transform([](double d) { return d + 2; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).transform([](int&& i) { -// int k = i; -// i = 0; -// return k + 2; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); -// ASSERT_EQ(forty, 0); -// forty = 40; - -// const beman::optional::optional cmv{forty}; -// ASSERT_EQ(*(cmv.data()), 40); -// auto r7 = cmv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r9 = mv.transform([](int& i) { -// int k = i; -// i = 56; -// return k * 2; -// }); -// ASSERT_TRUE(!r9.empty()); -// ASSERT_EQ(r9.size(), 1); -// ASSERT_TRUE(r9.data() != nullptr); -// for (auto r: r9) { -// ASSERT_EQ(r, 80); -// } -// ASSERT_TRUE(!mv.empty()); -// for (auto v: mv) { -// ASSERT_EQ(v, 56); -// } -// ASSERT_EQ(forty, 56); -// forty = 40; -// } - -// TEST(MaybeView, MonadicOrElseRef) { -// int fortytwo{42}; -// int thirteen{13}; -// beman::optional::optional o1(fortytwo); -// auto r = o1.or_else([&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r.data()) == 42); - -// beman::optional::optional o2; -// ASSERT_TRUE(*(o2.or_else([&thirteen] { -// return beman::optional::optional(thirteen); -// })).data() == 13); - -// auto r2 = std::move(o1).or_else( -// [&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r2.data()) == 42); - -// auto r3 = std::move(o2).or_else( -// [&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r3.data()) == 13); -// } diff --git a/src/beman/optional/tests/optional_monadic.t.cpp b/src/beman/optional/tests/optional_monadic.t.cpp deleted file mode 100644 index 79a1c6a7..00000000 --- a/src/beman/optional/tests/optional_monadic.t.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include - -#include - -constexpr int get_int(int) { return 42; } -constexpr beman::optional::optional get_opt_int(int) { return 42; } - - -TEST(OptionalMonadicTest, Transform) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 40; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - beman::optional::optional o3 = 42; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o4 = 40; - auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - const beman::optional::optional o5 = 40; - auto o5r = o5.transform([](const int &i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = 42; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = 42; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = 42; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - - // callable which returns a reference - beman::optional::optional o38 = 42; - auto o38r = o38.transform([](int &i) -> const int & { return i; }); - EXPECT_TRUE(o38r); - EXPECT_TRUE(*o38r == 42); - - } - - TEST(OptionalMonadicTest, TransformConstexpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = 42; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = 42; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); - } - -TEST(OptionalMonadicTest, Transform2) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 40; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - beman::optional::optional o3 = 42; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o4 = 40; - auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - const beman::optional::optional o5 = 40; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = 42; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = 42; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = 42; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - } - - TEST(OptionalMonadicTest, TransformConstxpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = 42; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = 42; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); - } - -TEST(OptionalMonadicTest, and_then) - { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 12; - auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42.f); - - // lhs is empty, rhs returns empty - beman::optional::optional o3; - auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o3r); - - // rhs returns empty - beman::optional::optional o4 = 12; - auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o4r); - - struct rval_call_and_then { - beman::optional::optional operator()(int) && { - return beman::optional::optional(42.0); - }; - }; - - // ensure that function object is forwarded - beman::optional::optional o5 = 42; - auto o5r = o5.and_then(rval_call_and_then{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o6 = 42; - auto o6r = - std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o6r.value() == 42); - - // ensure that function object is const-propagated - const beman::optional::optional o7 = 42; - auto o7r = - o7.and_then([](const int &i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o7r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o9 = 42; - auto o9r = - std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o9r == 42); - - const beman::optional::optional o10 = 42; - auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o10r == 42); - - const beman::optional::optional o11 = 42; - auto o11r = - std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o11r == 42); - - beman::optional::optional o16 = beman::optional::nullopt; - auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o16r); - - beman::optional::optional o17 = beman::optional::nullopt; - auto o17r = - std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o17r); - - const beman::optional::optional o18 = beman::optional::nullopt; - auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o18r); - - const beman::optional::optional o19 = beman::optional::nullopt; - auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o19r); - - int i = 3; - beman::optional::optional o20{i}; - std::move(o20).and_then([](int& r){return beman::optional::optional{++r};}); - EXPECT_TRUE(o20); - EXPECT_TRUE(i == 4); - } - -TEST(OptionalMonadicTest, Constexpr_and_then) -{ - constexpr beman::optional::optional o10 = 42; - constexpr auto o10r = o10.and_then(get_opt_int); - EXPECT_TRUE(*o10r == 42); - - constexpr beman::optional::optional o11 = 42; - constexpr auto o11r = std::move(o11).and_then(get_opt_int); - EXPECT_TRUE(*o11r == 42); - - constexpr beman::optional::optional o18 = beman::optional::nullopt; - constexpr auto o18r = o18.and_then(get_opt_int); - EXPECT_TRUE(!o18r); - - constexpr beman::optional::optional o19 = beman::optional::nullopt; - constexpr auto o19r = std::move(o19).and_then(get_opt_int); - EXPECT_TRUE(!o19r); - } - -TEST(OptionalMonadicTest, or_else){ - beman::optional::optional o1 = 42; - EXPECT_TRUE(*(o1.or_else([] { return beman::optional::make_optional(13); })) == 42); - - beman::optional::optional o2; - EXPECT_EQ(*(o2.or_else([] { return beman::optional::make_optional(13); })), 13); - } diff --git a/src/beman/optional/tests/optional_ref.t.cpp b/src/beman/optional/tests/optional_ref.t.cpp deleted file mode 100644 index 3591256b..00000000 --- a/src/beman/optional/tests/optional_ref.t.cpp +++ /dev/null @@ -1,560 +0,0 @@ -#include - -#include - -TEST(OptionalRefTest, TestGTest) { ASSERT_EQ(1, 1); } - -namespace { -struct empty {}; -struct no_default { - no_default() = delete; - no_default(const no_default&) = default; - no_default(no_default&&) = default; - no_default& operator=(const no_default&) = default; - no_default& operator=(no_default&&) = default; - no_default(empty){}; -}; - -struct base { - int i_; - base() : i_(0) {} - base(int i) : i_(i) {} -}; - -struct derived : public base { - int j_; - derived() : base(0), j_(0) {} - derived(int i, int j) : base(i), j_(j) {} -}; -} // namespace - -TEST(OptionalRefTest, Constructors) { - beman::optional::optional i1; - beman::optional::optional i2{beman::optional::nullopt}; - (void)i1; - (void)i2; - - int i = 0; - beman::optional::optional i3 = i; - (void)i3; - - beman::optional::optional e1; - beman::optional::optional e2{beman::optional::nullopt}; - (void)e1; - (void)e2; - - empty e{}; - beman::optional::optional e3 = e; - (void)e3; - - beman::optional::optional nd1; - beman::optional::optional nd2{beman::optional::nullopt}; - (void)nd1; - (void)nd2; - - no_default nd{e}; - - beman::optional::optional nd3 = nd; - (void)nd3; - - beman::optional::optional ie; - beman::optional::optional i4 = ie; - EXPECT_FALSE(i4); - - base b{1}; - derived d(1, 2); - beman::optional::optional b1 = b; - beman::optional::optional b2 = d; - - beman::optional::optional d2 = d; - beman::optional::optional b3 = d2; - beman::optional::optional b4{d2}; - - beman::optional::optional empty; - beman::optional::optional fromEmpty(empty); - beman::optional::optional fromEmpty2 = empty; -} - -TEST(OptionalRefTest, Assignment) { - beman::optional::optional i1; - EXPECT_FALSE(i1); - int i = 5; - i1 = i; - i = 7; - EXPECT_TRUE(i1); - EXPECT_TRUE(*i1 = 7); - - double d; - // i1 = d; // ill-formed by mandate - beman::optional::optional d1 = d; - // i1 = d1; // ill-formed by mandate - beman::optional::optional i2 = i1; - EXPECT_TRUE(i2); - EXPECT_TRUE(*i2 = 7); - - beman::optional::optional empty; - EXPECT_FALSE(empty); - i2 = empty; - EXPECT_FALSE(i2); - int eight = 8; - empty.emplace(eight); - EXPECT_TRUE(empty); - EXPECT_EQ(empty, 8); -} - -TEST(OptionalRefTest, RelationalOps) { - int i1 = 4; - int i2 = 42; - beman::optional::optional o1{i1}; - beman::optional::optional o2{i2}; - beman::optional::optional o3{}; - - // SECTION("self simple") - { - EXPECT_TRUE(!(o1 == o2)); - EXPECT_TRUE(o1 == o1); - EXPECT_TRUE(o1 != o2); - EXPECT_TRUE(!(o1 != o1)); - EXPECT_TRUE(o1 < o2); - EXPECT_TRUE(!(o1 < o1)); - EXPECT_TRUE(!(o1 > o2)); - EXPECT_TRUE(!(o1 > o1)); - EXPECT_TRUE(o1 <= o2); - EXPECT_TRUE(o1 <= o1); - EXPECT_TRUE(!(o1 >= o2)); - EXPECT_TRUE(o1 >= o1); - } - // SECTION("nullopt simple") - { - EXPECT_TRUE(!(o1 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o1)); - EXPECT_TRUE(o1 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o1); - EXPECT_TRUE(!(o1 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o1); - EXPECT_TRUE(o1 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o1)); - EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o1); - EXPECT_TRUE(o1 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o1)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - // SECTION("with T simple") - { - EXPECT_TRUE(!(o1 == 1)); - EXPECT_TRUE(!(1 == o1)); - EXPECT_TRUE(o1 != 1); - EXPECT_TRUE(1 != o1); - EXPECT_TRUE(!(o1 < 1)); - EXPECT_TRUE(1 < o1); - EXPECT_TRUE(o1 > 1); - EXPECT_TRUE(!(1 > o1)); - EXPECT_TRUE(!(o1 <= 1)); - EXPECT_TRUE(1 <= o1); - EXPECT_TRUE(o1 >= 1); - EXPECT_TRUE(!(1 >= o1)); - - EXPECT_TRUE(o1 == 4); - EXPECT_TRUE(4 == o1); - EXPECT_TRUE(!(o1 != 4)); - EXPECT_TRUE(!(4 != o1)); - EXPECT_TRUE(!(o1 < 4)); - EXPECT_TRUE(!(4 < o1)); - EXPECT_TRUE(!(o1 > 4)); - EXPECT_TRUE(!(4 > o1)); - EXPECT_TRUE(o1 <= 4); - EXPECT_TRUE(4 <= o1); - EXPECT_TRUE(o1 >= 4); - EXPECT_TRUE(4 >= o1); - } - std::string s4 = "hello"; - std::string s5 = "xyz"; - beman::optional::optional o4{s4}; - beman::optional::optional o5{s5}; - - // SECTION("self complex") - { - EXPECT_TRUE(!(o4 == o5)); - EXPECT_TRUE(o4 == o4); - EXPECT_TRUE(o4 != o5); - EXPECT_TRUE(!(o4 != o4)); - EXPECT_TRUE(o4 < o5); - EXPECT_TRUE(!(o4 < o4)); - EXPECT_TRUE(!(o4 > o5)); - EXPECT_TRUE(!(o4 > o4)); - EXPECT_TRUE(o4 <= o5); - EXPECT_TRUE(o4 <= o4); - EXPECT_TRUE(!(o4 >= o5)); - EXPECT_TRUE(o4 >= o4); - } - // SECTION("nullopt complex") - { - EXPECT_TRUE(!(o4 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o4)); - EXPECT_TRUE(o4 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o4); - EXPECT_TRUE(!(o4 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o4); - EXPECT_TRUE(o4 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o4)); - EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o4); - EXPECT_TRUE(o4 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o4)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - - // SECTION("with T complex") - { - EXPECT_TRUE(!(o4 == "a")); - EXPECT_TRUE(!("a" == o4)); - EXPECT_TRUE(o4 != "a"); - EXPECT_TRUE("a" != o4); - EXPECT_TRUE(!(o4 < "a")); - EXPECT_TRUE("a" < o4); - EXPECT_TRUE(o4 > "a"); - EXPECT_TRUE(!("a" > o4)); - EXPECT_TRUE(!(o4 <= "a")); - EXPECT_TRUE("a" <= o4); - EXPECT_TRUE(o4 >= "a"); - EXPECT_TRUE(!("a" >= o4)); - - EXPECT_TRUE(o4 == "hello"); - EXPECT_TRUE("hello" == o4); - EXPECT_TRUE(!(o4 != "hello")); - EXPECT_TRUE(!("hello" != o4)); - EXPECT_TRUE(!(o4 < "hello")); - EXPECT_TRUE(!("hello" < o4)); - EXPECT_TRUE(!(o4 > "hello")); - EXPECT_TRUE(!("hello" > o4)); - EXPECT_TRUE(o4 <= "hello"); - EXPECT_TRUE("hello" <= o4); - EXPECT_TRUE(o4 >= "hello"); - EXPECT_TRUE("hello" >= o4); - } -} - -TEST(OptionalRefTest, Triviality) { - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - } - - { - struct T { - T(const T&) {} - T(T&&){}; - T& operator=(const T&) { return *this; } - T& operator=(T&&) { return *this; }; - ~T() {} - }; - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - } -} - -TEST(OptionalRefTest, Deletion) { - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = delete; - T& operator=(const T&) = delete; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = default; - T& operator=(const T&) = delete; - T& operator=(T&&) = default; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = default; - T(T&&) = delete; - T& operator=(const T&) = default; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - } -} - -struct takes_init_and_variadic { - std::vector v; - std::tuple t; - template - takes_init_and_variadic(std::initializer_list l, Args&&... args) : v(l), t(std::forward(args)...) {} -}; - -TEST(OptionalRefTest, MakeOptional) { - int var{42}; - auto o1 = beman::optional::make_optional(var); - auto o2 = beman::optional::optional(var); - - constexpr bool is_same = std::is_same>::value; - EXPECT_TRUE(is_same); - EXPECT_TRUE(o1 == o2); - - std::tuple tvar{0, 1, 2, 3}; - auto o3 = beman::optional::make_optional&>(tvar); - EXPECT_TRUE(std::get<0>(*o3) == 0); - EXPECT_TRUE(std::get<1>(*o3) == 1); - EXPECT_TRUE(std::get<2>(*o3) == 2); - EXPECT_TRUE(std::get<3>(*o3) == 3); - - std::vector ivec{0, 1, 2, 3}; - auto o4 = beman::optional::make_optional&>(ivec); - EXPECT_TRUE(o4.value()[0] == 0); - EXPECT_TRUE(o4.value()[1] == 1); - EXPECT_TRUE(o4.value()[2] == 2); - EXPECT_TRUE(o4.value()[3] == 3); - - takes_init_and_variadic tiv{{0, 1}, 2, 3}; - auto o5 = beman::optional::make_optional(tiv); - EXPECT_TRUE(o5->v[0] == 0); - EXPECT_TRUE(o5->v[1] == 1); - EXPECT_TRUE(std::get<0>(o5->t) == 2); - EXPECT_TRUE(std::get<1>(o5->t) == 3); - - auto i = 42; - auto o6 = beman::optional::make_optional(i); - static_assert(std::is_same_v>); - - EXPECT_TRUE((std::is_same_v>)); - EXPECT_TRUE(o6); - EXPECT_TRUE(*o6 == 42); -} - -TEST(OptionalRefTest, Nullopt) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2{beman::optional::nullopt}; - beman::optional::optional o3(beman::optional::nullopt); - beman::optional::optional o4 = {beman::optional::nullopt}; - - EXPECT_TRUE(!o1); - EXPECT_TRUE(!o2); - EXPECT_TRUE(!o3); - EXPECT_TRUE(!o4); - - EXPECT_TRUE(!std::is_default_constructible::value); -} - -struct move_detector { - move_detector() = default; - move_detector(move_detector&& rhs) { rhs.been_moved = true; } - bool been_moved = false; -}; - -TEST(OptionalRefTest, Observers) { - int var = 42; - beman::optional::optional o1 = var; - beman::optional::optional o2; - const beman::optional::optional o3 = var; - const beman::optional::optional o4; - int var2 = 42; - int var3 = 6*9; - EXPECT_TRUE(*o1 == 42); - EXPECT_TRUE(*o1 == o1.value()); - EXPECT_TRUE(o2.value_or(var2) == 42); - EXPECT_TRUE(o3.value() == 42); - EXPECT_TRUE(o3.value_or(var3) == 42); - EXPECT_TRUE(o4.value_or(var3) == 54); - int j = 99; - EXPECT_TRUE(o4.value_or(j) == 99); - // o4.value_or(j) = 88; - // EXPECT_TRUE(j == 88); - int var99 = 99; - j = 88; - EXPECT_TRUE([&](){beman::optional::optional o(j);return o; }().value_or(var99) == 88); - - EXPECT_TRUE([&](){beman::optional::optional o;return o; }().value_or(var99) == 99); - - - EXPECT_TRUE(o3.value_or([&]()->int&{return var3;}()) == 42); - EXPECT_TRUE(o4.value_or([&]()->int&{return var3;}()) == 54); - - std::string meow{"meow"}; - std::string bark{"bark"}; - beman::optional::optional so1; - beman::optional::optional so2{meow}; - auto t1 = so1.value_or(bark); - auto t2 = so2.value_or(bark); - // auto t3 = so1.value_or("bark"); - // auto t4 = so2.value_or("bark"); - // std::tuple t("meow"); - - auto success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - - struct int_box {int i_;}; - int_box i1{3}; - beman::optional::optional ob1 = i1; - beman::optional::optional ob2; - const beman::optional::optional ob3 = i1; - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - -} - -TEST(OptionalRefTest, MoveCheck) { - int x = 0; - int& y = std::move(beman::optional::optional(x)).value(); - EXPECT_EQ(&y, &x); - - int& z = *std::move(beman::optional::optional(x)); - EXPECT_EQ(&z, &x); - -} - -TEST(OptionalRefTest, SwapValue) { - int var = 42; - int twelve = 12; - beman::optional::optional o1 = var; - beman::optional::optional o2 = twelve; - o1.swap(o2); - EXPECT_EQ(o1.value(), 12); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalRefTest, SwapWNull) { - int var = 42; - - beman::optional::optional o1 = var; - beman::optional::optional o2 = beman::optional::nullopt; - o1.swap(o2); - EXPECT_TRUE(!o1.has_value()); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalRefTest, SwapNullIntializedWithValue) { - int var = 42; - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = var; - o1.swap(o2); - EXPECT_EQ(o1.value(), 42); - EXPECT_TRUE(!o2.has_value()); -} diff --git a/src/beman/optional/tests/optional_ref_monadic.t.cpp b/src/beman/optional/tests/optional_ref_monadic.t.cpp deleted file mode 100644 index 9d9f9fda..00000000 --- a/src/beman/optional/tests/optional_ref_monadic.t.cpp +++ /dev/null @@ -1,318 +0,0 @@ -#include - -#include - -namespace { -inline constexpr int constexpr_fortytwo = 42; -constexpr int get_int(int) { return constexpr_fortytwo; } -constexpr beman::optional::optional get_opt_int(int) { return constexpr_fortytwo; } -} // namespace - -TEST(OptionalRefMonadicTest, Transform) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int forty = 40; - beman::optional::optional o2 = forty; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o3 = fortytwo; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // // ensure that lhs is forwarded - // forty = 40; - // beman::optional::optional o4 = forty; - // auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - forty = 40; - const beman::optional::optional o5 = forty; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - fortytwo = 42; - beman::optional::optional o8 = fortytwo; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = fortytwo; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = fortytwo; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = fortytwo; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - - // callable which returns a reference - beman::optional::optional o38 = fortytwo; - auto o38r = o38.transform([](int& i) -> const int& { return i; }); - EXPECT_TRUE(o38r); - EXPECT_TRUE(*o38r == 42); -} - -TEST(OptionalRefMonadicTest, TransformConstexpr) { - - // test each overload in turn - constexpr beman::optional::optional o16 = constexpr_fortytwo; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = constexpr_fortytwo; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); -} - -TEST(OptionalRefMonadicTest, Transform2) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int forty = 40; - beman::optional::optional o2 = forty; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o3 = fortytwo; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // // ensure that lhs is forwarded - // int forty = 40; - // beman::optional::optional o4 = forty; - // auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - forty = 40; - const beman::optional::optional o5 = forty; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - fortytwo = 42; - beman::optional::optional o8 = fortytwo; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = fortytwo; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = fortytwo; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = fortytwo; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); -} - -TEST(OptionalRefMonadicTest, TransformConstxpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = constexpr_fortytwo; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = constexpr_fortytwo; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); -} - -TEST(OptionalRefMonadicTest, and_then) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int twelve = 12; - beman::optional::optional o2 = twelve; - auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42.f); - - // lhs is empty, rhs returns empty - beman::optional::optional o3; - auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o3r); - - // rhs returns empty - beman::optional::optional o4 = twelve; - auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o4r); - - struct rval_call_and_then { - beman::optional::optional operator()(int) && { return beman::optional::optional(42.0); }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o5 = fortytwo; - auto o5r = o5.and_then(rval_call_and_then{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // // ensure that lhs is forwarded - // beman::optional::optional o6 = fortytwo; - // auto o6r = - // std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o6r.value() == 42); - - // ensure that function object is const-propagated - const beman::optional::optional o7 = fortytwo; - auto o7r = o7.and_then([](const int& i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o7r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = fortytwo; - auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o9 = fortytwo; - auto o9r = std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o9r == 42); - - const beman::optional::optional o10 = fortytwo; - auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o10r == 42); - - const beman::optional::optional o11 = fortytwo; - auto o11r = std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o11r == 42); - - beman::optional::optional o16 = beman::optional::nullopt; - auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o16r); - - beman::optional::optional o17 = beman::optional::nullopt; - auto o17r = std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o17r); - - const beman::optional::optional o18 = beman::optional::nullopt; - auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o18r); - - const beman::optional::optional o19 = beman::optional::nullopt; - auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o19r); - - int i = 3; - beman::optional::optional o20{i}; - std::move(o20).and_then([](int& r) { return beman::optional::optional{++r}; }); - EXPECT_TRUE(o20); - EXPECT_TRUE(i == 4); -} - -TEST(OptionalRefMonadicTest, Constexpr_and_then) { - constexpr beman::optional::optional o10 = constexpr_fortytwo; - constexpr auto o10r = o10.and_then(get_opt_int); - EXPECT_TRUE(*o10r == 42); - - constexpr beman::optional::optional o11 = constexpr_fortytwo; - constexpr auto o11r = std::move(o11).and_then(get_opt_int); - EXPECT_TRUE(*o11r == 42); - - constexpr beman::optional::optional o18 = beman::optional::nullopt; - constexpr auto o18r = o18.and_then(get_opt_int); - EXPECT_TRUE(!o18r); - - constexpr beman::optional::optional o19 = beman::optional::nullopt; - constexpr auto o19r = std::move(o19).and_then(get_opt_int); - EXPECT_TRUE(!o19r); -} - -TEST(OptionalRefMonadicTest, or_else) { - int fortytwo = 42; - int thirteen = 13; - beman::optional::optional o1 = fortytwo; - EXPECT_TRUE(*(o1.or_else([&] { return beman::optional::optional(thirteen); })) == 42); - - beman::optional::optional o2; - EXPECT_EQ(*(o2.or_else([&] { return beman::optional::optional(thirteen); })), 13); -} diff --git a/src/Beman/CMakeLists.txt b/src/tmp/CMakeLists.txt similarity index 100% rename from src/Beman/CMakeLists.txt rename to src/tmp/CMakeLists.txt diff --git a/src/Beman/optional/CMakeLists.txt b/src/tmp/optional/CMakeLists.txt similarity index 100% rename from src/Beman/optional/CMakeLists.txt rename to src/tmp/optional/CMakeLists.txt diff --git a/src/Beman/optional/optional.cpp b/src/tmp/optional/optional.cpp similarity index 100% rename from src/Beman/optional/optional.cpp rename to src/tmp/optional/optional.cpp diff --git a/src/Beman/optional/optional.t.cpp b/src/tmp/optional/optional.t.cpp similarity index 100% rename from src/Beman/optional/optional.t.cpp rename to src/tmp/optional/optional.t.cpp diff --git a/src/Beman/optional/optional_monadic.t.cpp b/src/tmp/optional/optional_monadic.t.cpp similarity index 100% rename from src/Beman/optional/optional_monadic.t.cpp rename to src/tmp/optional/optional_monadic.t.cpp diff --git a/src/Beman/optional/optional_ref.t.cpp b/src/tmp/optional/optional_ref.t.cpp similarity index 100% rename from src/Beman/optional/optional_ref.t.cpp rename to src/tmp/optional/optional_ref.t.cpp diff --git a/src/Beman/optional/optional_ref_monadic.t.cpp b/src/tmp/optional/optional_ref_monadic.t.cpp similarity index 100% rename from src/Beman/optional/optional_ref_monadic.t.cpp rename to src/tmp/optional/optional_ref_monadic.t.cpp diff --git a/src/Beman/optional/tests/optional.t.cpp b/src/tmp/optional/tests/optional.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional.t.cpp rename to src/tmp/optional/tests/optional.t.cpp diff --git a/src/Beman/optional/tests/optional_monadic.t.cpp b/src/tmp/optional/tests/optional_monadic.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional_monadic.t.cpp rename to src/tmp/optional/tests/optional_monadic.t.cpp diff --git a/src/beman/optional/tests/optional_range_support.t.cpp b/src/tmp/optional/tests/optional_range_support.t.cpp similarity index 100% rename from src/beman/optional/tests/optional_range_support.t.cpp rename to src/tmp/optional/tests/optional_range_support.t.cpp diff --git a/src/Beman/optional/tests/optional_ref.t.cpp b/src/tmp/optional/tests/optional_ref.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional_ref.t.cpp rename to src/tmp/optional/tests/optional_ref.t.cpp diff --git a/src/Beman/optional/tests/optional_ref_monadic.t.cpp b/src/tmp/optional/tests/optional_ref_monadic.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional_ref_monadic.t.cpp rename to src/tmp/optional/tests/optional_ref_monadic.t.cpp From 909f0bcaf405dd8d508ed641b04a62e39ee9a453 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 09:19:25 +0300 Subject: [PATCH 08/20] rename src/Beman --- src/{tmp => Beman}/CMakeLists.txt | 0 src/{tmp => Beman}/optional/CMakeLists.txt | 0 src/{tmp => Beman}/optional/optional.cpp | 0 src/{tmp => Beman}/optional/optional.t.cpp | 0 src/{tmp => Beman}/optional/optional_monadic.t.cpp | 0 src/{tmp => Beman}/optional/optional_ref.t.cpp | 0 src/{tmp => Beman}/optional/optional_ref_monadic.t.cpp | 0 src/{tmp => Beman}/optional/tests/optional.t.cpp | 0 src/{tmp => Beman}/optional/tests/optional_monadic.t.cpp | 0 src/{tmp => Beman}/optional/tests/optional_range_support.t.cpp | 0 src/{tmp => Beman}/optional/tests/optional_ref.t.cpp | 0 src/{tmp => Beman}/optional/tests/optional_ref_monadic.t.cpp | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename src/{tmp => Beman}/CMakeLists.txt (100%) rename src/{tmp => Beman}/optional/CMakeLists.txt (100%) rename src/{tmp => Beman}/optional/optional.cpp (100%) rename src/{tmp => Beman}/optional/optional.t.cpp (100%) rename src/{tmp => Beman}/optional/optional_monadic.t.cpp (100%) rename src/{tmp => Beman}/optional/optional_ref.t.cpp (100%) rename src/{tmp => Beman}/optional/optional_ref_monadic.t.cpp (100%) rename src/{tmp => Beman}/optional/tests/optional.t.cpp (100%) rename src/{tmp => Beman}/optional/tests/optional_monadic.t.cpp (100%) rename src/{tmp => Beman}/optional/tests/optional_range_support.t.cpp (100%) rename src/{tmp => Beman}/optional/tests/optional_ref.t.cpp (100%) rename src/{tmp => Beman}/optional/tests/optional_ref_monadic.t.cpp (100%) diff --git a/src/tmp/CMakeLists.txt b/src/Beman/CMakeLists.txt similarity index 100% rename from src/tmp/CMakeLists.txt rename to src/Beman/CMakeLists.txt diff --git a/src/tmp/optional/CMakeLists.txt b/src/Beman/optional/CMakeLists.txt similarity index 100% rename from src/tmp/optional/CMakeLists.txt rename to src/Beman/optional/CMakeLists.txt diff --git a/src/tmp/optional/optional.cpp b/src/Beman/optional/optional.cpp similarity index 100% rename from src/tmp/optional/optional.cpp rename to src/Beman/optional/optional.cpp diff --git a/src/tmp/optional/optional.t.cpp b/src/Beman/optional/optional.t.cpp similarity index 100% rename from src/tmp/optional/optional.t.cpp rename to src/Beman/optional/optional.t.cpp diff --git a/src/tmp/optional/optional_monadic.t.cpp b/src/Beman/optional/optional_monadic.t.cpp similarity index 100% rename from src/tmp/optional/optional_monadic.t.cpp rename to src/Beman/optional/optional_monadic.t.cpp diff --git a/src/tmp/optional/optional_ref.t.cpp b/src/Beman/optional/optional_ref.t.cpp similarity index 100% rename from src/tmp/optional/optional_ref.t.cpp rename to src/Beman/optional/optional_ref.t.cpp diff --git a/src/tmp/optional/optional_ref_monadic.t.cpp b/src/Beman/optional/optional_ref_monadic.t.cpp similarity index 100% rename from src/tmp/optional/optional_ref_monadic.t.cpp rename to src/Beman/optional/optional_ref_monadic.t.cpp diff --git a/src/tmp/optional/tests/optional.t.cpp b/src/Beman/optional/tests/optional.t.cpp similarity index 100% rename from src/tmp/optional/tests/optional.t.cpp rename to src/Beman/optional/tests/optional.t.cpp diff --git a/src/tmp/optional/tests/optional_monadic.t.cpp b/src/Beman/optional/tests/optional_monadic.t.cpp similarity index 100% rename from src/tmp/optional/tests/optional_monadic.t.cpp rename to src/Beman/optional/tests/optional_monadic.t.cpp diff --git a/src/tmp/optional/tests/optional_range_support.t.cpp b/src/Beman/optional/tests/optional_range_support.t.cpp similarity index 100% rename from src/tmp/optional/tests/optional_range_support.t.cpp rename to src/Beman/optional/tests/optional_range_support.t.cpp diff --git a/src/tmp/optional/tests/optional_ref.t.cpp b/src/Beman/optional/tests/optional_ref.t.cpp similarity index 100% rename from src/tmp/optional/tests/optional_ref.t.cpp rename to src/Beman/optional/tests/optional_ref.t.cpp diff --git a/src/tmp/optional/tests/optional_ref_monadic.t.cpp b/src/Beman/optional/tests/optional_ref_monadic.t.cpp similarity index 100% rename from src/tmp/optional/tests/optional_ref_monadic.t.cpp rename to src/Beman/optional/tests/optional_ref_monadic.t.cpp From 515b2d89391b16be49d0f9e4b36fc08b7266ef2b Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 09:24:41 +0300 Subject: [PATCH 09/20] rename src/Beman --- src/Beman/optional/optional.t.cpp | 1278 ----------------------------- 1 file changed, 1278 deletions(-) delete mode 100644 src/Beman/optional/optional.t.cpp diff --git a/src/Beman/optional/optional.t.cpp b/src/Beman/optional/optional.t.cpp deleted file mode 100644 index 9da8715d..00000000 --- a/src/Beman/optional/optional.t.cpp +++ /dev/null @@ -1,1278 +0,0 @@ -#include - -#include // test 2nd include OK - -#include -#include -#include - -#include - -TEST(OptionalTest, TestGTest) { ASSERT_EQ(1, 1); } - -namespace { -struct empty {}; -struct no_default { - no_default() = delete; - no_default(const no_default&) = default; - no_default(no_default&&) = default; - no_default& operator=(const no_default&) = default; - no_default& operator=(no_default&&) = default; - no_default(empty){}; -}; - -struct base { - int i_; - base() : i_(0) {} - base(int i) : i_(i) {} -}; - -struct derived : public base { - int j_; - derived() : base(0), j_(0) {} - derived(int i, int j) : base(i), j_(j) {} -}; -} // namespace - -TEST(OptionalTest, Constructors) { - beman::optional::optional i1; - beman::optional::optional i2{beman::optional::nullopt}; - - int i = 0; - beman::optional::optional i3 = i; - (void)i3; - - beman::optional::optional e1; - beman::optional::optional e2{beman::optional::nullopt}; - - empty e{}; - beman::optional::optional e3 = e; - (void)e3; -} - - -TEST(OptionalTest, Constructors2) { - beman::optional::optional o1; - EXPECT_TRUE(!o1); - - beman::optional::optional o2 = beman::optional::nullopt; - EXPECT_TRUE(!o2); - - beman::optional::optional o3 = 42; - EXPECT_TRUE(*o3 == 42); - - beman::optional::optional o4 = o3; - EXPECT_TRUE(*o4 == 42); - - beman::optional::optional o5 = o1; - EXPECT_TRUE(!o5); - - beman::optional::optional o6 = std::move(o3); - EXPECT_TRUE(*o6 == 42); - - beman::optional::optional o7 = 42; - EXPECT_TRUE(*o7 == 42); - - beman::optional::optional o8 = o7; - EXPECT_TRUE(*o8 == 42); - - beman::optional::optional o9 = std::move(o7); - EXPECT_TRUE(*o9 == 42); - - { - beman::optional::optional o; - EXPECT_TRUE(!o); - - beman::optional::optional oo = o; - EXPECT_TRUE(!oo); - } - - { - auto i = 42; - beman::optional::optional o = i; - EXPECT_TRUE(o); - EXPECT_TRUE(*o == 42); - - beman::optional::optional oo = o; - EXPECT_TRUE(oo); - EXPECT_TRUE(*oo == 42); - } - - std::vector v; - v.emplace_back(); - beman::optional::optional> ov = std::move(v); - EXPECT_TRUE(ov->size() == 1); -} - -TEST(OptionalTest, Constructors3) { - beman::optional::optional ie; - beman::optional::optional i4 = ie; - EXPECT_FALSE(i4); - - base b{1}; - derived d(1, 2); - beman::optional::optional b1{b}; - beman::optional::optional b2{d}; - - beman::optional::optional d2{d}; - beman::optional::optional b3 = d2; - beman::optional::optional b4{d2}; -} - -namespace { -class NoDefault { - int v_; - - public: - NoDefault(int v) : v_(v) {} -}; -} // namespace - -TEST(OptionalTest, NonDefaultConstruct) { - NoDefault i = 7; - beman::optional::optional v1{}; - beman::optional::optional v2{i}; -} - -TEST(OptionalTest, AssignmentValue) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = 12; - beman::optional::optional o3; - - o1 = o1; - EXPECT_TRUE(*o1 == 42); - - o1 = o2; - EXPECT_TRUE(*o1 == 12); - - o1 = o3; - EXPECT_TRUE(!o1); - - o1 = 42; - EXPECT_TRUE(*o1 == 42); - - o1 = beman::optional::nullopt; - EXPECT_TRUE(!o1); - - o1 = std::move(o2); - EXPECT_TRUE(*o1 == 12); - - beman::optional::optional o4 = 42; - - o1 = o4; - EXPECT_TRUE(*o1 == 42); - - o1 = std::move(o4); - EXPECT_TRUE(*o1 == 42); -} - -TEST(OptionalTest, Triviality) { - EXPECT_TRUE(std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE( - std::is_trivially_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE( - std::is_trivially_destructible>::value); - } - - { - struct T { - T(const T&) {} - T(T&&){}; - T& operator=(const T&) { return *this; } - T& operator=(T&&) { return *this; }; - ~T() {} - }; - EXPECT_TRUE(!std::is_trivially_copy_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_copy_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_move_constructible< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_move_assignable< - beman::optional::optional>::value); - EXPECT_TRUE(!std::is_trivially_destructible< - beman::optional::optional>::value); - } -} - -TEST(OptionalTest, Deletion) { - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE( - std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE( - std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = delete; - T& operator=(const T&) = delete; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE( - !std::is_copy_constructible>::value); - EXPECT_TRUE( - !std::is_copy_assignable>::value); - EXPECT_TRUE( - !std::is_move_constructible>::value); - EXPECT_TRUE( - !std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = default; - T& operator=(const T&) = delete; - T& operator=(T&&) = default; - }; - EXPECT_TRUE( - !std::is_copy_constructible>::value); - EXPECT_TRUE( - !std::is_copy_assignable>::value); - EXPECT_TRUE( - std::is_move_constructible>::value); - EXPECT_TRUE( - std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = default; - T(T&&) = delete; - T& operator=(const T&) = default; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE( - std::is_copy_constructible>::value); - EXPECT_TRUE( - std::is_copy_assignable>::value); - } -} - -struct takes_init_and_variadic { - std::vector v; - std::tuple t; - template - takes_init_and_variadic(std::initializer_list l, Args&&... args) - : v(l), t(std::forward(args)...) {} -}; - -TEST(OptionalTest, InPlace) { - beman::optional::optional o1{beman::optional::in_place}; - beman::optional::optional o2(beman::optional::in_place); - EXPECT_TRUE(o1); - EXPECT_TRUE(o1 == 0); - EXPECT_TRUE(o2); - EXPECT_TRUE(o2 == 0); - - beman::optional::optional o3(beman::optional::in_place, 42); - EXPECT_TRUE(o3 == 42); - - beman::optional::optional> o4( - beman::optional::in_place, 0, 1); - EXPECT_TRUE(o4); - EXPECT_TRUE(std::get<0>(*o4) == 0); - EXPECT_TRUE(std::get<1>(*o4) == 1); - - beman::optional::optional> o5(beman::optional::in_place, - {0, 1}); - EXPECT_TRUE(o5); - EXPECT_TRUE((*o5)[0] == 0); - EXPECT_TRUE((*o5)[1] == 1); - - beman::optional::optional o6( - beman::optional::in_place, {0, 1}, 2, 3); - EXPECT_TRUE(o6->v[0] == 0); - EXPECT_TRUE(o6->v[1] == 1); - EXPECT_TRUE(std::get<0>(o6->t) == 2); - EXPECT_TRUE(std::get<1>(o6->t) == 3); -} - -TEST(OptionalTest, MakeOptional) { - auto o1 = beman::optional::make_optional(42); - auto o2 = beman::optional::optional(42); - - constexpr bool is_same = - std::is_same>::value; - EXPECT_TRUE(is_same); - EXPECT_TRUE(o1 == o2); - - auto o3 = beman::optional::make_optional>( - 0, 1, 2, 3); - EXPECT_TRUE(std::get<0>(*o3) == 0); - EXPECT_TRUE(std::get<1>(*o3) == 1); - EXPECT_TRUE(std::get<2>(*o3) == 2); - EXPECT_TRUE(std::get<3>(*o3) == 3); - - auto o4 = beman::optional::make_optional>({0, 1, 2, 3}); - EXPECT_TRUE(o4.value()[0] == 0); - EXPECT_TRUE(o4.value()[1] == 1); - EXPECT_TRUE(o4.value()[2] == 2); - EXPECT_TRUE(o4.value()[3] == 3); - - auto o5 = - beman::optional::make_optional({0, 1}, 2, 3); - EXPECT_TRUE(o5->v[0] == 0); - EXPECT_TRUE(o5->v[1] == 1); - EXPECT_TRUE(std::get<0>(o5->t) == 2); - EXPECT_TRUE(std::get<1>(o5->t) == 3); - - auto i = 42; - auto o6 = beman::optional::make_optional(i); - static_assert(std::is_same>::value); - - EXPECT_TRUE( - (std::is_same>::value)); - EXPECT_TRUE(o6); - EXPECT_TRUE(*o6 == 42); -} - -TEST(OptionalTest, Nullopt) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2{beman::optional::nullopt}; - beman::optional::optional o3(beman::optional::nullopt); - beman::optional::optional o4 = {beman::optional::nullopt}; - - EXPECT_TRUE(!o1); - EXPECT_TRUE(!o2); - EXPECT_TRUE(!o3); - EXPECT_TRUE(!o4); - - EXPECT_TRUE( - !std::is_default_constructible::value); -} - -struct move_detector { - move_detector() = default; - move_detector(move_detector&& rhs) { rhs.been_moved = true; } - bool been_moved = false; -}; - -TEST(OptionalTest, Observers) { - beman::optional::optional o1 = 42; - beman::optional::optional o2; - const beman::optional::optional o3 = 42; - - EXPECT_TRUE(*o1 == 42); - EXPECT_TRUE(*o1 == o1.value()); - EXPECT_TRUE(o2.value_or(42) == 42); - EXPECT_TRUE(o3.value() == 42); - auto success = std::is_same::value; - EXPECT_TRUE(success); - success = std::is_same::value; - EXPECT_TRUE(success); - success = std::is_same::value; - EXPECT_TRUE(success); - - beman::optional::optional o4{beman::optional::in_place}; - move_detector o5 = std::move(o4).value(); - EXPECT_TRUE(o4->been_moved); - EXPECT_TRUE(!o5.been_moved); -} - -TEST(OptionalTest, RelationalOps) { - beman::optional::optional o1{4}; - beman::optional::optional o2{42}; - beman::optional::optional o3{}; - - // SECTION("self simple") - { - EXPECT_TRUE(!(o1 == o2)); - EXPECT_TRUE(o1 == o1); - EXPECT_TRUE(o1 != o2); - EXPECT_TRUE(!(o1 != o1)); - EXPECT_TRUE(o1 < o2); - EXPECT_TRUE(!(o1 < o1)); - EXPECT_TRUE(!(o1 > o2)); - EXPECT_TRUE(!(o1 > o1)); - EXPECT_TRUE(o1 <= o2); - EXPECT_TRUE(o1 <= o1); - EXPECT_TRUE(!(o1 >= o2)); - EXPECT_TRUE(o1 >= o1); - } - // SECTION("nullopt simple") - { - EXPECT_TRUE(!(o1 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o1)); - EXPECT_TRUE(o1 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o1); - EXPECT_TRUE(!(o1 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o1); - EXPECT_TRUE(o1 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o1)); - EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o1); - EXPECT_TRUE(o1 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o1)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - // SECTION("with T simple") - { - EXPECT_TRUE(!(o1 == 1)); - EXPECT_TRUE(!(1 == o1)); - EXPECT_TRUE(o1 != 1); - EXPECT_TRUE(1 != o1); - EXPECT_TRUE(!(o1 < 1)); - EXPECT_TRUE(1 < o1); - EXPECT_TRUE(o1 > 1); - EXPECT_TRUE(!(1 > o1)); - EXPECT_TRUE(!(o1 <= 1)); - EXPECT_TRUE(1 <= o1); - EXPECT_TRUE(o1 >= 1); - EXPECT_TRUE(!(1 >= o1)); - - EXPECT_TRUE(o1 == 4); - EXPECT_TRUE(4 == o1); - EXPECT_TRUE(!(o1 != 4)); - EXPECT_TRUE(!(4 != o1)); - EXPECT_TRUE(!(o1 < 4)); - EXPECT_TRUE(!(4 < o1)); - EXPECT_TRUE(!(o1 > 4)); - EXPECT_TRUE(!(4 > o1)); - EXPECT_TRUE(o1 <= 4); - EXPECT_TRUE(4 <= o1); - EXPECT_TRUE(o1 >= 4); - EXPECT_TRUE(4 >= o1); - } - beman::optional::optional o4{"hello"}; - beman::optional::optional o5{"xyz"}; - - // SECTION("self complex") - { - EXPECT_TRUE(!(o4 == o5)); - EXPECT_TRUE(o4 == o4); - EXPECT_TRUE(o4 != o5); - EXPECT_TRUE(!(o4 != o4)); - EXPECT_TRUE(o4 < o5); - EXPECT_TRUE(!(o4 < o4)); - EXPECT_TRUE(!(o4 > o5)); - EXPECT_TRUE(!(o4 > o4)); - EXPECT_TRUE(o4 <= o5); - EXPECT_TRUE(o4 <= o4); - EXPECT_TRUE(!(o4 >= o5)); - EXPECT_TRUE(o4 >= o4); - } - // SECTION("nullopt complex") - { - EXPECT_TRUE(!(o4 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o4)); - EXPECT_TRUE(o4 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o4); - EXPECT_TRUE(!(o4 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o4); - EXPECT_TRUE(o4 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o4)); - EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o4); - EXPECT_TRUE(o4 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o4)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - - // SECTION("with T complex") - { - EXPECT_TRUE(!(o4 == "a")); - EXPECT_TRUE(!("a" == o4)); - EXPECT_TRUE(o4 != "a"); - EXPECT_TRUE("a" != o4); - EXPECT_TRUE(!(o4 < "a")); - EXPECT_TRUE("a" < o4); - EXPECT_TRUE(o4 > "a"); - EXPECT_TRUE(!("a" > o4)); - EXPECT_TRUE(!(o4 <= "a")); - EXPECT_TRUE("a" <= o4); - EXPECT_TRUE(o4 >= "a"); - EXPECT_TRUE(!("a" >= o4)); - - EXPECT_TRUE(o4 == "hello"); - EXPECT_TRUE("hello" == o4); - EXPECT_TRUE(!(o4 != "hello")); - EXPECT_TRUE(!("hello" != o4)); - EXPECT_TRUE(!(o4 < "hello")); - EXPECT_TRUE(!("hello" < o4)); - EXPECT_TRUE(!(o4 > "hello")); - EXPECT_TRUE(!("hello" > o4)); - EXPECT_TRUE(o4 <= "hello"); - EXPECT_TRUE("hello" <= o4); - EXPECT_TRUE(o4 >= "hello"); - EXPECT_TRUE("hello" >= o4); - } -} - -TEST(OptionalTest, SwapValue) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = 12; - o1.swap(o2); - EXPECT_EQ(o1.value(), 12); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalTest, SwapWNull) { - beman::optional::optional o1 = 42; - beman::optional::optional o2 = beman::optional::nullopt; - o1.swap(o2); - EXPECT_TRUE(!o1.has_value()); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalTest, SwapNullIntializedWithValue) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = 42; - o1.swap(o2); - EXPECT_EQ(o1.value(), 42); - EXPECT_TRUE(!o2.has_value()); -} - -TEST(OptionalTest, Emplace) { - beman::optional::optional< - std::pair, std::pair>> - i; - i.emplace(std::piecewise_construct, - std::make_tuple(0, 2), - std::make_tuple(3, 4)); - EXPECT_TRUE(i->first.first == 0); - EXPECT_TRUE(i->first.second == 2); - EXPECT_TRUE(i->second.first == 3); - EXPECT_TRUE(i->second.second == 4); -} - -struct A { - A() { throw std::exception(); } -}; - -TEST(OptionalTest, EmplaceWithExceptionThrown) { - beman::optional::optional a; - EXPECT_ANY_THROW(a.emplace()); -} - -TEST(OptionalTest, RangeTest) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = 42; - EXPECT_EQ(*o2, 42); - for(auto k : o1) { - (void)k; - EXPECT_TRUE(false); - } - for(auto k : o2) { - EXPECT_EQ(k, 42); - } -} - -TEST(ViewMaybeTest, Constructors) { - std::ranges::single_view> s; - std::ranges::single_view> s2{s}; - std::ranges::single_view> s3{std::optional{}}; - - beman::optional::optional> n; - beman::optional::optional> n2{n}; - beman::optional::optional> n3{std::optional{}}; -} - -TEST(ViewMaybeTest, ConceptCheck) { - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(!std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - static_assert(std::ranges::sized_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); -} - -TEST(ViewMaybeTest, ConceptCheckRef) { - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper&; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); -} - -TEST(ViewMaybeTest, BreathingTest) { - beman::optional::optional m; - // ASSERT_TRUE(m.empty()); - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m.data() == nullptr); - - beman::optional::optional m1{1}; - // ASSERT_TRUE(!m1.empty()); - // ASSERT_TRUE(m1.size() == 1); - // ASSERT_TRUE(m1.data() != nullptr); - // ASSERT_TRUE(*(m1.data()) == 1); - - m = m1; - ASSERT_EQ(*std::begin(m), 1); - - m = {}; - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m1.size() == 1); - - beman::optional::optional d0{0}; - // ASSERT_TRUE(!d0.empty()); - - beman::optional::optional d1{1}; - // ASSERT_TRUE(!d1.empty()); - - d0 = d1; - ASSERT_EQ(*std::begin(d0), 1.0); -} - -TEST(ViewMaybeTest, BreathingTestRef) { - beman::optional::optional m; - // ASSERT_TRUE(m.empty()); - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m.data() == nullptr); - - int one = 1; - beman::optional::optional m1{one}; - // ASSERT_TRUE(!m1.empty()); - // ASSERT_TRUE(m1.size() == 1); - // ASSERT_TRUE(m1.data() != nullptr); - // ASSERT_TRUE(*(m1.data()) == 1); - - m = m1; - ASSERT_EQ(*std::begin(m), 1); - - // m = {}; - // ASSERT_TRUE(m.size() == 0); - // ASSERT_TRUE(m1.size() == 1); - - double zero = 0.0; - beman::optional::optional d0{zero}; - // ASSERT_TRUE(!d0.empty()); - - double one_d = 1.0; - beman::optional::optional d1{one_d}; - // ASSERT_TRUE(!d1.empty()); - - d0 = d1; - ASSERT_EQ(*std::begin(d0), 1.0); -} - -TEST(ViewMaybe, CompTest) { - beman::optional::optional m; - beman::optional::optional m0{0}; - beman::optional::optional m1{1}; - beman::optional::optional m1a{1}; - - ASSERT_EQ(m, m); - ASSERT_EQ(m0, m0); - ASSERT_EQ(m1, m1); - ASSERT_EQ(m1a, m1a); - ASSERT_EQ(m1, m1a); - - ASSERT_NE(m, m0); - ASSERT_NE(m0, m1); - - ASSERT_TRUE(m < m0); - ASSERT_TRUE(m0 < m1); - ASSERT_TRUE(m1 <= m1a); -} - -TEST(ViewMaybe, CompTestRef) { - beman::optional::optional m; - int zero = 0; - int one = 1; - int one_a = 1; - beman::optional::optional m0{zero}; - beman::optional::optional m1{one}; - beman::optional::optional m1a{one_a}; - - ASSERT_EQ(m, m); - ASSERT_EQ(m0, m0); - ASSERT_EQ(m1, m1); - ASSERT_EQ(m1a, m1a); - ASSERT_EQ(m1, m1a); - - ASSERT_NE(m, m0); - ASSERT_NE(m0, m1); - - ASSERT_TRUE(m < m0); - ASSERT_TRUE(m0 > m); - ASSERT_TRUE(m0 < m1); - ASSERT_TRUE(m1a <= m1); -} - -// "and_then" creates a new view by applying a -// transformation to each element in an input -// range, and flattening the resulting range of -// ranges. A.k.a. bind -// (This uses one syntax for constrained lambdas -// in C++20.) -inline constexpr auto and_then = [](auto&& r, auto fun) { - return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | - std::ranges::views::join; -}; - -// "yield_if" takes a bool and a value and -// returns a view of zero or one elements. -inline constexpr auto yield_if = [](bool b, T x) { - return b ? - beman::optional::optional{move(x)} : - beman::optional::nullopt; -}; - - -TEST(ViewMaybeTest, PythTripleTest) { - using std::ranges::views::iota; - auto triples = and_then(iota(1), [](int z) { - return and_then(iota(1, z + 1), [=](int x) { - return and_then(iota(x, z + 1), [=](int y) { - return yield_if(x * x + y * y == z * z, - std::make_tuple(x, y, z)); - }); - }); - }); - - ASSERT_EQ(*std::ranges::begin(triples), std::make_tuple(3, 4, 5)); -} - -using namespace beman; - -TEST(ViewMaybeTest, ValueBase) { - int i = 7; - beman::optional::optional v1{}; - // ASSERT_TRUE(v1.size() == 0); - - beman::optional::optional v2{i}; - // ASSERT_TRUE(v2.size() == 1); - for (auto i : v1) - ASSERT_TRUE(i != i); // tautology so i is used and not warned - - - for (auto i : v2) - ASSERT_EQ(i, 7); - -// ASSERT_EQ(v2[0], 7); // no match for operator[] -// auto x = v2[1000]; - - // int s = 4; - // for (auto&& i : views::maybe(s)) { - // ASSERT_EQ(i, 4); - // i = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 4); -} - -TEST(ViewMaybeTest, RefWrapper) { - int i = 7; - - beman::optional::optional v2{std::ref(i)}; - - for (auto i : v2) - ASSERT_EQ(i, 7); - - // int s = 4; - // for (auto&& i : views::maybe(std::ref(s))) { - // ASSERT_EQ(i, 4); - // i.get() = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 9); -} - - -TEST(ViewMaybeTest, ValueNonDefaultConstruct) { - NoDefault i = 7; - beman::optional::optional v1{}; - beman::optional::optional v2{i}; -} - -TEST(ViewMaybeTest, RefBase) { - int i = 7; - beman::optional::optional v1{}; - // ASSERT_TRUE(v1.size() == 0); - - beman::optional::optional v2{i}; - // ASSERT_TRUE(v2.size() == 1); - for (auto i : v1) - ASSERT_TRUE(i != i); // tautology so i is used and not warned - - for (auto i : v2) { - ASSERT_EQ(i, 7); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(i, 7); - - for (auto&& i : v2) { - ASSERT_EQ(i, 7); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(i, 9); - - int s = 4; - // for (auto&& i : views::maybe(s)) { - // ASSERT_EQ(i, 4); - // i = 9; - // ASSERT_EQ(i, 9); - // } - // ASSERT_EQ(s, 4); - - for (auto&& i : beman::optional::optional(s)) { - ASSERT_EQ(i, 4); - i = 9; - ASSERT_EQ(i, 9); - } - ASSERT_EQ(s, 9); -} - -// TEST(ViewMaybeTest, MonadicAndThen) { -// beman::optional::optional mv{40}; -// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); -// ASSERT_TRUE(r2.empty()); -// ASSERT_TRUE(r2.size() == 0); -// ASSERT_TRUE(r2.data() == nullptr); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).and_then([](int&& i) { -// int k = i; -// i = 0; -// return beman::optional::optional{k + 2}; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); - -// const beman::optional::optional cmv{40}; -// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicTransform) { -// beman::optional::optional mv{40}; -// auto r = mv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.transform([](int& i) { -// i += 2; -// return i; -// }); -// ASSERT_TRUE(!r2.empty()); -// ASSERT_TRUE(r2.size() == 1); -// ASSERT_TRUE(r2.data() != nullptr); -// ASSERT_TRUE(*(r2.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 42); - -// beman::optional::optional empty{}; - -// auto r3 = empty.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.transform([](double d) { return d + 2; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 44.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 44); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 42); - -// auto r6 = std::move(mv).transform([](int&& i) { -// int k = i; -// i = 0; -// return k + 2; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 44); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); - -// const beman::optional::optional cmv{40}; -// auto r7 = cmv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicOrElse) { -// beman::optional::optional o1(42); -// auto r = o1.or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r.data()) == 42); - -// beman::optional::optional o2; -// ASSERT_TRUE(*(o2.or_else([] { return beman::optional::optional(13); })).data() == -// 13); - -// auto r2 = std::move(o1).or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r2.data()) == 42); - -// auto r3 = std::move(o2).or_else([] { return beman::optional::optional(13); }); -// ASSERT_TRUE(*(r3.data()) == 13); -// } - -// TEST(ViewMaybeTest, MonadicAndThenRef) { -// int forty{40}; -// beman::optional::optional mv{forty}; -// auto r = mv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_TRUE(*(r.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r2 = mv.and_then([](int) { return beman::optional::optional{}; }); -// ASSERT_TRUE(r2.empty()); -// ASSERT_TRUE(r2.size() == 0); -// ASSERT_TRUE(r2.data() == nullptr); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.and_then([](double d) { return beman::optional::optional{d + 2}; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).and_then([](int&& i) { -// int k = i; -// i = 0; -// return beman::optional::optional{k + 2}; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); -// ASSERT_EQ(forty, 0); -// forty = 40; - -// const beman::optional::optional cmv{forty}; -// auto r7 = cmv.and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_EQ(*(r7.data()), 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).and_then([](int i) { return beman::optional::optional{i + 2}; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_EQ(*(r8.data()), 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); -// } - -// TEST(MaybeView, MonadicTransformRef) { -// int forty{40}; -// beman::optional::optional mv{forty}; -// auto r = mv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r.empty()); -// ASSERT_TRUE(r.size() == 1); -// ASSERT_TRUE(r.data() != nullptr); -// ASSERT_EQ(*(r.data()), 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// beman::optional::optional empty{}; - -// auto r3 = empty.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(r3.empty()); -// ASSERT_TRUE(r3.size() == 0); -// ASSERT_TRUE(r3.data() == nullptr); -// ASSERT_TRUE(empty.empty()); - -// auto r4 = mv.transform([](double d) { return d + 2; }); -// ASSERT_TRUE(!r4.empty()); -// ASSERT_TRUE(r4.size() == 1); -// ASSERT_TRUE(*(r4.data()) == 42.0); -// static_assert(std::is_same_v>); - -// auto r5 = std::move(mv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r5.empty()); -// ASSERT_TRUE(r5.size() == 1); -// ASSERT_TRUE(r5.data() != nullptr); -// ASSERT_TRUE(*(r5.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 40); - -// auto r6 = std::move(mv).transform([](int&& i) { -// int k = i; -// i = 0; -// return k + 2; -// }); -// ASSERT_TRUE(!r6.empty()); -// ASSERT_TRUE(r6.size() == 1); -// ASSERT_TRUE(r6.data() != nullptr); -// ASSERT_TRUE(*(r6.data()) == 42); -// ASSERT_TRUE(!mv.empty()); -// ASSERT_TRUE(*(mv.data()) == 0); -// ASSERT_EQ(forty, 0); -// forty = 40; - -// const beman::optional::optional cmv{forty}; -// ASSERT_EQ(*(cmv.data()), 40); -// auto r7 = cmv.transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r7.empty()); -// ASSERT_TRUE(r7.size() == 1); -// ASSERT_TRUE(r7.data() != nullptr); -// ASSERT_TRUE(*(r7.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r8 = std::move(cmv).transform([](int i) { return i + 2; }); -// ASSERT_TRUE(!r8.empty()); -// ASSERT_TRUE(r8.size() == 1); -// ASSERT_TRUE(r8.data() != nullptr); -// ASSERT_TRUE(*(r8.data()) == 42); -// ASSERT_TRUE(!cmv.empty()); -// ASSERT_TRUE(*(cmv.data()) == 40); - -// auto r9 = mv.transform([](int& i) { -// int k = i; -// i = 56; -// return k * 2; -// }); -// ASSERT_TRUE(!r9.empty()); -// ASSERT_EQ(r9.size(), 1); -// ASSERT_TRUE(r9.data() != nullptr); -// for (auto r: r9) { -// ASSERT_EQ(r, 80); -// } -// ASSERT_TRUE(!mv.empty()); -// for (auto v: mv) { -// ASSERT_EQ(v, 56); -// } -// ASSERT_EQ(forty, 56); -// forty = 40; -// } - -// TEST(MaybeView, MonadicOrElseRef) { -// int fortytwo{42}; -// int thirteen{13}; -// beman::optional::optional o1(fortytwo); -// auto r = o1.or_else([&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r.data()) == 42); - -// beman::optional::optional o2; -// ASSERT_TRUE(*(o2.or_else([&thirteen] { -// return beman::optional::optional(thirteen); -// })).data() == 13); - -// auto r2 = std::move(o1).or_else( -// [&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r2.data()) == 42); - -// auto r3 = std::move(o2).or_else( -// [&thirteen] { return beman::optional::optional(thirteen); }); -// ASSERT_TRUE(*(r3.data()) == 13); -// } From ef0d7be729b13629f6fbf45c995b932a5da72ceb Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 09:25:21 +0300 Subject: [PATCH 10/20] rename src/Beman --- src/Beman/optional/optional_monadic.t.cpp | 311 ---------- src/Beman/optional/optional_ref.t.cpp | 560 ------------------ src/Beman/optional/optional_ref_monadic.t.cpp | 318 ---------- 3 files changed, 1189 deletions(-) delete mode 100644 src/Beman/optional/optional_monadic.t.cpp delete mode 100644 src/Beman/optional/optional_ref.t.cpp delete mode 100644 src/Beman/optional/optional_ref_monadic.t.cpp diff --git a/src/Beman/optional/optional_monadic.t.cpp b/src/Beman/optional/optional_monadic.t.cpp deleted file mode 100644 index 79a1c6a7..00000000 --- a/src/Beman/optional/optional_monadic.t.cpp +++ /dev/null @@ -1,311 +0,0 @@ -#include - -#include - -constexpr int get_int(int) { return 42; } -constexpr beman::optional::optional get_opt_int(int) { return 42; } - - -TEST(OptionalMonadicTest, Transform) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 40; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - beman::optional::optional o3 = 42; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o4 = 40; - auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - const beman::optional::optional o5 = 40; - auto o5r = o5.transform([](const int &i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = 42; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = 42; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = 42; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - - // callable which returns a reference - beman::optional::optional o38 = 42; - auto o38r = o38.transform([](int &i) -> const int & { return i; }); - EXPECT_TRUE(o38r); - EXPECT_TRUE(*o38r == 42); - - } - - TEST(OptionalMonadicTest, TransformConstexpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = 42; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = 42; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); - } - -TEST(OptionalMonadicTest, Transform2) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 40; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - beman::optional::optional o3 = 42; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o4 = 40; - auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - const beman::optional::optional o5 = 40; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = 42; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = 42; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = 42; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - } - - TEST(OptionalMonadicTest, TransformConstxpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = 42; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = 42; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); - } - -TEST(OptionalMonadicTest, and_then) - { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - beman::optional::optional o2 = 12; - auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42.f); - - // lhs is empty, rhs returns empty - beman::optional::optional o3; - auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o3r); - - // rhs returns empty - beman::optional::optional o4 = 12; - auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o4r); - - struct rval_call_and_then { - beman::optional::optional operator()(int) && { - return beman::optional::optional(42.0); - }; - }; - - // ensure that function object is forwarded - beman::optional::optional o5 = 42; - auto o5r = o5.and_then(rval_call_and_then{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // ensure that lhs is forwarded - beman::optional::optional o6 = 42; - auto o6r = - std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o6r.value() == 42); - - // ensure that function object is const-propagated - const beman::optional::optional o7 = 42; - auto o7r = - o7.and_then([](const int &i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o7r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = 42; - auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o9 = 42; - auto o9r = - std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o9r == 42); - - const beman::optional::optional o10 = 42; - auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o10r == 42); - - const beman::optional::optional o11 = 42; - auto o11r = - std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o11r == 42); - - beman::optional::optional o16 = beman::optional::nullopt; - auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o16r); - - beman::optional::optional o17 = beman::optional::nullopt; - auto o17r = - std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o17r); - - const beman::optional::optional o18 = beman::optional::nullopt; - auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o18r); - - const beman::optional::optional o19 = beman::optional::nullopt; - auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o19r); - - int i = 3; - beman::optional::optional o20{i}; - std::move(o20).and_then([](int& r){return beman::optional::optional{++r};}); - EXPECT_TRUE(o20); - EXPECT_TRUE(i == 4); - } - -TEST(OptionalMonadicTest, Constexpr_and_then) -{ - constexpr beman::optional::optional o10 = 42; - constexpr auto o10r = o10.and_then(get_opt_int); - EXPECT_TRUE(*o10r == 42); - - constexpr beman::optional::optional o11 = 42; - constexpr auto o11r = std::move(o11).and_then(get_opt_int); - EXPECT_TRUE(*o11r == 42); - - constexpr beman::optional::optional o18 = beman::optional::nullopt; - constexpr auto o18r = o18.and_then(get_opt_int); - EXPECT_TRUE(!o18r); - - constexpr beman::optional::optional o19 = beman::optional::nullopt; - constexpr auto o19r = std::move(o19).and_then(get_opt_int); - EXPECT_TRUE(!o19r); - } - -TEST(OptionalMonadicTest, or_else){ - beman::optional::optional o1 = 42; - EXPECT_TRUE(*(o1.or_else([] { return beman::optional::make_optional(13); })) == 42); - - beman::optional::optional o2; - EXPECT_EQ(*(o2.or_else([] { return beman::optional::make_optional(13); })), 13); - } diff --git a/src/Beman/optional/optional_ref.t.cpp b/src/Beman/optional/optional_ref.t.cpp deleted file mode 100644 index 3591256b..00000000 --- a/src/Beman/optional/optional_ref.t.cpp +++ /dev/null @@ -1,560 +0,0 @@ -#include - -#include - -TEST(OptionalRefTest, TestGTest) { ASSERT_EQ(1, 1); } - -namespace { -struct empty {}; -struct no_default { - no_default() = delete; - no_default(const no_default&) = default; - no_default(no_default&&) = default; - no_default& operator=(const no_default&) = default; - no_default& operator=(no_default&&) = default; - no_default(empty){}; -}; - -struct base { - int i_; - base() : i_(0) {} - base(int i) : i_(i) {} -}; - -struct derived : public base { - int j_; - derived() : base(0), j_(0) {} - derived(int i, int j) : base(i), j_(j) {} -}; -} // namespace - -TEST(OptionalRefTest, Constructors) { - beman::optional::optional i1; - beman::optional::optional i2{beman::optional::nullopt}; - (void)i1; - (void)i2; - - int i = 0; - beman::optional::optional i3 = i; - (void)i3; - - beman::optional::optional e1; - beman::optional::optional e2{beman::optional::nullopt}; - (void)e1; - (void)e2; - - empty e{}; - beman::optional::optional e3 = e; - (void)e3; - - beman::optional::optional nd1; - beman::optional::optional nd2{beman::optional::nullopt}; - (void)nd1; - (void)nd2; - - no_default nd{e}; - - beman::optional::optional nd3 = nd; - (void)nd3; - - beman::optional::optional ie; - beman::optional::optional i4 = ie; - EXPECT_FALSE(i4); - - base b{1}; - derived d(1, 2); - beman::optional::optional b1 = b; - beman::optional::optional b2 = d; - - beman::optional::optional d2 = d; - beman::optional::optional b3 = d2; - beman::optional::optional b4{d2}; - - beman::optional::optional empty; - beman::optional::optional fromEmpty(empty); - beman::optional::optional fromEmpty2 = empty; -} - -TEST(OptionalRefTest, Assignment) { - beman::optional::optional i1; - EXPECT_FALSE(i1); - int i = 5; - i1 = i; - i = 7; - EXPECT_TRUE(i1); - EXPECT_TRUE(*i1 = 7); - - double d; - // i1 = d; // ill-formed by mandate - beman::optional::optional d1 = d; - // i1 = d1; // ill-formed by mandate - beman::optional::optional i2 = i1; - EXPECT_TRUE(i2); - EXPECT_TRUE(*i2 = 7); - - beman::optional::optional empty; - EXPECT_FALSE(empty); - i2 = empty; - EXPECT_FALSE(i2); - int eight = 8; - empty.emplace(eight); - EXPECT_TRUE(empty); - EXPECT_EQ(empty, 8); -} - -TEST(OptionalRefTest, RelationalOps) { - int i1 = 4; - int i2 = 42; - beman::optional::optional o1{i1}; - beman::optional::optional o2{i2}; - beman::optional::optional o3{}; - - // SECTION("self simple") - { - EXPECT_TRUE(!(o1 == o2)); - EXPECT_TRUE(o1 == o1); - EXPECT_TRUE(o1 != o2); - EXPECT_TRUE(!(o1 != o1)); - EXPECT_TRUE(o1 < o2); - EXPECT_TRUE(!(o1 < o1)); - EXPECT_TRUE(!(o1 > o2)); - EXPECT_TRUE(!(o1 > o1)); - EXPECT_TRUE(o1 <= o2); - EXPECT_TRUE(o1 <= o1); - EXPECT_TRUE(!(o1 >= o2)); - EXPECT_TRUE(o1 >= o1); - } - // SECTION("nullopt simple") - { - EXPECT_TRUE(!(o1 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o1)); - EXPECT_TRUE(o1 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o1); - EXPECT_TRUE(!(o1 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o1); - EXPECT_TRUE(o1 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o1)); - EXPECT_TRUE(!(o1 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o1); - EXPECT_TRUE(o1 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o1)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - // SECTION("with T simple") - { - EXPECT_TRUE(!(o1 == 1)); - EXPECT_TRUE(!(1 == o1)); - EXPECT_TRUE(o1 != 1); - EXPECT_TRUE(1 != o1); - EXPECT_TRUE(!(o1 < 1)); - EXPECT_TRUE(1 < o1); - EXPECT_TRUE(o1 > 1); - EXPECT_TRUE(!(1 > o1)); - EXPECT_TRUE(!(o1 <= 1)); - EXPECT_TRUE(1 <= o1); - EXPECT_TRUE(o1 >= 1); - EXPECT_TRUE(!(1 >= o1)); - - EXPECT_TRUE(o1 == 4); - EXPECT_TRUE(4 == o1); - EXPECT_TRUE(!(o1 != 4)); - EXPECT_TRUE(!(4 != o1)); - EXPECT_TRUE(!(o1 < 4)); - EXPECT_TRUE(!(4 < o1)); - EXPECT_TRUE(!(o1 > 4)); - EXPECT_TRUE(!(4 > o1)); - EXPECT_TRUE(o1 <= 4); - EXPECT_TRUE(4 <= o1); - EXPECT_TRUE(o1 >= 4); - EXPECT_TRUE(4 >= o1); - } - std::string s4 = "hello"; - std::string s5 = "xyz"; - beman::optional::optional o4{s4}; - beman::optional::optional o5{s5}; - - // SECTION("self complex") - { - EXPECT_TRUE(!(o4 == o5)); - EXPECT_TRUE(o4 == o4); - EXPECT_TRUE(o4 != o5); - EXPECT_TRUE(!(o4 != o4)); - EXPECT_TRUE(o4 < o5); - EXPECT_TRUE(!(o4 < o4)); - EXPECT_TRUE(!(o4 > o5)); - EXPECT_TRUE(!(o4 > o4)); - EXPECT_TRUE(o4 <= o5); - EXPECT_TRUE(o4 <= o4); - EXPECT_TRUE(!(o4 >= o5)); - EXPECT_TRUE(o4 >= o4); - } - // SECTION("nullopt complex") - { - EXPECT_TRUE(!(o4 == beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt == o4)); - EXPECT_TRUE(o4 != beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt != o4); - EXPECT_TRUE(!(o4 < beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt < o4); - EXPECT_TRUE(o4 > beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt > o4)); - EXPECT_TRUE(!(o4 <= beman::optional::nullopt)); - EXPECT_TRUE(beman::optional::nullopt <= o4); - EXPECT_TRUE(o4 >= beman::optional::nullopt); - EXPECT_TRUE(!(beman::optional::nullopt >= o4)); - - EXPECT_TRUE(o3 == beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt == o3); - EXPECT_TRUE(!(o3 != beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt != o3)); - EXPECT_TRUE(!(o3 < beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt < o3)); - EXPECT_TRUE(!(o3 > beman::optional::nullopt)); - EXPECT_TRUE(!(beman::optional::nullopt > o3)); - EXPECT_TRUE(o3 <= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt <= o3); - EXPECT_TRUE(o3 >= beman::optional::nullopt); - EXPECT_TRUE(beman::optional::nullopt >= o3); - } - - // SECTION("with T complex") - { - EXPECT_TRUE(!(o4 == "a")); - EXPECT_TRUE(!("a" == o4)); - EXPECT_TRUE(o4 != "a"); - EXPECT_TRUE("a" != o4); - EXPECT_TRUE(!(o4 < "a")); - EXPECT_TRUE("a" < o4); - EXPECT_TRUE(o4 > "a"); - EXPECT_TRUE(!("a" > o4)); - EXPECT_TRUE(!(o4 <= "a")); - EXPECT_TRUE("a" <= o4); - EXPECT_TRUE(o4 >= "a"); - EXPECT_TRUE(!("a" >= o4)); - - EXPECT_TRUE(o4 == "hello"); - EXPECT_TRUE("hello" == o4); - EXPECT_TRUE(!(o4 != "hello")); - EXPECT_TRUE(!("hello" != o4)); - EXPECT_TRUE(!(o4 < "hello")); - EXPECT_TRUE(!("hello" < o4)); - EXPECT_TRUE(!(o4 > "hello")); - EXPECT_TRUE(!("hello" > o4)); - EXPECT_TRUE(o4 <= "hello"); - EXPECT_TRUE("hello" <= o4); - EXPECT_TRUE(o4 >= "hello"); - EXPECT_TRUE("hello" >= o4); - } -} - -TEST(OptionalRefTest, Triviality) { - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - } - - { - struct T { - T(const T&) {} - T(T&&){}; - T& operator=(const T&) { return *this; } - T& operator=(T&&) { return *this; }; - ~T() {} - }; - EXPECT_TRUE(std::is_trivially_copy_constructible>::value); - EXPECT_TRUE(std::is_trivially_copy_assignable>::value); - EXPECT_TRUE(std::is_trivially_move_constructible>::value); - EXPECT_TRUE(std::is_trivially_move_assignable>::value); - EXPECT_TRUE(std::is_trivially_destructible>::value); - } -} - -TEST(OptionalRefTest, Deletion) { - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - - { - struct T { - T(const T&) = default; - T(T&&) = default; - T& operator=(const T&) = default; - T& operator=(T&&) = default; - ~T() = default; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - EXPECT_TRUE(std::is_destructible>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = delete; - T& operator=(const T&) = delete; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = delete; - T(T&&) = default; - T& operator=(const T&) = delete; - T& operator=(T&&) = default; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - EXPECT_TRUE(std::is_move_constructible>::value); - EXPECT_TRUE(std::is_move_assignable>::value); - } - - { - struct T { - T(const T&) = default; - T(T&&) = delete; - T& operator=(const T&) = default; - T& operator=(T&&) = delete; - }; - EXPECT_TRUE(std::is_copy_constructible>::value); - EXPECT_TRUE(std::is_copy_assignable>::value); - } -} - -struct takes_init_and_variadic { - std::vector v; - std::tuple t; - template - takes_init_and_variadic(std::initializer_list l, Args&&... args) : v(l), t(std::forward(args)...) {} -}; - -TEST(OptionalRefTest, MakeOptional) { - int var{42}; - auto o1 = beman::optional::make_optional(var); - auto o2 = beman::optional::optional(var); - - constexpr bool is_same = std::is_same>::value; - EXPECT_TRUE(is_same); - EXPECT_TRUE(o1 == o2); - - std::tuple tvar{0, 1, 2, 3}; - auto o3 = beman::optional::make_optional&>(tvar); - EXPECT_TRUE(std::get<0>(*o3) == 0); - EXPECT_TRUE(std::get<1>(*o3) == 1); - EXPECT_TRUE(std::get<2>(*o3) == 2); - EXPECT_TRUE(std::get<3>(*o3) == 3); - - std::vector ivec{0, 1, 2, 3}; - auto o4 = beman::optional::make_optional&>(ivec); - EXPECT_TRUE(o4.value()[0] == 0); - EXPECT_TRUE(o4.value()[1] == 1); - EXPECT_TRUE(o4.value()[2] == 2); - EXPECT_TRUE(o4.value()[3] == 3); - - takes_init_and_variadic tiv{{0, 1}, 2, 3}; - auto o5 = beman::optional::make_optional(tiv); - EXPECT_TRUE(o5->v[0] == 0); - EXPECT_TRUE(o5->v[1] == 1); - EXPECT_TRUE(std::get<0>(o5->t) == 2); - EXPECT_TRUE(std::get<1>(o5->t) == 3); - - auto i = 42; - auto o6 = beman::optional::make_optional(i); - static_assert(std::is_same_v>); - - EXPECT_TRUE((std::is_same_v>)); - EXPECT_TRUE(o6); - EXPECT_TRUE(*o6 == 42); -} - -TEST(OptionalRefTest, Nullopt) { - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2{beman::optional::nullopt}; - beman::optional::optional o3(beman::optional::nullopt); - beman::optional::optional o4 = {beman::optional::nullopt}; - - EXPECT_TRUE(!o1); - EXPECT_TRUE(!o2); - EXPECT_TRUE(!o3); - EXPECT_TRUE(!o4); - - EXPECT_TRUE(!std::is_default_constructible::value); -} - -struct move_detector { - move_detector() = default; - move_detector(move_detector&& rhs) { rhs.been_moved = true; } - bool been_moved = false; -}; - -TEST(OptionalRefTest, Observers) { - int var = 42; - beman::optional::optional o1 = var; - beman::optional::optional o2; - const beman::optional::optional o3 = var; - const beman::optional::optional o4; - int var2 = 42; - int var3 = 6*9; - EXPECT_TRUE(*o1 == 42); - EXPECT_TRUE(*o1 == o1.value()); - EXPECT_TRUE(o2.value_or(var2) == 42); - EXPECT_TRUE(o3.value() == 42); - EXPECT_TRUE(o3.value_or(var3) == 42); - EXPECT_TRUE(o4.value_or(var3) == 54); - int j = 99; - EXPECT_TRUE(o4.value_or(j) == 99); - // o4.value_or(j) = 88; - // EXPECT_TRUE(j == 88); - int var99 = 99; - j = 88; - EXPECT_TRUE([&](){beman::optional::optional o(j);return o; }().value_or(var99) == 88); - - EXPECT_TRUE([&](){beman::optional::optional o;return o; }().value_or(var99) == 99); - - - EXPECT_TRUE(o3.value_or([&]()->int&{return var3;}()) == 42); - EXPECT_TRUE(o4.value_or([&]()->int&{return var3;}()) == 54); - - std::string meow{"meow"}; - std::string bark{"bark"}; - beman::optional::optional so1; - beman::optional::optional so2{meow}; - auto t1 = so1.value_or(bark); - auto t2 = so2.value_or(bark); - // auto t3 = so1.value_or("bark"); - // auto t4 = so2.value_or("bark"); - // std::tuple t("meow"); - - auto success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - success = std::is_same::value; - static_assert(std::is_same::value); - EXPECT_TRUE(success); - - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - success = std::is_same()), int*>::value; - static_assert(std::is_same()), int*>::value); - EXPECT_TRUE(success); - - struct int_box {int i_;}; - int_box i1{3}; - beman::optional::optional ob1 = i1; - beman::optional::optional ob2; - const beman::optional::optional ob3 = i1; - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - success = std::is_samei_), int>::value; - static_assert(std::is_samei_), int>::value); - EXPECT_TRUE(success); - -} - -TEST(OptionalRefTest, MoveCheck) { - int x = 0; - int& y = std::move(beman::optional::optional(x)).value(); - EXPECT_EQ(&y, &x); - - int& z = *std::move(beman::optional::optional(x)); - EXPECT_EQ(&z, &x); - -} - -TEST(OptionalRefTest, SwapValue) { - int var = 42; - int twelve = 12; - beman::optional::optional o1 = var; - beman::optional::optional o2 = twelve; - o1.swap(o2); - EXPECT_EQ(o1.value(), 12); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalRefTest, SwapWNull) { - int var = 42; - - beman::optional::optional o1 = var; - beman::optional::optional o2 = beman::optional::nullopt; - o1.swap(o2); - EXPECT_TRUE(!o1.has_value()); - EXPECT_EQ(o2.value(), 42); -} - -TEST(OptionalRefTest, SwapNullIntializedWithValue) { - int var = 42; - beman::optional::optional o1 = beman::optional::nullopt; - beman::optional::optional o2 = var; - o1.swap(o2); - EXPECT_EQ(o1.value(), 42); - EXPECT_TRUE(!o2.has_value()); -} diff --git a/src/Beman/optional/optional_ref_monadic.t.cpp b/src/Beman/optional/optional_ref_monadic.t.cpp deleted file mode 100644 index 9d9f9fda..00000000 --- a/src/Beman/optional/optional_ref_monadic.t.cpp +++ /dev/null @@ -1,318 +0,0 @@ -#include - -#include - -namespace { -inline constexpr int constexpr_fortytwo = 42; -constexpr int get_int(int) { return constexpr_fortytwo; } -constexpr beman::optional::optional get_opt_int(int) { return constexpr_fortytwo; } -} // namespace - -TEST(OptionalRefMonadicTest, Transform) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int forty = 40; - beman::optional::optional o2 = forty; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o3 = fortytwo; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // // ensure that lhs is forwarded - // forty = 40; - // beman::optional::optional o4 = forty; - // auto o4r = std::move(o4).transform([](int &&i) { return i + 2; }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - forty = 40; - const beman::optional::optional o5 = forty; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - fortytwo = 42; - beman::optional::optional o8 = fortytwo; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = fortytwo; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = fortytwo; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = fortytwo; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); - - // callable which returns a reference - beman::optional::optional o38 = fortytwo; - auto o38r = o38.transform([](int& i) -> const int& { return i; }); - EXPECT_TRUE(o38r); - EXPECT_TRUE(*o38r == 42); -} - -TEST(OptionalRefMonadicTest, TransformConstexpr) { - - // test each overload in turn - constexpr beman::optional::optional o16 = constexpr_fortytwo; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = constexpr_fortytwo; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); -} - -TEST(OptionalRefMonadicTest, Transform2) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int forty = 40; - beman::optional::optional o2 = forty; - auto o2r = o2.transform([](int i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42); - - struct rval_call_transform { - double operator()(int) && { return 42.0; }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o3 = fortytwo; - auto o3r = o3.transform(rval_call_transform{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o3r.value() == 42); - - // // ensure that lhs is forwarded - // int forty = 40; - // beman::optional::optional o4 = forty; - // auto o4r = std::move(o4).transform([](int&& i) { return i + 2; }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o4r.value() == 42); - - // ensure that lhs is const-propagated - forty = 40; - const beman::optional::optional o5 = forty; - auto o5r = o5.transform([](const int& i) { return i + 2; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // test each overload in turn - fortytwo = 42; - beman::optional::optional o8 = fortytwo; - auto o8r = o8.transform([](int) { return 42; }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o12 = fortytwo; - auto o12r = std::move(o12).transform([](int) { return 42; }); - EXPECT_TRUE(*o12r == 42); - - const beman::optional::optional o16 = fortytwo; - auto o16r = o16.transform([](int) { return 42; }); - EXPECT_TRUE(*o16r == 42); - - const beman::optional::optional o20 = fortytwo; - auto o20r = std::move(o20).transform([](int) { return 42; }); - EXPECT_TRUE(*o20r == 42); - - beman::optional::optional o24 = beman::optional::nullopt; - auto o24r = o24.transform([](int) { return 42; }); - EXPECT_TRUE(!o24r); - - beman::optional::optional o28 = beman::optional::nullopt; - auto o28r = std::move(o28).transform([](int) { return 42; }); - EXPECT_TRUE(!o28r); - - const beman::optional::optional o32 = beman::optional::nullopt; - auto o32r = o32.transform([](int) { return 42; }); - EXPECT_TRUE(!o32r); - - const beman::optional::optional o36 = beman::optional::nullopt; - auto o36r = std::move(o36).transform([](int) { return 42; }); - EXPECT_TRUE(!o36r); -} - -TEST(OptionalRefMonadicTest, TransformConstxpr) { - // test each overload in turn - constexpr beman::optional::optional o16 = constexpr_fortytwo; - constexpr auto o16r = o16.transform(get_int); - static_assert(*o16r == 42); - - constexpr beman::optional::optional o20 = constexpr_fortytwo; - constexpr auto o20r = std::move(o20).transform(get_int); - static_assert(*o20r == 42); - - constexpr beman::optional::optional o32 = beman::optional::nullopt; - constexpr auto o32r = o32.transform(get_int); - static_assert(!o32r); - constexpr beman::optional::optional o36 = beman::optional::nullopt; - constexpr auto o36r = std::move(o36).transform(get_int); - static_assert(!o36r); -} - -TEST(OptionalRefMonadicTest, and_then) { - // lhs is empty - beman::optional::optional o1; - auto o1r = o1.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o1r); - - // lhs has value - int twelve = 12; - beman::optional::optional o2 = twelve; - auto o2r = o2.and_then([](int) { return beman::optional::optional{42}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o2r.value() == 42.f); - - // lhs is empty, rhs returns empty - beman::optional::optional o3; - auto o3r = o3.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o3r); - - // rhs returns empty - beman::optional::optional o4 = twelve; - auto o4r = o4.and_then([](int) { return beman::optional::optional{}; }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(!o4r); - - struct rval_call_and_then { - beman::optional::optional operator()(int) && { return beman::optional::optional(42.0); }; - }; - - // ensure that function object is forwarded - int fortytwo = 42; - beman::optional::optional o5 = fortytwo; - auto o5r = o5.and_then(rval_call_and_then{}); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o5r.value() == 42); - - // // ensure that lhs is forwarded - // beman::optional::optional o6 = fortytwo; - // auto o6r = - // std::move(o6).and_then([](int &&i) { return beman::optional::optional(i); }); - // static_assert((std::is_same>::value)); - // EXPECT_TRUE(o6r.value() == 42); - - // ensure that function object is const-propagated - const beman::optional::optional o7 = fortytwo; - auto o7r = o7.and_then([](const int& i) { return beman::optional::optional(i); }); - static_assert((std::is_same>::value)); - EXPECT_TRUE(o7r.value() == 42); - - // test each overload in turn - beman::optional::optional o8 = fortytwo; - auto o8r = o8.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o8r == 42); - - beman::optional::optional o9 = fortytwo; - auto o9r = std::move(o9).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o9r == 42); - - const beman::optional::optional o10 = fortytwo; - auto o10r = o10.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o10r == 42); - - const beman::optional::optional o11 = fortytwo; - auto o11r = std::move(o11).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(*o11r == 42); - - beman::optional::optional o16 = beman::optional::nullopt; - auto o16r = o16.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o16r); - - beman::optional::optional o17 = beman::optional::nullopt; - auto o17r = std::move(o17).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o17r); - - const beman::optional::optional o18 = beman::optional::nullopt; - auto o18r = o18.and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o18r); - - const beman::optional::optional o19 = beman::optional::nullopt; - auto o19r = std::move(o19).and_then([](int) { return beman::optional::make_optional(42); }); - EXPECT_TRUE(!o19r); - - int i = 3; - beman::optional::optional o20{i}; - std::move(o20).and_then([](int& r) { return beman::optional::optional{++r}; }); - EXPECT_TRUE(o20); - EXPECT_TRUE(i == 4); -} - -TEST(OptionalRefMonadicTest, Constexpr_and_then) { - constexpr beman::optional::optional o10 = constexpr_fortytwo; - constexpr auto o10r = o10.and_then(get_opt_int); - EXPECT_TRUE(*o10r == 42); - - constexpr beman::optional::optional o11 = constexpr_fortytwo; - constexpr auto o11r = std::move(o11).and_then(get_opt_int); - EXPECT_TRUE(*o11r == 42); - - constexpr beman::optional::optional o18 = beman::optional::nullopt; - constexpr auto o18r = o18.and_then(get_opt_int); - EXPECT_TRUE(!o18r); - - constexpr beman::optional::optional o19 = beman::optional::nullopt; - constexpr auto o19r = std::move(o19).and_then(get_opt_int); - EXPECT_TRUE(!o19r); -} - -TEST(OptionalRefMonadicTest, or_else) { - int fortytwo = 42; - int thirteen = 13; - beman::optional::optional o1 = fortytwo; - EXPECT_TRUE(*(o1.or_else([&] { return beman::optional::optional(thirteen); })) == 42); - - beman::optional::optional o2; - EXPECT_EQ(*(o2.or_else([&] { return beman::optional::optional(thirteen); })), 13); -} From 04db193ff8db17df1e4d63d50568ef77eaa0f714 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 09:51:17 +0300 Subject: [PATCH 11/20] Check __cpp_lib_format_ranges for interaction between range support and format --- include/Beman/Optional26/optional.hpp | 5 ++--- .../optional/tests/optional_range_support.t.cpp | 17 +++++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index 6bcfa02c..66d4c491 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -229,9 +229,8 @@ template inline constexpr bool ranges::enable_borrowed_range> = true; // Since P3168R1: Give std::optional Range Support. -// Note: At 13.06.2024, gcc and msvc do not implement P2585R1: "Improve default container formatting". -// TODO @neatudarius: always enable once supported by other compilers. -#if defined(__clang__) +// TODO: Always enable when all major compilers implement P2585R1: "Improve default container formatting". +#if defined(__cpp_lib_format_ranges) template inline constexpr auto format_kind> = range_format::disabled; #endif diff --git a/src/Beman/optional/tests/optional_range_support.t.cpp b/src/Beman/optional/tests/optional_range_support.t.cpp index db09e388..26f5f4c2 100644 --- a/src/Beman/optional/tests/optional_range_support.t.cpp +++ b/src/Beman/optional/tests/optional_range_support.t.cpp @@ -1,3 +1,10 @@ +/** + * This file contains tests for the range support. Check P3168R1: "Give std::optional Range Support". + * + * RangeSupportTest: test suite for the range support. + * + * Classes used in the tests: int, pointers, empty, no_default_ctor, base, derived. + */ #include #include @@ -178,14 +185,12 @@ TEST(RangeSupportTest, IteratorConceptsCheck) { } TEST(RangeSupportTest, FormatOptionalIsStillDisabled) { -// Since P3168R1: Give std::optional Range Support. -// Note: At 13.06.2024, gcc and msvc do not implement P2585R1: "Improve default container formatting". -// TODO @neatudarius: always enable once supported by other compilers. -#if defined(__clang__) +// TODO: Always enable when all major compilers implement P2585R1: "Improve default container formatting". +#if defined(__cpp_lib_format_ranges) EXPECT_EQ(std::format_kind>, std::range_format::disabled); - // Next line shold not compile: formatter is not defined for std::optional and bemans::optional::optional. - // EXPECT_EQ(std::format("{}", beman::optional::optional {}), ""); + // Next line shold not compile: formatter is not defined for optional. + // EXPECT_EQ(std::format("{}", beman::optional::optional {}), "[]"); #endif } From 5a0ae2b4dd1b0b1bdfdb7e3d2310ad98a5997272 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 09:57:53 +0300 Subject: [PATCH 12/20] Use shorter alias - std::views --- src/Beman/optional/tests/optional.t.cpp | 6 +-- .../tests/optional_range_support.t.cpp | 37 +++++++++---------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/Beman/optional/tests/optional.t.cpp b/src/Beman/optional/tests/optional.t.cpp index 9da8715d..ef73d6f5 100644 --- a/src/Beman/optional/tests/optional.t.cpp +++ b/src/Beman/optional/tests/optional.t.cpp @@ -823,8 +823,8 @@ TEST(ViewMaybe, CompTestRef) { // (This uses one syntax for constrained lambdas // in C++20.) inline constexpr auto and_then = [](auto&& r, auto fun) { - return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | - std::ranges::views::join; + return decltype(r)(r) | std::views::transform(std::move(fun)) | + std::views::join; }; // "yield_if" takes a bool and a value and @@ -837,7 +837,7 @@ inline constexpr auto yield_if = [](bool b, T x) { TEST(ViewMaybeTest, PythTripleTest) { - using std::ranges::views::iota; + using std::views::iota; auto triples = and_then(iota(1), [](int z) { return and_then(iota(1, z + 1), [=](int x) { return and_then(iota(x, z + 1), [=](int y) { diff --git a/src/Beman/optional/tests/optional_range_support.t.cpp b/src/Beman/optional/tests/optional_range_support.t.cpp index 26f5f4c2..24b39993 100644 --- a/src/Beman/optional/tests/optional_range_support.t.cpp +++ b/src/Beman/optional/tests/optional_range_support.t.cpp @@ -259,17 +259,16 @@ TEST(RangeSupportTest, RangeChainExampleWithVector) { } }; - auto&& r = - v // starting vector - | std::ranges::views::transform(test) // generates {nullopt, 3, nullopt, 7, nullopt, nullopt, nullopt, 9, 1} - | std::ranges::views::filter([](auto x) { - return bool(x); - }) // generates {optional{3}, optional{7}, optional{9}, optional{1}} - | std::ranges::views::transform([](auto x) { return *x; }) // generates {3, 5, 7, 9} - | std::ranges::views::transform([](int i) { - // std::cout << i << "\n"; // do not actually do it in tests - return i; - }) // print + identity transform + auto&& r = v // starting vector + | std::views::transform(test) // generates {nullopt, 3, nullopt, 7, nullopt, nullopt, nullopt, 9, 1} + | std::views::filter([](auto x) { + return bool(x); + }) // generates {optional{3}, optional{7}, optional{9}, optional{1}} + | std::views::transform([](auto x) { return *x; }) // generates {3, 5, 7, 9} + | std::views::transform([](int i) { + // std::cout << i << "\n"; // do not actually do it in tests + return i; + }) // print + identity transform ; ASSERT_TRUE(std::ranges::equal(r, std::vector{3, 7, 9, 1})); @@ -286,9 +285,9 @@ TEST(RangeSupportTest, RangeChainExampleWithSets) { } }; - for (auto i : std::ranges::views::iota(1, 10) | std::ranges::views::transform(flt)) { + for (auto i : std::views::iota(1, 10) | std::views::transform(flt)) { for (auto j : i) { // no need to transform - for (auto k : std::ranges::views::iota(0, j)) { + for (auto k : std::views::iota(0, j)) { // std::cout << '\a'; // do not actually log in tests std::ignore = k; } @@ -304,11 +303,11 @@ TEST(RangeSupportTest, PythagoreanTriples) { return b ? beman::optional::optional{std::move(x)} : beman::optional::nullopt; }; constexpr auto and_then = [](T&& r, auto fun) { - return decltype(r)(r) | std::ranges::views::transform(std::move(fun)) | std::ranges::views::join; + return decltype(r)(r) | std::views::transform(std::move(fun)) | std::views::join; }; - auto triples = and_then(std::ranges::views::iota(1), [=](int z) { - return and_then(std::ranges::views::iota(1, z + 1), [=](int x) { - return and_then(std::ranges::views::iota(x, z + 1), + auto triples = and_then(std::views::iota(1), [=](int z) { + return and_then(std::views::iota(1, z + 1), [=](int x) { + return and_then(std::views::iota(x, z + 1), [=](int y) { return yield_if(x * x + y * y == z * z, std::make_tuple(x, y, z)); }); }); }); @@ -316,7 +315,7 @@ TEST(RangeSupportTest, PythagoreanTriples) { { // Generate first 10 Pythagorean triples. // https://mathworld.wolfram.com/PythagoreanTriple.html - auto&& r = triples | std::ranges::views::take(10); + auto&& r = triples | std::views::take(10); EXPECT_TRUE(std::ranges::equal(r, std::vector{ std::tuple{3, 4, 5}, @@ -359,7 +358,7 @@ TEST(RangeSupportTest, PythagoreanTriples) { ASSERT_EQ(bruteforce_generate_nth(100, 200), k100th_triple); // Generate the 100th Pythagorean triple with ranges. - auto&& r = triples | std::ranges::views::drop(99) | std::ranges::views::take(1); + auto&& r = triples | std::views::drop(99) | std::views::take(1); EXPECT_TRUE(std::ranges::equal(r, std::vector{k100th_triple})); } } From e4366f74f5cb7f9239ffef1eb01ba1307fc9947b Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 10:01:41 +0300 Subject: [PATCH 13/20] Remove enable_view> specialization: optional is already always a view --- include/Beman/Optional26/optional.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index 66d4c491..a6ed979d 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -209,13 +209,6 @@ namespace std { template inline constexpr bool ranges::enable_view> = true; -// Since ${PAPER_NUMBER}: ${PAPER_TITLE}. -// Note: P3168 and P2988 may have different flows inside LEWG/LWG. -// Implementation of the range support for optional reflects P3168R1 for now. -// [optional.iterators], iterator support -template -inline constexpr bool ranges::enable_view> = true; - // TODO: document why this is needed. template inline constexpr bool ranges::enable_borrowed_range> = true; From 799e49515b3c5aadb6b989f0652361a3bbaa9aa5 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Fri, 14 Jun 2024 10:10:04 +0300 Subject: [PATCH 14/20] Add more concepts tests --- src/Beman/optional/tests/optional.t.cpp | 36 ------------------- .../tests/optional_range_support.t.cpp | 17 +++++++++ 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/src/Beman/optional/tests/optional.t.cpp b/src/Beman/optional/tests/optional.t.cpp index ef73d6f5..e29ff4ea 100644 --- a/src/Beman/optional/tests/optional.t.cpp +++ b/src/Beman/optional/tests/optional.t.cpp @@ -638,42 +638,6 @@ TEST(ViewMaybeTest, Constructors) { beman::optional::optional> n3{std::optional{}}; } -TEST(ViewMaybeTest, ConceptCheck) { - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(!std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - static_assert(std::ranges::sized_range>); - - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); - - using ref = std::reference_wrapper; - static_assert(std::ranges::range>); - static_assert(std::ranges::view>); - static_assert(std::ranges::input_range>); - static_assert(std::ranges::forward_range>); - static_assert(std::ranges::bidirectional_range>); - static_assert(std::ranges::contiguous_range>); - static_assert(std::ranges::common_range>); - static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); - static_assert(std::ranges::random_access_range>); -} TEST(ViewMaybeTest, ConceptCheckRef) { static_assert(std::ranges::range>); diff --git a/src/Beman/optional/tests/optional_range_support.t.cpp b/src/Beman/optional/tests/optional_range_support.t.cpp index 24b39993..86c49394 100644 --- a/src/Beman/optional/tests/optional_range_support.t.cpp +++ b/src/Beman/optional/tests/optional_range_support.t.cpp @@ -148,6 +148,23 @@ TEST(RangeSupportTest, RangeConceptsCheck) { std::ranges::borrowed_range>); // borrowed_range is enabled for pointers static_assert(std::ranges::random_access_range>); } + + { + using ref = std::reference_wrapper; + // beman::optional::optional is a range. + static_assert(std::ranges::range>); + static_assert(std::ranges::view>); + static_assert(std::ranges::input_range>); + static_assert(std::ranges::forward_range>); + static_assert(std::ranges::bidirectional_range>); + static_assert(std::ranges::contiguous_range>); + static_assert(std::ranges::common_range>); + static_assert(std::ranges::viewable_range>); + static_assert(std::ranges::borrowed_range>); // borrowed_range is + // enabled for + // reference_wrapper + static_assert(std::ranges::random_access_range>); + } } TEST(RangeSupportTest, IteratorConceptsCheck) { From 923fde0fe5ec89fd41f2249b96363df65494941d Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Mon, 17 Jun 2024 10:27:40 +0300 Subject: [PATCH 15/20] Rename src/Beman/optional to src/Beman/Optional26 (match the include/ subtree) --- include/Beman/Optional26/optional.hpp | 9 +++++---- src/Beman/CMakeLists.txt | 2 +- src/Beman/{optional => Optional26}/CMakeLists.txt | 0 src/Beman/{optional => Optional26}/optional.cpp | 0 src/Beman/{optional => Optional26}/tests/optional.t.cpp | 0 .../tests/optional_monadic.t.cpp | 0 .../tests/optional_range_support.t.cpp | 0 .../{optional => Optional26}/tests/optional_ref.t.cpp | 0 .../tests/optional_ref_monadic.t.cpp | 0 9 files changed, 6 insertions(+), 5 deletions(-) rename src/Beman/{optional => Optional26}/CMakeLists.txt (100%) rename src/Beman/{optional => Optional26}/optional.cpp (100%) rename src/Beman/{optional => Optional26}/tests/optional.t.cpp (100%) rename src/Beman/{optional => Optional26}/tests/optional_monadic.t.cpp (100%) rename src/Beman/{optional => Optional26}/tests/optional_range_support.t.cpp (100%) rename src/Beman/{optional => Optional26}/tests/optional_ref.t.cpp (100%) rename src/Beman/{optional => Optional26}/tests/optional_ref_monadic.t.cpp (100%) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index a6ed979d..67d15d88 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -1,6 +1,6 @@ -// beman/optional/optional.h -*-C++-*- -#ifndef BEMAN_OPTIONAL26_OPTIONAL -#define BEMAN_OPTIONAL26_OPTIONAL +// include/Beman/Optional26/optional.hpp -*-C++-*- +#ifndef BEMAN_OPTIONAL26_OPTIONAL_HPP +#define BEMAN_OPTIONAL26_OPTIONAL_HPP /* 22.5.2 Header synopsis[optional.syn] @@ -1129,4 +1129,5 @@ class optional { constexpr void reset() noexcept { value_ = nullptr; } }; } // namespace beman::optional -#endif + +#endif // BEMAN_OPTIONAL26_OPTIONAL_HPP diff --git a/src/Beman/CMakeLists.txt b/src/Beman/CMakeLists.txt index 3fff7288..ade4beba 100644 --- a/src/Beman/CMakeLists.txt +++ b/src/Beman/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(optional) +add_subdirectory(Optional26) diff --git a/src/Beman/optional/CMakeLists.txt b/src/Beman/Optional26/CMakeLists.txt similarity index 100% rename from src/Beman/optional/CMakeLists.txt rename to src/Beman/Optional26/CMakeLists.txt diff --git a/src/Beman/optional/optional.cpp b/src/Beman/Optional26/optional.cpp similarity index 100% rename from src/Beman/optional/optional.cpp rename to src/Beman/Optional26/optional.cpp diff --git a/src/Beman/optional/tests/optional.t.cpp b/src/Beman/Optional26/tests/optional.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional.t.cpp rename to src/Beman/Optional26/tests/optional.t.cpp diff --git a/src/Beman/optional/tests/optional_monadic.t.cpp b/src/Beman/Optional26/tests/optional_monadic.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional_monadic.t.cpp rename to src/Beman/Optional26/tests/optional_monadic.t.cpp diff --git a/src/Beman/optional/tests/optional_range_support.t.cpp b/src/Beman/Optional26/tests/optional_range_support.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional_range_support.t.cpp rename to src/Beman/Optional26/tests/optional_range_support.t.cpp diff --git a/src/Beman/optional/tests/optional_ref.t.cpp b/src/Beman/Optional26/tests/optional_ref.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional_ref.t.cpp rename to src/Beman/Optional26/tests/optional_ref.t.cpp diff --git a/src/Beman/optional/tests/optional_ref_monadic.t.cpp b/src/Beman/Optional26/tests/optional_ref_monadic.t.cpp similarity index 100% rename from src/Beman/optional/tests/optional_ref_monadic.t.cpp rename to src/Beman/Optional26/tests/optional_ref_monadic.t.cpp From eba77143bc1b6ee99f4f0a0eb75085a6c38a1df4 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Mon, 17 Jun 2024 11:48:41 +0300 Subject: [PATCH 16/20] Remove build cache from CI --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d09acbdd..ddf1d929 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,9 @@ jobs: - uses: seanmiddleditch/gha-setup-ninja@master + - name: Activate verbose shell + run: set -x + - name: Install LLVM+Clang if: startsWith(matrix.config.os, 'ubuntu-') run: | @@ -105,6 +108,7 @@ jobs: - name: Configure run: | + rm -rf .build mkdir -p .build cd .build echo ${{ matrix.config.cmake_args }} From fdb8d84baf06dad7f50c34d6acf7db07eb7b3027 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Tue, 18 Jun 2024 18:10:41 +0300 Subject: [PATCH 17/20] Disable borrowed_range for some optional overloads --- include/Beman/Optional26/optional.hpp | 8 -------- .../Optional26/tests/optional_range_support.t.cpp | 10 +++------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index 67d15d88..3f369e6d 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -209,14 +209,6 @@ namespace std { template inline constexpr bool ranges::enable_view> = true; -// TODO: document why this is needed. -template -inline constexpr bool ranges::enable_borrowed_range> = true; - -// TODO: document why this is needed. -template -inline constexpr bool ranges::enable_borrowed_range>> = true; - // TODO: document why this is needed. template inline constexpr bool ranges::enable_borrowed_range> = true; diff --git a/src/Beman/Optional26/tests/optional_range_support.t.cpp b/src/Beman/Optional26/tests/optional_range_support.t.cpp index 86c49394..92257dc2 100644 --- a/src/Beman/Optional26/tests/optional_range_support.t.cpp +++ b/src/Beman/Optional26/tests/optional_range_support.t.cpp @@ -128,8 +128,7 @@ TEST(RangeSupportTest, RangeConceptsCheck) { static_assert(std::ranges::contiguous_range>); static_assert(std::ranges::common_range>); static_assert(std::ranges::viewable_range>); - static_assert(!std::ranges::borrowed_range>); // borrowed_range is disabled for - // non-pointers + static_assert(!std::ranges::borrowed_range>); static_assert(std::ranges::random_access_range>); static_assert(std::ranges::sized_range>); } @@ -144,8 +143,7 @@ TEST(RangeSupportTest, RangeConceptsCheck) { static_assert(std::ranges::contiguous_range>); static_assert(std::ranges::common_range>); static_assert(std::ranges::viewable_range>); - static_assert( - std::ranges::borrowed_range>); // borrowed_range is enabled for pointers + static_assert(!std::ranges::borrowed_range>); static_assert(std::ranges::random_access_range>); } @@ -160,9 +158,7 @@ TEST(RangeSupportTest, RangeConceptsCheck) { static_assert(std::ranges::contiguous_range>); static_assert(std::ranges::common_range>); static_assert(std::ranges::viewable_range>); - static_assert(std::ranges::borrowed_range>); // borrowed_range is - // enabled for - // reference_wrapper + static_assert(!std::ranges::borrowed_range>); static_assert(std::ranges::random_access_range>); } } From cb0b4584982e9c59ad6d87928f3a1369b341a493 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Tue, 18 Jun 2024 18:19:35 +0300 Subject: [PATCH 18/20] Remove non-range specific test --- .../tests/optional_range_support.t.cpp | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/src/Beman/Optional26/tests/optional_range_support.t.cpp b/src/Beman/Optional26/tests/optional_range_support.t.cpp index 92257dc2..aa2623e6 100644 --- a/src/Beman/Optional26/tests/optional_range_support.t.cpp +++ b/src/Beman/Optional26/tests/optional_range_support.t.cpp @@ -257,37 +257,7 @@ TEST(RangeSupportTest, LoopOptionalAssignment) { EXPECT_EQ(opt_int.value(), expected_value); } -TEST(RangeSupportTest, RangeChainExampleWithVector) { - // Example from P3168R1: start from a vector of values, apply multiple range operations involving optional values. - std::vector v{2, 3, 4, 5, 6, 7, 8, 9, 1}; - const auto test = [](int i) -> beman::optional::optional { - switch (i) { - case 1: - case 3: - case 7: - case 9: - return i; - default: - return {}; - } - }; - - auto&& r = v // starting vector - | std::views::transform(test) // generates {nullopt, 3, nullopt, 7, nullopt, nullopt, nullopt, 9, 1} - | std::views::filter([](auto x) { - return bool(x); - }) // generates {optional{3}, optional{7}, optional{9}, optional{1}} - | std::views::transform([](auto x) { return *x; }) // generates {3, 5, 7, 9} - | std::views::transform([](int i) { - // std::cout << i << "\n"; // do not actually do it in tests - return i; - }) // print + identity transform - ; - - ASSERT_TRUE(std::ranges::equal(r, std::vector{3, 7, 9, 1})); -} - -TEST(RangeSupportTest, RangeChainExampleWithSets) { +TEST(RangeSupportTest, RangeChainExample) { // Example from P3168R1: start from a set of values, apply multiple range operations involving optional values. std::unordered_set s{1, 3, 7, 9}; const auto flt = [&](int i) -> beman::optional::optional { From 777ddb10a417986e218d01a0a6f652add7854bf1 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Tue, 18 Jun 2024 18:37:26 +0300 Subject: [PATCH 19/20] Temporary disable CI worflow for clang-19 as it cannot be tested on all platforms on local setups --- .github/workflows/ci.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ddf1d929..7947a633 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,15 +34,6 @@ jobs: cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" " } - - { - name: "Ubuntu Clang 19", - os: ubuntu-24.04, - toolchain: "clang-19-toolchain.cmake", - clang_version: 19, - installed_clang_version: 14, - cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" " - } - - { name: "Ubuntu GCC 13", os: ubuntu-24.04, @@ -74,6 +65,7 @@ jobs: - name: Install LLVM+Clang if: startsWith(matrix.config.os, 'ubuntu-') run: | + set -x cat /etc/lsb-release sudo apt-get remove clang-${{matrix.config.installed_clang_version}} \ lldb-${{matrix.config.installed_clang_version}} \ From 77fb8da70e9bddc11a2f78b64238e21905cd7256 Mon Sep 17 00:00:00 2001 From: Darius Neatu Date: Wed, 19 Jun 2024 08:49:17 +0300 Subject: [PATCH 20/20] Add guards for --- include/Beman/Optional26/optional.hpp | 3 ++- src/Beman/Optional26/tests/optional_range_support.t.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/Beman/Optional26/optional.hpp b/include/Beman/Optional26/optional.hpp index 3f369e6d..4758632a 100644 --- a/include/Beman/Optional26/optional.hpp +++ b/include/Beman/Optional26/optional.hpp @@ -165,7 +165,9 @@ namespace std { */ #include +#if defined(__cpp_lib_format_ranges) #include +#endif #include #include #include @@ -214,7 +216,6 @@ template inline constexpr bool ranges::enable_borrowed_range> = true; // Since P3168R1: Give std::optional Range Support. -// TODO: Always enable when all major compilers implement P2585R1: "Improve default container formatting". #if defined(__cpp_lib_format_ranges) template inline constexpr auto format_kind> = range_format::disabled; diff --git a/src/Beman/Optional26/tests/optional_range_support.t.cpp b/src/Beman/Optional26/tests/optional_range_support.t.cpp index aa2623e6..b58d4c39 100644 --- a/src/Beman/Optional26/tests/optional_range_support.t.cpp +++ b/src/Beman/Optional26/tests/optional_range_support.t.cpp @@ -8,7 +8,9 @@ #include #include +#if defined(__cpp_lib_format_ranges) #include +#endif #include #include #include