std::print
Modern formatted output for C++
🖨️ What is std::print?
std::print is a C++23 feature that provides a modern, type-safe way to output formatted text. It combines the power of std::format with direct output, making printing easier and more efficient than traditional methods.
#include <print>
#include <string>
int main() {
std::string name = "World";
int number = 42;
std::print("Hello {}! The answer is {}.\n", name, number);
std::println("This adds a newline automatically!");
return 0;
}
Output:
Hello World! The answer is 42. This adds a newline automatically!
Key Features of std::print
Type Safe
Compile-time format string validation
std::print("{}", value);
Efficient
Direct output without string creation
// No intermediate strings
Simple
Cleaner than cout and printf
std::println("Hello!");
Unicode Ready
Proper Unicode and encoding support
// UTF-8 support built-in
🔹 Basic Printing
C++23 introduces std::print and std::println for simplified, type-safe output to
streams. Unlike printf, these functions leverage std::format syntax,
providing compile-time checks and avoiding manual format specifiers. For example,
std::println("Hello, {}!", name); safely embeds variables. They default to standard output but can
target any output stream. This modern approach reduces errors, improves readability, and integrates seamlessly with
locale and Unicode, making console output more robust.
#include <print>
int main() {
// Basic print (no automatic newline)
std::print("Hello ");
std::print("World!");
// Print with newline
std::println("\nThis is on a new line");
// Print without arguments
std::println("Simple message");
return 0;
}
Output:
Hello World! This is on a new line Simple message
🔹 Formatted Output
Formatted output with std::format allows embedding variables directly into strings using
replacement fields {}. It provides type-safe, memory-safe formatting without the pitfalls
of C-style printf. For instance, std::format("The value is {}", 42) produces a string that
can be printed or logged. You can also customize formatting with alignment, precision, and locale-specific options.
This feature is essential for creating user messages, logs, and reports with clean, maintainable code.
#include <print>
int main() {
int age = 25;
double height = 5.9;
std::string name = "Alice";
// Multiple arguments
std::println("Name: {}, Age: {}, Height: {:.1f}ft", name, age, height);
// Positional arguments
std::println("{1} is {0} years old", age, name);
// Repeated arguments
std::println("{0} {0} {0}!", "Hip");
return 0;
}
Output:
Name: Alice, Age: 25, Height: 5.9ft Alice is 25 years old Hip Hip Hip!
🔹 Number Formatting
Advanced number formatting in C++ enables precise control over numeric output, including bases, alignment,
and localization. Using std::format, you can format integers as hex ({:x}),
control floating-point precision ({:.2f}), and add thousands separators. For example,
std::format("{:#x}", 255) produces 0xff. This eliminates manual string manipulation and
ensures consistent, readable output across different numeric types, which is crucial for financial, scientific, and
debugging applications.
#include <print>
int main() {
double pi = 3.14159265359;
int number = 1234567;
// Decimal precision
std::println("Pi to 2 places: {:.2f}", pi);
std::println("Pi to 5 places: {:.5f}", pi);
// Different number bases
std::println("Decimal: {}, Hex: {:x}, Binary: {:b}", 255, 255, 255);
// Width and padding
std::println("Padded: '{:>10}'", number);
std::println("Zero-padded: '{:010}'", 42);
return 0;
}
Output:
Pi to 2 places: 3.14 Pi to 5 places: 3.14159 Decimal: 255, Hex: ff, Binary: 11111111 Padded: ' 1234567' Zero-padded: '0000000042'
🔹 Output to Files
Printing to files and other output streams is streamlined with std::print and
std::format, supporting any std::ostream. You can direct formatted output to
files, strings, or custom streams using a file stream argument. For example,
std::print(file_stream, "Data: {}", value) writes directly to a file. This integration simplifies
logging and data export, providing consistent formatting across different outputs while maintaining the safety and
expressiveness of modern C++ I/O.
#include <print>
#include <fstream>
int main() {
// Print to file
std::ofstream file("output.txt");
std::print(file, "Writing to file: {}\n", "Hello File!");
// Print to stderr
std::print(stderr, "Error message: {}\n", "Something went wrong");
// Print to stdout (default)
std::println("This goes to standard output");
file.close();
return 0;
}
Output:
This goes to standard output (Error message goes to stderr) (File contains: "Writing to file: Hello File!")
🔹 Comparison with Other Methods
std::print offers significant advantages over traditional output methods like
printf and iostreams. Unlike printf, it is type-safe and
prevents format string vulnerabilities. Compared to verbose iostream chaining, it provides concise,
readable syntax with built-in formatting. It also outperforms manual string concatenation in both clarity and
performance. Adopting std::print reduces boilerplate, minimizes errors, and aligns with modern C++ best
practices for output.
#include <print>
#include <iostream>
#include <format>
int main() {
std::string name = "Bob";
int score = 95;
// Traditional cout (verbose)
std::cout << "Player " << name << " scored " << score << " points" << std::endl;
// printf (not type-safe)
printf("Player %s scored %d points\n", name.c_str(), score);
// std::format + cout (extra step)
std::cout << std::format("Player {} scored {} points\n", name, score);
// std::print (clean and efficient)
std::println("Player {} scored {} points", name, score);
return 0;
}
Output:
Player Bob scored 95 points Player Bob scored 95 points Player Bob scored 95 points Player Bob scored 95 points