modernize-use-std-print

将对 printffprintfabsl::PrintFabsl::FPrintf 的调用转换为等效的 C++23 的 std::printstd::println 调用(根据需要),并相应地修改格式字符串。被替换和替换函数可以通过配置选项自定义。每个作为对 std::string::c_str()std::string::data() 的调用结果的实参将被删除现在不必要的调用,类似于 readability-redundant-string-cstr 检查。

换句话说,它将以下代码行

fprintf(stderr, "The %s is %3d\n", description.c_str(), value);

转换为

std::println(stderr, "The {} is {:3}", description, value);

如果 ReplacementPrintFunctionReplacementPrintlnFunction 选项保留其默认值或设置为其默认值,则此检查仅在使用 -std=c++23 或更高版本时启用。

<inttypes.h> 中以 PRI__PRI 开头的宏将被展开,转义将被处理,并且相邻的字符串将被连接起来以形成一个单一的 StringLiteral,然后格式字符串将被转换。在格式字符串中使用任何其他宏将导致发出警告消息,并且不会执行任何转换。转换后的格式字符串将始终是单个字符串文字。

该检查做得还不错,但并不完美。特别是

如果转换不完整或不安全,则整个调用将保持不变。

如果调用被认为适合转换,则

选项

StrictMode

当为 true 时,检查将在从像 printf 这样的可变参数函数转换时添加强制转换,并将有符号或无符号整型类型(包括来自 <cstdint>ptrdiff_tsize_tssize_t 的定长整型类型)打印为相反的符号性,以确保输出与 printf 的输出匹配。这在从非可变参数函数转换时不适用,例如 absl::PrintFfmt::printf。例如,当 StrictMode 启用时

int i = -42;
unsigned int u = 0xffffffff;
printf("%u %d\n", i, u);

将被转换为

std::print("{} {}\n", static_cast<unsigned int>(i), static_cast<int>(u));

以确保输出将继续是 -42 的无符号表示和 0xffffffff 的有符号表示(通常分别为 4294967254-1)。当为 false(默认值)时,这些强制转换将不会被添加,这可能会导致输出发生变化。

PrintfLikeFunctions

要替换的(完全限定的)函数名列表(以分号分隔),要求第一个参数包含 printf 样式的格式字符串,并且要格式化的实参紧随其后。支持限定的成员函数名,但替换函数名必须是不限定的。如果既没有设置此选项,也没有设置 FprintfLikeFunctions,那么此选项的默认值为 printf; absl::PrintF,否则为空。

FprintfLikeFunctions

要替换的(完全限定的)函数名列表(以分号分隔),要求第一个参数被保留,第二个参数包含 printf 样式的格式字符串,并且要格式化的实参紧随其后。支持限定的成员函数名,但替换函数名必须是不限定的。如果既没有设置此选项,也没有设置 PrintfLikeFunctions,那么此选项的默认值为 fprintf; absl::FPrintF,否则为空。

ReplacementPrintFunction

在转换期间将用于替换 printffprintf 等的函数,而不是默认的 std::print,当原始格式字符串不以 \n 结尾时。预期该函数提供与 std::print 兼容的接口。一个合适的候选函数是 fmt::print

ReplacementPrintlnFunction

在转换期间将用于替换 printffprintf 等的函数,而不是默认的 std::println,当原始格式字符串以 \n 结尾时。预期该函数提供与 std::println 兼容的接口。一个合适的候选函数是 fmt::println

PrintHeader

必须包含的头文件,用于 ReplacementPrintFunction 的声明,以便可以添加 #include 指令(如果需要)。如果 ReplacementPrintFunctionstd::print,那么此选项的默认值为 <print>,否则此选项的默认值为 nothing,并且不会添加 #include 指令。