The std::fmt library in C++ provides a modern, fast, and type-safe
approach to text formatting, drawing inspiration from Python’s
str.format syntax. It serves as a more robust and performant
alternative to the C-style printf and the C++ iostreams
(std::cout).
C++ version introduction
The core components of the C++ standard library’s formatting capabilities were introduced in C++20.
Methods for formatting custom objects
For a user-defined type to be formatted by the std::fmt library, you must provide a specialization of the std::formatter template. The required methods within this specialization are:
parse(): This method is called during the parsing of the format string. It receives astd::format_parse_contextand is responsible for parsing any custom format specifiers for your type, such as"{:spec}". It should beconstexprfor compile-time format string validation.format(): This method performs the actual formatting of the object. It takes the object to be formatted and astd::format_context. It then usesstd::format_toor a similar function to write the formatted output to the context’s output iterator.
Example
Here is a simplified example of specializing std::formatter for a custom Point class:
|
|
Before std::fmt
Before the introduction of std::fmt in C++20, developers used several non-standard and open-source mechanisms to get printf-like formatting. These libraries were created to address the type-safety issues of C’s printf while offering a more convenient and sometimes faster alternative to C++’s built-in iostreams.
The primary non-standard libraries and techniques included:
{fmt} library
The {fmt} library is the most notable open-source, non-standard formatting library, as std::fmt was directly adopted from it.
- Syntax: Inspired by Python’s
str.format, it uses a{}syntax for placeholders, which is a significant improvement in readability overprintf’s specifiers like%d,%s, and%x. - Type Safety: It uses C++ variadic templates to perform compile-time argument checks, making it type-safe and preventing errors like passing the wrong argument type for a format specifier.
- Performance: It was designed to be faster than iostreams and competitive with C’s
printffamily of functions. - Extensibility: User-defined types can be made formattable by specializing a
fmt::formattertemplate, a feature that was carried over tostd::fmt.
Boost.Format
The Boost.Format library was a popular predecessor that provided a type-safe and extensible printf-like facility.
- Syntax: It uses a syntax of
%N%to denote the position of arguments, which are passed to the format object using theoperator%. - Mechanism: Internally, it used C++ iostreams to do the actual formatting. A
boost::formatobject first parses the format string, and then each argument is streamed into it. - Extensibility: Any user-defined type that had a
std::ostream& operator<<overload could be used with Boost.Format.
tinyformat.h
This is a minimalist, header-only library that provides a type-safe printf replacement. Git
- Simplicity: With the code contained in a single header file, it was easy to integrate into projects.
- Compatibility: It aimed for compatibility with C99
printf()syntax while leveraging C++ features for type safety. - Mechanism: It augmented standard stream formatting rather than completely replacing it.
Variadic templates
Some developers created custom printf-like functions using C++11 variadic templates.
- Purpose: These implementations were written to provide a type-safe formatting mechanism for specific use cases or projects, without relying on a third-party library.
- Mechanism: They typically used a recursive template approach to process each argument in the format string.
Standard iostreams
While not a “non-standard” solution, many developers chose to use std::cout, std::ostringstream, and iostream manipulators from <iomanip> as an alternative to printf.
- Extensibility: The main advantage was the ability to define
operator<<overloads for custom types. - Performance: Iostreams are generally slower than
printfand the {fmt} library, a factor that prompted the development of faster alternatives. - Complexity: Complex formatting using manipulators was sometimes considered less intuitive than
printfor {fmt} syntax.