第一个参数std::format
必须在编译时知道,因为格式字符串被指定为只能构造为常量表达式。目的是保证无效格式字符串的编译时错误。
fmt_str
是一个函数参数,因此它的值永远不是编译时常量。
您可以使用std::vformat相反,但它不会对格式字符串执行编译时检查,而是将其延迟到运行时(抛出std::format_error
错误时):
puts(std::vformat(fmt_str, std::make_format_args(args...)).c_str());
如果你不需要fmt_str
为了与运行时相关,您可以将其作为模板参数传递。不幸的是,目前这还不是那么简单,因为std::string
and std::string_view
不能用于此目的,并且字符串文字不能直接通过const char*
非类型模板参数。
因此,您可能希望创建自己的结构固定长度字符串类型,该类型可以用作非类型模板参数,例如这是该用例的一个非常小的版本,您可能希望根据您的需求进行扩展:
template<std::size_t N>
struct fixed_string {
char str[N];
constexpr fixed_string(const char (&str_)[N]) noexcept {
std::ranges::copy(str_, str);
}
};
template <fixed_string fmt_str, typename... Args>
void FormatString(Args&&... args)
{
puts(std::format(fmt_str.str, args...).c_str());
}
int main()
{
FormatString<"This is a {}.\n">("test");
return 0;
}
我假设 MSVC 还没有实现第一个参数的要求std::format
在以前的版本中可以构造为常量表达式。
该要求是在 C++20 之后为 C++23 添加的,但如果理解正确,也可以作为缺陷报告追溯适用于 C++20,按照论文中列出的投票进行here其中包含相关更改。