#include "catch.hpp" #include "optional.hpp" #define TOKENPASTE(x, y) x##y #define TOKENPASTE2(x, y) TOKENPASTE(x, y) #define STATIC_REQUIRE(e) \ constexpr bool TOKENPASTE2(rqure, __LINE__) = e; \ REQUIRE(e); // What is Clang Format up to?! TEST_CASE("Monadic operations", "[monadic]"){SECTION("map"){// lhs is empty tl::optional o1; auto o1r = o1.map([](int i) { return i + 2; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(!o1r); // lhs has value tl::optional o2 = 40; auto o2r = o2.map([](int i) { return i + 2; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o2r.value() == 42); struct rval_call_map { auto operator()(int) && { return 42.0; }; }; // ensure that function object is forwarded tl::optional o3 = 42; auto o3r = o3.map(rval_call_map{}); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o3r.value() == 42); // ensure that lhs is forwarded tl::optional o4 = 40; auto o4r = std::move(o4).map([](int &&i) { return i + 2; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o4r.value() == 42); // ensure that lhs is const-propagated const tl::optional o5 = 40; auto o5r = o5.map([](const int &i) { return i + 2; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o5r.value() == 42); // test applicative functor tl::optional o6 = 40; auto f6 = tl::make_optional([](const int &i) { return i + 2; }); auto o6r = o6.map(f6); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o6r.value() == 42); // test void return tl::optional o7 = 40; auto f7 = tl::make_optional([](const int &i) { return; }); auto o7r = o7.map(f7); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o6r.has_value()); } SECTION("bind") { // lhs is empty tl::optional o1; auto o1r = o1.bind([](int i) { return tl::optional{42}; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(!o1r); // lhs has value tl::optional o2 = 12; auto o2r = o2.bind([](int i) { return tl::optional{42}; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o2r.value() == 42.f); // lhs is empty, rhs returns empty tl::optional o3; auto o3r = o3.bind([](int i) { return tl::optional{}; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(!o3r); // rhs returns empty tl::optional o4 = 12; auto o4r = o4.bind([](int i) { return tl::optional{}; }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(!o4r); struct rval_call_bind { auto operator()(int) && { return tl::optional(42.0); }; }; // ensure that function object is forwarded tl::optional o5 = 42; auto o5r = o5.bind(rval_call_bind{}); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o5r.value() == 42); // ensure that lhs is forwarded tl::optional o6 = 42; auto o6r = std::move(o6).bind([](int &&i) { return tl::optional(i); }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o6r.value() == 42); // ensure that function object is const-propagated const tl::optional o7 = 42; auto o7r = o7.bind([](const int &i) { return tl::optional(i); }); STATIC_REQUIRE((std::is_same>::value)); REQUIRE(o7r.value() == 42); } } ;