modernize-use-std-print

Converts calls to printf, fprintf, absl::PrintF and absl::FPrintf to equivalent calls to C++23’s std::print or std::println as appropriate, modifying the format string appropriately. The replaced and replacement functions can be customised by configuration options. Each argument that is the result of a call to std::string::c_str() and std::string::data() will have that now-unnecessary call removed in a similar manner to the readability-redundant-string-cstr check.

In other words, it turns lines like:

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

into:

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

If the ReplacementPrintFunction or ReplacementPrintlnFunction options are left, or assigned to their default values then this check is only enabled with -std=c++23 or later.

The check doesn’t do a bad job, but it’s not perfect. In particular:

If conversion would be incomplete or unsafe then the entire invocation will be left unchanged.

If the call is deemed suitable for conversion then:

Options

StrictMode

When true, the check will add casts when converting from variadic functions like printf and printing signed or unsigned integer types (including fixed-width integer types from <cstdint>, ptrdiff_t, size_t and ssize_t) as the opposite signedness to ensure that the output matches that of printf. This does not apply when converting from non-variadic functions such as absl::PrintF and fmt::printf. For example, with StrictMode enabled:

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

would be converted to:

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

to ensure that the output will continue to be the unsigned representation of -42 and the signed representation of 0xffffffff (often 4294967254 and -1 respectively.) When false (which is the default), these casts will not be added which may cause a change in the output.

PrintfLikeFunctions

A semicolon-separated list of (fully qualified) extra function names to replace, with the requirement that the first parameter contains the printf-style format string and the arguments to be formatted follow immediately afterwards. If neither this option nor FprintfLikeFunctions are set then the default value for this option is printf; absl::PrintF, otherwise it is empty.

FprintfLikeFunctions

A semicolon-separated list of (fully qualified) extra function names to replace, with the requirement that the first parameter is retained, the second parameter contains the printf-style format string and the arguments to be formatted follow immediately afterwards. If neither this option nor PrintfLikeFunctions are set then the default value for this option is fprintf; absl::FPrintF, otherwise it is empty.

ReplacementPrintFunction

The function that will be used to replace printf, fprintf etc. during conversion rather than the default std::print when the originalformat string does not end with \n. It is expected that the function provides an interface that is compatible with std::print. A suitable candidate would be fmt::print.

ReplacementPrintlnFunction

The function that will be used to replace printf, fprintf etc. during conversion rather than the default std::println when the original format string ends with \n. It is expected that the function provides an interface that is compatible with std::println. A suitable candidate would be fmt::println.

PrintHeader

The header that must be included for the declaration of ReplacementPrintFunction so that a #include directive can be added if required. If ReplacementPrintFunction is std::print then this option will default to <print>, otherwise this option will default to nothing and no #include directive will be added.