diff --git a/include/etl/expected.h b/include/etl/expected.h index a8335247..829c4247 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -604,6 +604,38 @@ namespace etl return etl::move(etl::get(storage)); } + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) const& + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return error(); + } + } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) && + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return etl::move(error()); + } + } + //******************************************* /// Swap with another etl::expected. //******************************************* @@ -661,6 +693,22 @@ namespace etl { return etl::get(storage); } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + error_type error_or(const G& default_error) const + { + if (has_value()) + { + return static_cast(default_error); + } + else + { + return error(); + } + } #endif //******************************************* @@ -725,6 +773,39 @@ namespace etl } #endif + //******************************************* + /// Returns a pointer to the value if has_value(), otherwise returns nullptr. + /// Allows expected to be used as a range of 0 or 1 elements. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 value_type* begin() ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) : ETL_NULLPTR; + } + + //******************************************* + /// Returns a pointer past the value if has_value(), otherwise returns nullptr. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 value_type* end() ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) + 1 : ETL_NULLPTR; + } + + //******************************************* + /// Returns a const pointer to the value if has_value(), otherwise returns nullptr. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 const value_type* begin() const ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) : ETL_NULLPTR; + } + + //******************************************* + /// Returns a const pointer past the value if has_value(), otherwise returns nullptr. + //******************************************* + ETL_NODISCARD ETL_CONSTEXPR14 const value_type* end() const ETL_NOEXCEPT + { + return has_value() ? &etl::get(storage) + 1 : ETL_NULLPTR; + } + #if ETL_USING_CPP11 template ::type>::type> auto transform(F&& f) & -> expected @@ -1065,6 +1146,38 @@ namespace etl { return etl::move(etl::get(storage)); } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) const& + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return error(); + } + } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + ETL_NODISCARD ETL_CONSTEXPR14 etl::enable_if_t::value, error_type> error_or(G&& default_error) && + { + if (has_value()) + { + return static_cast(etl::forward(default_error)); + } + else + { + return etl::move(error()); + } + } #else //******************************************* /// Returns the error @@ -1074,6 +1187,22 @@ namespace etl { return etl::get(storage); } + + //******************************************* + /// Get the error or a default value. + //******************************************* + template + error_type error_or(const G& default_error) const + { + if (has_value()) + { + return static_cast(default_error); + } + else + { + return error(); + } + } #endif //******************************************* diff --git a/test/test_expected.cpp b/test/test_expected.cpp index 024ecf47..a28e2f54 100644 --- a/test/test_expected.cpp +++ b/test/test_expected.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include "etl/expected.h" #include "etl/type_traits.h" +#include #include #include @@ -1477,5 +1478,143 @@ namespace auto with_error_type_check = check_expected_type_helper(unexpected_out); CHECK_TRUE(with_error_type_check); } + + //************************************************************************* + TEST(test_begin_end_with_value) + { + etl::expected exp(std::string("hello")); + + CHECK_TRUE(exp.begin() != exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 1); + CHECK_EQUAL(*exp.begin(), std::string("hello")); + } + + //************************************************************************* + TEST(test_begin_end_with_error) + { + etl::expected exp(etl::unexpected(Error("err"))); + + CHECK_TRUE(exp.begin() == exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 0); + } + + //************************************************************************* + TEST(test_begin_end_const_with_value) + { + const etl::expected exp(std::string("world")); + + CHECK_TRUE(exp.begin() != exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 1); + CHECK_EQUAL(*exp.begin(), std::string("world")); + } + + //************************************************************************* + TEST(test_begin_end_const_with_error) + { + const etl::expected exp(etl::unexpected(Error("err"))); + + CHECK_TRUE(exp.begin() == exp.end()); + CHECK_EQUAL(std::distance(exp.begin(), exp.end()), 0); + } + + //************************************************************************* + TEST(test_range_for_with_value) + { + etl::expected exp(42); + + int count = 0; + int sum = 0; + for (auto& v : exp) + { + ++count; + sum += v; + } + + CHECK_EQUAL(1, count); + CHECK_EQUAL(42, sum); + } + + //************************************************************************* + TEST(test_range_for_with_error) + { + etl::expected exp(etl::unexpected(Error("err"))); + + int count = 0; + for (auto& v : exp) + { + (void)v; + ++count; + } + + CHECK_EQUAL(0, count); + } + + //************************************************************************* + TEST(test_error_or_with_value) + { + etl::expected exp(42); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_with_error) + { + etl::expected exp(etl::unexpected(Error("real_error"))); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } + + //************************************************************************* + TEST(test_error_or_const_with_value) + { + const etl::expected exp(42); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_const_with_error) + { + const etl::expected exp(etl::unexpected(Error("real_error"))); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } + + //************************************************************************* + TEST(test_error_or_rvalue_with_value) + { + Error result = etl::expected(42).error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_rvalue_with_error) + { + Error result = etl::expected(etl::unexpected(Error("real_error"))).error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } + + //************************************************************************* + TEST(test_error_or_void_value_with_value) + { + etl::expected exp; + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("default", result.e); + } + + //************************************************************************* + TEST(test_error_or_void_value_with_error) + { + etl::expected exp(etl::unexpected(Error("real_error"))); + + Error result = exp.error_or(Error("default")); + CHECK_EQUAL("real_error", result.e); + } } } // namespace