Home > Enterprise >  How can I wrap std::format() with my own template function?
How can I wrap std::format() with my own template function?

Time:06-29

Note: this question uses C 20, and I'm using Visual Studio 2022 (v17.2.2).

I would like to create a template function wrapper to allow me to use std::format style logging. The wrapper function will eventually do some other non-format related stuff that is not important here.

Refer to the code below. Note that Log1() works fine, but feels clunky to use. Log2() is ok, but using std::vformat() loses compile-time checking of log format strings.

What I really want to do is Log3(). Problem is that Visual Studio (v17.2.2) doesn't like this.

Is there any way I can get this to work (without macros)?

#include <iostream>
#include <format>
#include <string_view>
 
// works fine:  usage is clunky
auto Log1(std::string_view sv)
{
    std::cout << sv;
}
 
// works, but fmt string is checked at runtime - not compile time
template<typename... Args>
auto Log2(std::string_view fmt, Args&&... args)
{
    std::cout << std::vformat(fmt, std::make_format_args(args...));
}
 
// this doesn't work
template<typename... Args>
auto Log3(std::string_view fmt, Args&&... args)
{
    std::cout << std::format(fmt, std::forward<Args>(args)...);
}
 
int main()
{
    Log1(std::format("Hello, {}\n", "world!")); // ok - clunky
    Log2("Hello, {}\n", "world!");              // ok - no compile time checking of fmt string
    Log2("Hello, {:s}\n", 42);                  // ok - throws at runtime
    Log3("Hello, {}\n", "world!");              // ERROR:  doesn't compile
    return 0;
}

CodePudding user response:

You need P2508 (my paper) to land, which exposes the currently exposition-only type std::basic-format-string<charT, Args...>, which will allow you to write:

template<typename... Args>
auto Log3(std::format_string<Args...> fmt, Args&&... args)

Until then, you can just be naughty and use the MSVC implementation's internal helper for this, with understanding that they can rename this type at will at any point.

template<typename... Args>
auto Log3(std::_Fmt_string<Args...> fmt, Args&&... args) 
  • Related