Skip to content

Commit

Permalink
Add rsl::maybe_error
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisThrasher authored and tylerjw committed Dec 12, 2023
1 parent 79b6c41 commit 608dd6e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 0 deletions.
1 change: 1 addition & 0 deletions .codespell_words
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unexpect
22 changes: 22 additions & 0 deletions include/rsl/monad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,28 @@ template <typename T, typename E>
return exp.has_value();
}

/**
* @brief Tests if any of the expected args passed in has an error.
*
* @param args tl::expected<T, E> parameter pack
*
* @tparam E The error type
* @tparam Args The value types for the tl::expected<T, E> args
*
* @return The first error found or nothing
*/
template <typename E, typename... Args>
[[nodiscard]] constexpr auto maybe_error(tl::expected<Args, E>... args) {
auto maybe = std::optional<E>();
(
[&](auto& exp) {
if (maybe.has_value()) return;
if (has_error(exp)) maybe = exp.error();
}(args),
...);
return maybe;
}

template <typename>
constexpr inline bool is_optional_impl = false;
template <typename T>
Expand Down
23 changes: 23 additions & 0 deletions tests/monad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,26 @@ TEST_CASE("operator|") {
CHECK(val == Catch::Approx(4.61538));
}
}

TEST_CASE("rsl::maybe_error") {
SECTION("No error") {
CHECK(rsl::maybe_error(tl::expected<int, std::string>(42)) == std::nullopt);
CHECK(rsl::maybe_error(tl::expected<int, std::string>(1), tl::expected<int, std::string>(2),
tl::expected<int, std::string>(3), tl::expected<int, std::string>(4),
tl::expected<int, std::string>(5)) == std::nullopt);
}

SECTION("Errors") {
CHECK(rsl::maybe_error<std::string, int>(tl::unexpected<std::string>("oops")) ==
std::optional<std::string>("oops"));
CHECK(rsl::maybe_error(tl::expected<int, std::string>(tl::unexpect, "oops1"),
tl::expected<int, std::string>(tl::unexpect, "oops2"),
tl::expected<int, std::string>(tl::unexpect, "oops3")) ==
std::optional<std::string>("oops1"));
CHECK(rsl::maybe_error(tl::expected<int, std::string>(tl::unexpect, "oops1"),
tl::expected<int, std::string>(1337),
tl::expected<int, std::string>(tl::unexpect, "oops2"),
tl::expected<int, std::string>(tl::unexpect, "oops3")) ==
std::optional<std::string>("oops1"));
}
}

0 comments on commit 608dd6e

Please sign in to comment.