From 7b3684b54eb38f0ad4c18359e5b3f6780492fccd Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Mon, 17 Dec 2018 18:24:13 +0900 Subject: [PATCH] add and_other and or_other to toml::result effectively same as Rust's std::Result::and and or. --- tests/test_result.cpp | 30 ++++++++++++++++++++++++++++++ toml/result.hpp | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/tests/test_result.cpp b/tests/test_result.cpp index 5d7bcdd..4832c5d 100644 --- a/tests/test_result.cpp +++ b/tests/test_result.cpp @@ -409,3 +409,33 @@ BOOST_AUTO_TEST_CASE(test_or_else) BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge"); } } + +BOOST_AUTO_TEST_CASE(test_and_or_other) +{ + { + const toml::result r1(toml::ok(42)); + const toml::result r2(toml::err("foo")); + + BOOST_CHECK_EQUAL(r1, r1.or_other(r2)); + BOOST_CHECK_EQUAL(r2, r1.and_other(r2)); + BOOST_CHECK_EQUAL(42, r1.or_other(r2).unwrap()); + BOOST_CHECK_EQUAL("foo", r1.and_other(r2).unwrap_err()); + } + { + auto r1_gen = []() -> toml::result { + return toml::ok(42); + }; + auto r2_gen = []() -> toml::result { + return toml::err("foo"); + }; + const auto r3 = r1_gen(); + const auto r4 = r2_gen(); + + BOOST_CHECK_EQUAL(r3, r1_gen().or_other (r2_gen())); + BOOST_CHECK_EQUAL(r4, r1_gen().and_other(r2_gen())); + BOOST_CHECK_EQUAL(42, r1_gen().or_other (r2_gen()).unwrap()); + BOOST_CHECK_EQUAL("foo", r1_gen().and_other(r2_gen()).unwrap_err()); + } +} + + diff --git a/toml/result.hpp b/toml/result.hpp index 3b13acd..1d2e596 100644 --- a/toml/result.hpp +++ b/toml/result.hpp @@ -592,6 +592,26 @@ struct result return ok(std::move(this->as_ok())); } + // if *this is error, returns *this. otherwise, returns other. + result and_other(const result& other) const& + { + return this->is_err() ? *this : other; + } + result and_other(result&& other) && + { + return this->is_err() ? std::move(*this) : std::move(other); + } + + // if *this is okay, returns *this. otherwise, returns other. + result or_other(const result& other) const& + { + return this->is_ok() ? *this : other; + } + result or_other(result&& other) && + { + return this->is_ok() ? std::move(*this) : std::move(other); + } + void swap(result& other) { result tmp(std::move(*this)); @@ -638,5 +658,22 @@ void swap(result& lhs, result& rhs) return; } +// this might be confusing because it eagerly evaluated, while in the other +// cases operator && and || are short-circuited. +// +// template +// inline result +// operator&&(const result& lhs, const result& rhs) noexcept +// { +// return lhs.is_ok() ? rhs : lhs; +// } +// +// template +// inline result +// operator||(const result& lhs, const result& rhs) noexcept +// { +// return lhs.is_ok() ? lhs : rhs; +// } + } // toml11 #endif// TOML11_RESULT_H