diff --git a/include/fmt/core.h b/include/fmt/core.h index 966033fe..2323585b 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -286,8 +286,10 @@ struct monostate { #endif // This is defined in core.h instead of format.h to avoid injecting in std. +// It is a template to avoid undesirable implicit conversions to std::byte. #ifdef __cpp_lib_byte -inline auto format_as(std::byte b) -> unsigned char { +template ::value)> +inline auto format_as(T b) -> unsigned char { return static_cast(b); } #endif diff --git a/test/core-test.cc b/test/core-test.cc index dbb19017..22175dab 100644 --- a/test/core-test.cc +++ b/test/core-test.cc @@ -831,3 +831,28 @@ TEST(core_test, has_const_formatter) { TEST(core_test, format_nonconst) { EXPECT_EQ(fmt::format("{}", nonconst_formattable()), "test"); } + +struct its_a_trap { + template operator T() const { + auto v = T(); + v.x = 42; + return v; + } +}; + +FMT_BEGIN_NAMESPACE +template <> struct formatter { + auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + auto format(its_a_trap, format_context& ctx) const -> decltype(ctx.out()) { + auto s = string_view("42"); + return std::copy(s.begin(), s.end(), ctx.out()); + } +}; +FMT_END_NAMESPACE + +TEST(core_test, trappy_conversion) { + EXPECT_EQ(fmt::format("{}", its_a_trap()), "42"); +}