<格式> 在里面 视觉 导播室 2019版 16.10

C++ 20向标准库添加了一个新的文本格式设置工具,主要用于替换 snprintf 以及拥有快速和类型安全界面的朋友。标准化图书馆建立在现有图书馆的基础上 {fmt} 图书馆,所以图书馆的使用者会有宾至如归的感觉。

null

在深入研究 std::format 我要感谢维克托·兹维罗维奇、埃尔纳尔·达克肖夫、凯西·卡特和米斯科,他们都是 大量捐款 这就是为什么我们能这么快完成它的原因。

概述

开始使用 <format> 您只需要使用VisualStudio2019版本16.10或更高版本,并且需要使用 /std:c++latest . 您可以获得最新的visualstudio预览 在这里 .

最简单最常用的使用方法 <format> 是呼叫:

template<class... Args>
string format(string_view fmt, const Args&... args);

fmt 是格式字符串 args 是你想要格式化的东西。格式字符串由一些文本组成,其中穿插着大括号分隔的替换字段。例如: "Format arguments: {} {}!" 用于格式化两个参数的格式字符串。每个替换字段对应于传递的下一个参数。所以呢 std::format("Format arguments {} {}!", 2, 1) 会产生弦 "Format arguments 2 1!"

例如,格式字符串还可以包含带编号的替换字段 "Format arguments {1} {0}!" . 这些引用传入的编号参数,从零开始。编号和未编号(自动)替换字段不能在同一格式字符串中混合。

您可以使用各种各样的修饰符来更改特定参数的格式。这些被称为“格式说明符”,在替换字段中指定如下: std::format("{:<specifiers>}", <arg>) . 让我们看一个例子,其中包含了所有的一个。

std::format("{::cat_face:^+#12.4La}", 4.f);

返回字符串 “:cat_face:+1.0000p+2:cat_face:” (将此字符串打印到Windows上的控制台可能有点困难)。让我们看一下上面字符串的每个组成部分都说明了什么 std::format 去做。首先我们有 “:cat_face:^” 格式说明符的“填充和对齐”部分,表示我们希望输出中心对齐并填充cat emojis。接下来是 “+” ,这意味着无论发生什么,我们都需要一个符号字符(默认值为 “-” 只打印 “-” 符号表示负数,也可以用空格表示负号或空格)。之后我们指定 “#” ,意思是“替代形式”。对于浮点数,替代形式会导致格式始终插入小数点。接下来我们具体说明 “12.4” 获得12的宽度和4的精度。这意味着格式将使用“填充”和“对齐”设置,以确保我们的输出是至少12个字符宽和浮点数本身将打印到4位精度。下一个 “L” 说明符使format使用特定于区域设置的格式来打印诸如小数分隔符之类的内容。最后 “a” 使输出为hexfloat格式。有关可能的格式规范的更多详细信息,请访问 CPP参考 .

对于宽度和精度说明符,可以引用格式参数,而不是使用如下文字值:

std::format("{0:{1}.{2}}", 4.2f, 4, 5);

这将导致宽度为4,精度为5。混合自动和手动索引的规则(不执行此操作)仍然适用,但您可以使用自动索引来引用宽度和精度,如中所示:

std::format("{:{}.{}}", 4.2f, 4, 5);

自动索引的赋值是从左到右进行的,因此上述两个例子是等价的。

性能

一般来说 std::format 表现应该和 fmt::format snprintf 如果你用 /utf-8 . 如果你不使用 /utf-8 选项,则性能可能会显著降低,因为我们需要检索系统区域设置以正确解析格式字符串。在将来的版本中,我们正在努力提高这种情况下的性能,但我们建议您使用 /utf-8 为了最好的体验。

Unicode码

std::format 不在不同的文本编码之间进行任何转码,但是它知道“执行字符集”并使用它来解释格式字符串。的版本 std::format 采取广泛的( wchar_t )格式字符串是 总是 解释为UTF-16 std::format 如果我们检测到 /utf-8 (或 /execution-charset:utf-8 )选项。否则,我们将格式字符串解释为在活动系统代码页中编码。这意味着,如果使用非UTF-8执行字符集编译代码,它可能无法在具有不同系统代码页设置的系统上正确运行。还有一个 重要的 计算系统代码页的性能成本,因此为了获得最佳性能,我们建议您使用 /utf-8 . 我们正在努力提高未来版本中非UTF执行字符集格式的性能。

在处理字符串的宽度和精度规范时,Unicode也起作用。当我们将格式字符串解释为UTF-8或UTF-16时,我们计算字符串的“估计宽度”,并考虑每个代码点大小的粗略估计。如果我们将格式字符串解释为非Unicode编码,我们只需将宽度估计为字符串中的代码单元(而不是代码点)的数量。在未来的版本中,我们将为Unicode编码的宽度计算添加grapheme集群化。

区域设置

当我们总是分析 设置字符串格式 根据上述规则,可以自定义用于小数分隔符位置之类的区域设置。默认情况下不使用区域设置。如果你使用 L 说明符,则可以使用特定于语言环境的格式。默认情况下,它是默认值返回的当前全局区域设置 std::locale 但是,每个格式化函数都有一个版本,允许您传入自己的 std::locale 对象来重写该行为。

今后的工作

在接下来的几个visualstudio版本中,我们将改进 std::format ,并修复错误。另外,C++ 23可能会添加编译时格式检查来格式化文字,我们可以在2023之前实现它(对于C++中的23个伟大的代码,不要依赖于捕获)。 std::format_errors 来自无效格式字符串!)。C++ 23也会对定义的定义做一个小小的修改。 std::vformat_to std::format_to 这减少了代码大小,但可以观察到,为了向前兼容性,请确保任何自定义格式化程序都能与所有输出迭代器一起工作。有关这些更改的更多信息,请参阅 p2216r3页 . C++ 5月23日也带来了类似的功能 std::print 以及处理Unicode文本的更好方法。

与{fmt}的区别(并非详尽无遗)

对于那些熟悉 {fmt} ,一个与标准化版本的库不同之处的快速列表:

  • 不支持命名参数。
  • 没有像这样的其他格式化函数 fmt::print fmt::printf 支持。
  • 编译时不检查格式字符串
  • 不支持使用 std::ostream& operator<<(std::ostream&, const T&) 超载
  • 某些格式说明符的行为略有不同(例如 void* ,并允许无符号类型使用符号说明符)

给我们反馈

在您自己的代码中尝试格式化,并在我们的 out GitHub问题跟踪程序 .

© 版权声明
THE END
喜欢就支持一下吧,技术咨询可以联系QQ407933975
点赞0 分享