Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion include/log/fmt/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ namespace fmt_detail {
using namespace std::string_view_literals;
constexpr std::array level_text{"MAX"sv, "FATAL"sv, "ERROR"sv, "WARN"sv,
"INFO"sv, "USER1"sv, "USER2"sv, "TRACE"sv};

template <typename T> auto decay_enum_value(T const &t) -> decltype(auto) {
if constexpr (requires { format_as(t); } or not std::is_enum_v<T>) {
return (t);
} else {
return stdx::to_underlying(t);
}
}
} // namespace fmt_detail

template <logging::level L>
Expand Down Expand Up @@ -55,7 +63,8 @@ template <typename TDestinations> struct log_handler {
constexpr auto fmtstr =
std::string_view{decltype(fr.str)::value};
fr.args.apply([&](auto const &...args) {
::fmt::format_to(out, fmtstr, args...);
::fmt::format_to(out, fmtstr,
fmt_detail::decay_enum_value(args)...);
});
*out = '\n';
},
Expand Down
24 changes: 23 additions & 1 deletion test/log/fmt_logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,35 @@ TEST_CASE("logging doesn't use dynamic memory", "[fmt_logger]") {
}

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

namespace detail {
enum struct E1 { A, B, C };
enum struct E2 { A, B, C };
[[maybe_unused]] static auto format_as(E2) { return 42; }
} // namespace detail

TEST_CASE("fmt logger can deal with runtime enum values", "[fmt_logger]") {
buffer.clear();
auto x = detail::E1::A;
CIB_INFO("Hello {}", x);
CAPTURE(buffer);
CHECK(buffer.substr(buffer.size() - std::size("Hello 0")) == "Hello 0\n");
}

TEST_CASE("fmt logger can deal with formattable runtime enum values",
"[fmt_logger]") {
buffer.clear();
auto x = detail::E2::A;
CIB_INFO("Hello {}", x);
CAPTURE(buffer);
CHECK(buffer.substr(buffer.size() - std::size("Hello 42")) == "Hello 42\n");
}

TEST_CASE("log levels are properly represented", "[fmt_logger]") {
{
std::string level{};
Expand Down
Loading