Home » More details on formatting custom data types in C++20

More details on formatting custom data types in C++20

by admin
More details on formatting custom data types in C++20

More details on formatting custom data types in C++20

This article is the fifth in my mini-series on formatting in C++20. The previous posts can be found here:


Rainer Grimm has been working as a software architect, team and training manager for many years. He enjoys writing articles on the programming languages ​​C++, Python and Haskell, but also enjoys speaking frequently at specialist conferences. On his blog Modern C++ he deals intensively with his passion C++.

Point is a class with three members.

// formatPoint.cpp

#include #include

struct Point {
int x{2017};
int y{2020};
int z{2023};

struct std::formatter : std::formatter<:string> {
auto format(Point point, format_context& context) const {
return formatter::format(
std::format(“({}, {}, {})”,
point.x, point.y, point.y), context);

int main() {

std::cout 25}”, point) 10}”, point.x)
In this case I rely on the standard formatter std::formatter<:string> away. A std::string_view is also possible. std::formatter produces the formatted output by calling format on std::formatter. This function call already receives a formatted string as a value. Consequently, all format specifications of std::string are applicable (1 – 3). On the contrary, any value of Point can also be formatted. This is exactly what happens in (4) and (5).

The formatting functions std::format* and std::vformat* have overloads that also accept locals. These overloads can be used to localize a formatting string.

The following code snippet shows the corresponding overload of std::format:

std::string format( const std::locale& loc,
std::format_string fmt,
Args&&… args );

To use a specific local, specify L before the data type in the format string. Now you apply the locale every time you call std::format or set it globally with std::locale::global.

In the following example, I explicitly use the German local for every std::format call.

See also  “Dos & Don’ts” for smartphone batteries

// internationalization.cpp


std::locale createLocale(const std::string& localString) { // (1)
try {
return std::locale{localString};
catch (const std::exception& e) {
return std::locale{“”};

int main() {

std::cout The createLocale (1) function creates the German local. If this fails, it returns the default local, which uses American formatting. I use the German local in (2), (3), (4) and (5). To see the difference, I also applied the std::format calls immediately afterward. Consequently, the location-dependent thousands separator is used for the integer value (2) and the location-dependent decimal point and thousands separator is used for the floating point value (3). Accordingly, the time period (4) and time point (5) use the specified German locale.

The following screenshot shows the output of the program.

std::formatter and its specializations define the format specification for the chrono library data types as well. Before I write about them, I will dive deeper into C++20’s Chrono extension.


To home page

You may also like

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More

Privacy & Cookies Policy