Skip to content

Commit 49ff8ed

Browse files
authored
Merge pull request #750 from elbeno/fmt-enum-formatting
✨ Allow fmt formatter to format runtime enum values
2 parents e2dbd2d + 5c79744 commit 49ff8ed

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

include/log/fmt/logger.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ namespace fmt_detail {
2424
using namespace std::string_view_literals;
2525
constexpr std::array level_text{"MAX"sv, "FATAL"sv, "ERROR"sv, "WARN"sv,
2626
"INFO"sv, "USER1"sv, "USER2"sv, "TRACE"sv};
27+
28+
template <typename T> auto decay_enum_value(T const &t) -> decltype(auto) {
29+
if constexpr (requires { format_as(t); } or not std::is_enum_v<T>) {
30+
return (t);
31+
} else {
32+
return stdx::to_underlying(t);
33+
}
34+
}
2735
} // namespace fmt_detail
2836

2937
template <logging::level L>
@@ -55,7 +63,8 @@ template <typename TDestinations> struct log_handler {
5563
constexpr auto fmtstr =
5664
std::string_view{decltype(fr.str)::value};
5765
fr.args.apply([&](auto const &...args) {
58-
::fmt::format_to(out, fmtstr, args...);
66+
::fmt::format_to(out, fmtstr,
67+
fmt_detail::decay_enum_value(args)...);
5968
});
6069
*out = '\n';
6170
},

test/log/fmt_logger.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,35 @@ TEST_CASE("logging doesn't use dynamic memory", "[fmt_logger]") {
5353
}
5454

5555
TEST_CASE("logging behavior can be properly overridden", "[fmt_logger]") {
56-
buffer.reserve(100);
5756
buffer.clear();
5857
log_test_override();
5958
CAPTURE(buffer);
6059
CHECK(buffer.substr(buffer.size() - std::size("Hello")) == "Hello\n");
6160
}
6261

62+
namespace detail {
63+
enum struct E1 { A, B, C };
64+
enum struct E2 { A, B, C };
65+
[[maybe_unused]] static auto format_as(E2) { return 42; }
66+
} // namespace detail
67+
68+
TEST_CASE("fmt logger can deal with runtime enum values", "[fmt_logger]") {
69+
buffer.clear();
70+
auto x = detail::E1::A;
71+
CIB_INFO("Hello {}", x);
72+
CAPTURE(buffer);
73+
CHECK(buffer.substr(buffer.size() - std::size("Hello 0")) == "Hello 0\n");
74+
}
75+
76+
TEST_CASE("fmt logger can deal with formattable runtime enum values",
77+
"[fmt_logger]") {
78+
buffer.clear();
79+
auto x = detail::E2::A;
80+
CIB_INFO("Hello {}", x);
81+
CAPTURE(buffer);
82+
CHECK(buffer.substr(buffer.size() - std::size("Hello 42")) == "Hello 42\n");
83+
}
84+
6385
TEST_CASE("log levels are properly represented", "[fmt_logger]") {
6486
{
6587
std::string level{};

0 commit comments

Comments
 (0)