fix: allow overlapping types in Expected (#5218)

For example, Expected<std::uint32_t, Json::Value>, will now build even though there is animplicit conversion from unsigned int to Json::Value.
This commit is contained in:
Mayukha Vadari
2024-12-16 15:00:14 -08:00
committed by GitHub
parent 5cd72f2431
commit bcbfb04992
2 changed files with 27 additions and 2 deletions

View File

@@ -137,13 +137,15 @@ class [[nodiscard]] Expected
public:
template <typename U>
requires std::convertible_to<U, T>
constexpr Expected(U&& r) : Base(T(std::forward<U>(r)))
constexpr Expected(U&& r)
: Base(boost::outcome_v2::in_place_type_t<T>{}, std::forward<U>(r))
{
}
template <typename U>
requires std::convertible_to<U, E> && (!std::is_reference_v<U>)
constexpr Expected(Unexpected<U> e) : Base(E(std::move(e.value())))
constexpr Expected(Unexpected<U> e)
: Base(boost::outcome_v2::in_place_type_t<E>{}, std::move(e.value()))
{
}

View File

@@ -84,6 +84,29 @@ struct Expected_test : beast::unit_test::suite
}
BEAST_EXPECT(throwOccurred);
}
// Test non-error overlapping type construction.
{
auto expected = []() -> Expected<std::uint32_t, std::uint16_t> {
return 1;
}();
BEAST_EXPECT(expected);
BEAST_EXPECT(expected.has_value());
BEAST_EXPECT(expected.value() == 1);
BEAST_EXPECT(*expected == 1);
bool throwOccurred = false;
try
{
// There's no error, so should throw.
[[maybe_unused]] std::uint16_t const t = expected.error();
}
catch (std::runtime_error const& e)
{
BEAST_EXPECT(e.what() == std::string("bad expected access"));
throwOccurred = true;
}
BEAST_EXPECT(throwOccurred);
}
// Test error construction from rvalue.
{
auto const expected = []() -> Expected<std::string, TER> {