fix case of variant which is valueless by exception (#3347)

Co-authored-by: theomegacarrot <theomegacarrot@gmail.com>
This commit is contained in:
TheOmegaCarrot 2023-03-18 10:07:06 -04:00 committed by GitHub
parent e1720c0e51
commit d8e1c4265a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 5 deletions

View File

@ -218,11 +218,15 @@ struct formatter<
auto out = ctx.out(); auto out = ctx.out();
out = detail::write<Char>(out, "variant("); out = detail::write<Char>(out, "variant(");
std::visit( try {
[&](const auto& v) { std::visit(
out = detail::write_variant_alternative<Char>(out, v); [&](const auto& v) {
}, out = detail::write_variant_alternative<Char>(out, v);
value); },
value);
} catch (const std::bad_variant_access&) {
detail::write<Char>(out, "valueless by exception");
}
*out++ = ')'; *out++ = ')';
return out; return out;
} }

View File

@ -7,6 +7,7 @@
#include "fmt/std.h" #include "fmt/std.h"
#include <stdexcept>
#include <string> #include <string>
#include <vector> #include <vector>
@ -95,6 +96,26 @@ TEST(std_test, optional) {
#endif #endif
} }
struct throws_on_move {
throws_on_move() = default;
[[noreturn]] throws_on_move(throws_on_move&&) {
throw std::runtime_error("Thrown by throws_on_move");
}
throws_on_move(const throws_on_move&) = default;
};
namespace fmt {
template <> struct formatter<throws_on_move> : formatter<string_view> {
auto format(const throws_on_move&, format_context& ctx) const
-> decltype(ctx.out()) {
string_view str("<throws_on_move>");
return formatter<string_view>::format(str, ctx);
}
};
} // namespace fmt
TEST(std_test, variant) { TEST(std_test, variant) {
#ifdef __cpp_lib_variant #ifdef __cpp_lib_variant
EXPECT_EQ(fmt::format("{}", std::monostate{}), "monostate"); EXPECT_EQ(fmt::format("{}", std::monostate{}), "monostate");
@ -126,6 +147,18 @@ TEST(std_test, variant) {
volatile int i = 42; // Test compile error before GCC 11 described in #3068. volatile int i = 42; // Test compile error before GCC 11 described in #3068.
EXPECT_EQ(fmt::format("{}", i), "42"); EXPECT_EQ(fmt::format("{}", i), "42");
std::variant<std::monostate, throws_on_move> v6;
try {
throws_on_move thrower;
v6.emplace<throws_on_move>(std::move(thrower));
} catch (const std::runtime_error&) {
}
// v6 is now valueless by exception
EXPECT_EQ(fmt::format("{}", v6), "variant(valueless by exception)");
#endif #endif
} }