如何使用C ++ 20 std :: format?

Mar*_*ine 3 c++ printf cout string-formatting c++20

C ++ 20引入std::format。与printf或相比有什么优势std::cout?我如何使用它,有人给它举例?

eer*_*ika 19

与printf相比有什么优势

类型安全。对于 printf,程序员必须仔细地将格式说明符与参数类型匹配。如果他们犯了错误,程序的行为是未定义的。这是一个非常常见的错误来源,尤其是对于初学者。

公平地说,只要使用常量格式字符串,只要程序员记住/知道如何启用警告,体面的编译器就会诊断这些错误。无论如何,使用模板参数推导来自动选择格式化类型更方便、更安全。

此外,无法扩展 printf 以支持打印类类型。

或 std::cout

流操纵器非常麻烦和冗长,并且具有不一致的行为。一些操纵器是“粘性”的,影响所有后续插入,而其他操纵器仅影响单个插入。

iostream API 中的格式和参数之间缺乏分离可以说是更难理解(预期的)结果。

我该如何使用它

要么等待您的编译器/标准库实现支持它。或者,如果不想等待,请改用原始的非标准版本。然后按照文档进行操作。

规范性规范是C++ 标准。还有一些网站提供了标准,包括以更方便的格式包含这个库。另一个很好的信息来源是标准提案。非标准版本的 repo(在上一段中链接)也有大量的文档,尽管与标准中的内容会有差异。

有人举个例子吗?

给你(改编自 libfmt 的文档):

std::string s = std::format("I'd rather be {1} than {0}.", "right", "happy");
Run Code Online (Sandbox Code Playgroud)

  • “iostream API 中格式和参数之间缺乏分离”也阻碍了支持多种语言的努力(例如,名词和动词可能交换位置)。 (5认同)
  • @Jeff:顺便说一句,这个问题很久以前就解决了。在制作可能需要国际化的消息时,切勿执行类似“format("The {} {} is bad", color, Furniture)”之类的操作,因为它在英语中是“red table”,但在法语中是不同顺序的“table rouge”。相反,选择类似“格式(“P1 指定的颜色 P2 的对象已损坏(P1={},P2={})”,家具,颜色)”。唯一需要更改的特定于语言的位是完全独立的格式字符串,可以针对每种语言进行定制。否则,顺序与变量无关。 (3认同)

pax*_*blo 5

C ++ 20 std::format主要只是包含fmt许多人已经在使用的库(我们将其用作spdlog日志记录框架的一部分)。

因此,如果您想使用它,就可以下载了fmt

至于优点,它具有流的类型安全性,但没有冗长性(legacy-C printf是简洁的,但既不是类型安全的也不是可扩展的)。这是我们自己的代码库中的一个示例(略作修改):

std::string idStr = fmt::format("prefix.{:05d}.suffix", id);
Run Code Online (Sandbox Code Playgroud)

这将另外需要相当比简明标准C ++:

std::string idStr;
{
    std::stringstream ss;
    ss << "prefix." << std::setfill('0') << std::setw(5) << id << ".suffix";
    idStr = ss.str();
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,格式版本还可以更好地传达输出的外观。 (4认同)
  • @uneven_mark 旁注:标准 C++ 的另一个从(标准的)概念中被弃用的功能是从字符串文字到非常量 `char*` 的隐式转换。该转换在 C++11 中已被删除。 (2认同)