【问题标题】:How can I use C++20 std::format?如何使用 C++20 std::format?
【发布时间】:2020-03-20 07:19:57
【问题描述】:

C++20 引入了std::format。与printfstd::cout 相比有哪些优势? 我该如何使用它,有人举个例子吗?

【问题讨论】:

  • 您不清楚description on cppreference.com 的哪一部分,具体而言,您对该描述有疑问?
  • 你在这里并没有真正比较类似的东西。 std::format 履行std::ostringstreamstd::sprintf 的角色,而不是std::coutprintf

标签: c++ printf string-formatting c++20 fmt


【解决方案1】:

相比printf有什么优势

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

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

此外,没有办法扩展 printf 以支持打印类类型。

或 std::cout

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

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

我该如何使用它

要么等待你的编译器/标准库实现支持它。 或者,如果不想等待,请改用original non-standard version。然后按照文档进行操作。

标准规范是C++ standard。也有一些网站展示了该标准,包括这个库在一个更方便的format。另一个很好的信息来源是standard proposal。非标准版本的存储库(在上一段中链接)也有大量文档,尽管标准中的内容会有所不同。

有人举个例子吗?

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

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

【讨论】:

  • “iostream API 中的格式和参数之间缺乏分离”也阻碍了支持多种语言的努力(例如,名词和动词可能交换位置)。
  • @Jeff:顺便说一句,这个问题早就解决了。在发出可能需要国际化的消息时,永远不要做类似format("The {} {} is broken", color, furniture) 的事情,因为它在英语中是“红表”,但在法语中是不同顺序的table rouge。相反,请选择format("The object specified by P1, of color P2 is broken (P1={}, P2={})", furniture, color) 之类的东西。唯一需要更改的语言特定位是完全独立的格式字符串,可以针对每种语言进行定制。否则顺序与变量 stuff 无关。
【解决方案2】:

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

所以,如果你想使用它,你可以下载fmt

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

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

否则需要更少而不是简洁的标准C++:

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

【讨论】:

  • 对我来说,格式版本也能更好地传达输出的外观。
  • 实际上,可以想象(并编写)一个像ss &lt;&lt; "prefix." &lt;&lt; std::format(":05d") &lt;&lt; id &lt;&lt; ".suffix"; 这样的格式操纵器,有效地将下一个输出项的完整格式捆绑在一个操纵器中。 (不确定这是否可以静态类型安全(比 printf 更安全))。
  • 感谢 @uneven_mark 的编辑,如果 C++23 刚刚杀死 strstream 并自动将 std::sstreamstd::strstream 视为 std::stringstream,我会非常高兴。这将阻止我每次需要使用它时都必须查找它(当然,在我没有fmt 的情况下)。即使是现在,我也不确定我是否在此评论中将这些内容放在了正确的位置:-)
  • 我什至不知道std::strstream。我从未见过它被使用过,但显然在我开始编程之前它已经被弃用了。我什至不知道您可能会在第一次标准迭代中弃用某些东西。看着界面,我觉得我很幸运不用它。
  • @uneven_mark 旁注:标准 C++ 的另一个从概念(标准)中弃用的特性是从字符串文字到非常量 char* 的隐式转换。该转换在 C++11 中被删除。
猜你喜欢
  • 2020-12-22
  • 2022-08-15
  • 2021-08-11
  • 2020-09-24
  • 2020-11-26
  • 2020-12-22
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
相关资源
最近更新 更多