Using fmtlib & source_location to create variadic-template-based logging function

  c++, default-arguments, variadic-templates

I’d like to create a simple log function in C++ which prepend the code location to the log message. I’d like to avoid macros overall as well as the usage of __FILE__ & __LINE__.

Note that the format string is always a compile-time string, and I’d like to have a much computation as possible on compile time (the target machine is a small MCU).

I can use the C++20 source_location feature via experimental/source_location.
I can also use fmtlib.

I started off from this. Currently, I’ve got the following:

#include <fmt/format.h>
#include <experimental/source_location>

using source_location = std::experimental::source_location;

void vlog(fmt::string_view format, fmt::format_args args)
{
  fmt::vprint(format, args);
}

template <typename S, typename... Args>
void log(const S& format, const source_location& location, Args&&... args)
{
  vlog(format, fmt::make_args_checked<fmt::string_view, uint32_t, Args...>(format, location.file_name(), location.line(), args...));
}

#define MY_LOG(format, ...) log(FMT_STRING("{},{}, " format), source_location::current(), __VA_ARGS__)

int main() {
  MY_LOG("invalid squishiness: {}", 42);
}

Which yields correctly ./example.cpp,20, invalid squishiness: 42.

Looks to me like I’m pretty close. I think what’s left is to make the log function take a default argument for source_location (I understand that source_location::current() as a default arguement is a good practice). I’m getting the following error though:

:12:99: error: missing default argument on parameter ‘args’

Is this even possible to mix variadic templates and default arguments for parameters? If so, how?

Also, is there a way to prepend the "{},{}, " part to the compile-time format string to yield yet another compile-time string (to be used as format)?

Source: Windows Questions C++

LEAVE A COMMENT