C++20 introduces a new text formatting API with the <format>
header, in addition to the printf
function
family — inherited from C — and iostreams
. std::format
combines the convenience of printf
, separating
formatting and arguments, with the type-safety of iostreams
. C++23 adds the <print>
header, which provides similar
features that output to a stream instead of generating a string.
Before C++20, if you wanted to format an output stream, you had to use standard manipulators that control the output streams. This approach is very
verbose, is often stateful, and is not thread-safe. That is why we recommend replacing them with std::print
or std::format
when possible.
Some manipulators will have a temporary effect on the output. For example, std::setw
. This is due to the resetting of the width
property of the stream when most of the operator<<
is called. Other manipulators will have a lasting effect on the output. For
example, std::boolalpha
. It will set the boolalpha
flag of the output stream without resetting it.
This rule raises an issue when an output stream is used with standard manipulators to output a formattable type in a way that can be replaced by
std::print
or std::format
. You should be careful to avoid undesirable side effects when replacing a manipulator with lasting
effects.
Noncompliant code example
void printBool(bool b) {
std::cout << std::boolalpha << b; // Noncompliant
}
void printInt(int b) {
std::cout << std::setfill('*') << std::setw(5) << b; // Noncompliant
}
int main() {
printInt(10);
printBool(true);
}
Compliant solution
void printBool(bool b) {
// Compliant, be aware of the side effect of not setting the boolalpha flag
std::print("{}", b);
// Or, in C++20
std::cout << std::format("{}", b);
}
void printInt(int b) {
// Compliant, no side effect because setw has a temporary effect
std::print("{:*>5}", b);
}
void setFlags() {
// Compliant, the intention is to set the flags and not to output
std::cout << std::boolalpha << std::showbase;
}
int main() {
printInt(10);
printBool(true);
setFlags();
}
Exceptions
Manipulators that don’t have a direct equivalent in the format library like std::quoted
, std::put_money
, etc.
void printQuoted(std::string_view s) {
// Compliant by exception: no simple format-based alternative
std::cout << std::quoted(s, '$', '-');
}