diff --git a/nano/lib/logging.hpp b/nano/lib/logging.hpp index dbb986f88e..e9f8d412c4 100644 --- a/nano/lib/logging.hpp +++ b/nano/lib/logging.hpp @@ -9,6 +9,7 @@ #include #include +#include #include namespace nano::log @@ -146,12 +147,7 @@ class logger final auto logger = get_logger (type); if (logger.should_log (spdlog::level::trace)) { - std::stringstream ss; - - nano::object_stream obs{ ss }; - (obs.write (args.name, args.value), ...); - - logger.trace ("\"{}\" {}", to_string (detail), ss.str ()); + logger.trace ("\"{}\" {}", to_string (detail), nano::object_stream_formatter{ std::forward (args)... }); } } diff --git a/nano/lib/object_stream.hpp b/nano/lib/object_stream.hpp index 60ee70408d..a7554657d0 100644 --- a/nano/lib/object_stream.hpp +++ b/nano/lib/object_stream.hpp @@ -8,6 +8,7 @@ #include #include +#include #include namespace nano @@ -44,16 +45,14 @@ class array_stream; */ template -concept object_streamable = requires (T const & obj, object_stream & obs) -{ +concept object_streamable = requires (T const & obj, object_stream & obs) { { obj (obs) }; }; template -concept array_streamable = requires (T const & obj, array_stream & ars) -{ +concept array_streamable = requires (T const & obj, array_stream & ars) { { obj (ars) }; @@ -180,8 +179,39 @@ class root_object_stream : private object_stream_base void write (Value const & value); }; +/** + * Wraps `Args &&... args` and provides a `<< (std::ostream &, ...)` operator that writes the arguments to the stream in a lazy manner. + */ +template +struct object_stream_formatter +{ + std::tuple args; + + explicit object_stream_formatter (Args &&... args) : + args{ std::forward (args)... } + { + } + + friend std::ostream & operator<< (std::ostream & os, object_stream_formatter const & self) + { + object_stream obs{ os }; + std::apply ([&obs] (auto &&... args) { + ((obs.write (args.name, args.value)), ...); + }, + self.args); + return os; + } +}; + +// Needed for fmt formatting, uses the ostream operator under the hood +template +auto format_as (object_stream_formatter const & val) +{ + return fmt::streamed (val); +} + /* - * Impl + * implementation */ template