Skip to content

Commit

Permalink
fix case of variant which is valueless by exception (#3347)
Browse files Browse the repository at this point in the history
Co-authored-by: theomegacarrot <theomegacarrot@gmail.com>
  • Loading branch information
TheOmegaCarrot and theomegacarrot committed Mar 18, 2023
1 parent e1720c0 commit d8e1c42
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
14 changes: 9 additions & 5 deletions include/fmt/std.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,15 @@ struct formatter<
auto out = ctx.out();

out = detail::write<Char>(out, "variant(");
std::visit(
[&](const auto& v) {
out = detail::write_variant_alternative<Char>(out, v);
},
value);
try {
std::visit(
[&](const auto& v) {
out = detail::write_variant_alternative<Char>(out, v);
},
value);
} catch (const std::bad_variant_access&) {
detail::write<Char>(out, "valueless by exception");
}
*out++ = ')';
return out;
}
Expand Down
33 changes: 33 additions & 0 deletions test/std-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "fmt/std.h"

#include <stdexcept>
#include <string>
#include <vector>

Expand Down Expand Up @@ -95,6 +96,26 @@ TEST(std_test, optional) {
#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) {
#ifdef __cpp_lib_variant
EXPECT_EQ(fmt::format("{}", std::monostate{}), "monostate");
Expand Down Expand Up @@ -126,6 +147,18 @@ TEST(std_test, variant) {

volatile int i = 42; // Test compile error before GCC 11 described in #3068.
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
}

Expand Down

0 comments on commit d8e1c42

Please sign in to comment.