如何用我自己的模板函数包装 std::format() ?

mar*_*rkv 2 c++ variadic-templates c++20 fmt

注意:这个问题使用C++20,我使用的是Visual Studio 2022 (v17.2.2)。

我想创建一个模板函数包装器以允许我使用 std::format 样式日志记录。包装函数最终将执行一些其他与格式无关的操作,这些操作在这里并不重要。

请参考下面的代码。请注意,Log1()工作正常,但使用起来感觉很笨拙。 Log2()没问题,但使用std::vformat()会丢失日志格式字符串的编译时检查。

我真正想做的是Log3()。问题是 Visual Studio (v17.2.2) 不喜欢这样。

有什么方法可以让它工作(没有宏)?

#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;
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 7

你需要P2508(我的论文)来登陆,它公开了当前仅展示的类型std::basic-format-string<charT, Args...>,这将允许你编写:

template<typename... Args>
auto Log3(std::format_string<Args...> fmt, Args&&... args)
Run Code Online (Sandbox Code Playgroud)

在那之前,您可以顽皮地使用 MSVC 实现的内部帮助程序来实现此目的,并了解它们可以随时重命名此类型。

template<typename... Args>
auto Log3(std::_Fmt_string<Args...> fmt, Args&&... args) 
Run Code Online (Sandbox Code Playgroud)