{"id":5996,"date":"2020-10-02T05:47:01","date_gmt":"2020-10-02T05:47:01","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/std-format-in-c-20\/"},"modified":"2023-06-26T09:42:32","modified_gmt":"2023-06-26T09:42:32","slug":"std-format-in-c-20","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/std-format-in-c-20\/","title":{"rendered":"std::format in C++20"},"content":{"rendered":"<p>Today, I&#8217;m happy to present Peter Gottschling&#8217;s guest post to the new formatting library in C++20: <code>std::format<\/code>. &nbsp;Thanks to&nbsp;<code>std::format<\/code>, text formatting becomes in C++20 as easy as in Python.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5945\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/07\/TimelineCpp20CoreLanguage.png\" alt=\"TimelineCpp20CoreLanguage\" width=\"650\" height=\"267\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<p>Peter is the author of the must-read book &#8220;<a href=\"https:\/\/www.pearson.com\/us\/higher-education\/program\/Gottschling-Discovering-Modern-C-2nd-Edition\/PGM2775899.html\">Discovering Modern C++<\/a>&#8221;&nbsp; for professional C++ developers.<\/p>\n<h2>New Formatting<\/h2>\n<p>Traditional stream formatting&nbsp;requires a fair amount of typing.&nbsp;Format strings in <code>printf<\/code> and alike&nbsp;are more expressive and allow us to declare with few symbols what&nbsp;we&#8217;ve written with multiple I\/O manipulators.&nbsp;<\/p>\n<p>Nonetheless, we advise against using <code>printf<\/code>.&nbsp;For two reasons, it can&#8217;t be used with user types and is not type-safe.&nbsp;The format string is parsed at run time, and the following arguments are treated&nbsp;with an obscure macro mechanism.&nbsp;If the arguments don&#8217;t match the format string, the behavior is undefined&nbsp;and can cause program crashes.&nbsp;For instance, a string is passed as a pointer, and from the pointed address on, the bytes are read and printed as <code>char<\/code> until a binary <code>0<\/code> is&nbsp;found in memory.&nbsp;If we accidentally try printing an <code>int<\/code> as a string, the <code>int<\/code> value&nbsp;is misinterpreted as an address from which a sequence&nbsp; <code>char<\/code> shall be&nbsp;printed. This will result in either absolute nonsensical output or (more likely) a&nbsp;memory error if the address is inaccessible.&nbsp;We must admit that recent compilers parse format strings (when known at compile time) and warn&nbsp;about argument mismatches.<\/p>\n<p>The new <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/format\/format\">format&nbsp;<\/a>library {By the time of writing, no compiler supported the&nbsp;library, and the examples were implemented with its prototype version: the <a href=\"https:\/\/github.com\/fmtlib\/fmt\">fmt <\/a>library. The format library combines the expressibility of the format string&nbsp;with the type safety and the user-extensibility of stream I\/O. It adds the opportunity to reorder the arguments in the output.<\/p>\n<h3>Integrals<\/h3>\n<p>Instead of a formal specification,&nbsp;we port some <code>printf<\/code> examples from <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/io\/c\/fprintf\">cppreference.com<\/a>&nbsp;to the new format:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">print(<span style=\"color: #cc3300;\">\"Decimal:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t<\/span><span style=\"color: #cc3300;\">{} {} {:06} {} {:0} {:+} {:d}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">0<\/span>, <span style=\"color: #ff6600;\">0<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>);\r\n\r\nprint(<span style=\"color: #cc3300;\">\"Hexadecimal:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t<\/span><span style=\"color: #cc3300;\">{:x} {:x} {:X} {:#x}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">6<\/span>);\r\n\r\nprint(<span style=\"color: #cc3300;\">\"Octal:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">{:o} {:#o} {:#o}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">4<\/span>);\r\n\r\nprint(<span style=\"color: #cc3300;\">\"Binary:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t\\t<\/span><span style=\"color: #cc3300;\">{:b} {:#b} {:#b}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">10<\/span>, <span style=\"color: #ff6600;\">4<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>This snippet prints:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">Decimal:        1 2 000003 0 0 +4 -1\r\n\r\nHexadecimal:    5 a A 0x6\r\n\r\nOctal:          12 012 04\r\n\r\nBinary:         1010 0b1010 0b100<br \/>\r\n<\/pre>\n<\/div>\n<p>The first two numbers were just printed without giving any format information. The exact output is generated when we ask for a decimal number with the format specifier <code>:d. <\/code>The third number shall be printed (minimally) 6~characters wide and filled with <code>0<\/code>s. The specifier <code>+<\/code> allows us to force printing the sign for all numbers. <code>printf<\/code> allows for specifying <code>unsigned<\/code> the output of numbers. That leads to incorrect large numbers when the value to print is negative. The <code>format<\/code> library refrains from user declarations of&nbsp; <code>unsigned <\/code>output since this information is already contained in the type of the according to the argument. If somebody wants to print a negative value as a largely positive, he must convert it explicitly.<\/p>\n<p>The second line demonstrates that we can print values hexadecimally with the lower and upper case for digits larger than 9. The specifier <code>#<\/code> generates the prefix <code>0x<\/code> used in hexadecimal literals.<\/p>\n<p>Likewise, we can print the values as octal and binaries, optionally with the according to literal prefix.<\/p>\n<\/p>\n<h3>Floating-Point Numbers<\/h3>\n<p>With floating-point numbers, we have more formatting options:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">print(<span style=\"color: #cc3300;\">\"Default:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t<\/span><span style=\"color: #cc3300;\">{} {:g} {:g}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1e20<\/span>);\r\n\r\nprint(<span style=\"color: #cc3300;\">\"Rounding:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t<\/span><span style=\"color: #cc3300;\">{:f} {:.0f} {:.22f}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1.3<\/span>);\r\n\r\nprint(<span style=\"color: #cc3300;\">\"Padding:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t<\/span><span style=\"color: #cc3300;\">{:05.2f} {:.2f} {:5.2f}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>);\r\n\r\nprint(<span style=\"color: #cc3300;\">\"Scientific:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t<\/span><span style=\"color: #cc3300;\">{:E} {:e}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>);\r\n\r\nprint(<span style=\"color: #cc3300;\">\"Hexadecimal:<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\t<\/span><span style=\"color: #cc3300;\">{:a} {:A}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">1.5<\/span>, <span style=\"color: #ff6600;\">1.3<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Then we get:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">Default:        1.5 1.5 1e+20\r\n\r\nRounding:       1.500000 2 1.3000000000000000444089\r\n\r\nPadding:        01.50 1.50  1.50\r\n\r\nScientific:     1.500000E+00 1.500000e+00\r\n\r\nHexadecimal:    0x1.8p+0 0X1.4CCCCCCCCCCCDP+0\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>We get the default output with empty braces or only containing a colon. This corresponds to the format specifier<code>&nbsp;:g<\/code>&nbsp;and yields the same output as streams without the manipulators. The number of fractional digits can be given between a dot and the format specifier<code> f<\/code>. Then the value is rounded to that precision. If the requested number is larger than what is representable by the value&#8217;s type, the last digits aren&#8217;t significant. A digit in front of the dot specifies the (minimal) width of the output. As with integers, we can request leading<code> 0<\/code>s. Floating-point numbers can be printed in scientific notation with either upper or lower case <code>e<\/code> to start the exponential part. The hexadecimal output can initialize a variable in another program with precisely the same bits.<\/p>\n<h3>Redirecting Output<\/h3>\n<p>The output can be redirected to any other <code>std::ostream (<\/code>Requires including <code>ostream.h<\/code> with the fmt library.):<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">print(std<span style=\"color: #555555;\">::<\/span>cerr, <span style=\"color: #cc3300;\">\"System error code = {}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">7<\/span>);\r\n\r\nofstream <span style=\"color: #cc00ff;\">error_file<\/span>(<span style=\"color: #cc3300;\">\"error_file.txt\"<\/span>);\r\n\r\nprint(error_file, <span style=\"color: #cc3300;\">\"System error code = {}<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #ff6600;\">7<\/span>);<\/pre>\n<\/div>\n<h3>Reordering Arguments and Name them<\/h3>\n<p>In contrast to <code>printf<\/code>, arguments can now be reordered:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">print(<span style=\"color: #cc3300;\">\"I'd rather be {1} than {0}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>, <span style=\"color: #cc3300;\">\"right\"<\/span>, <span style=\"color: #cc3300;\">\"happy\"<\/span>);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In addition to referring to the arguments by their positions, we can give them names:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">print(<span style=\"color: #cc3300;\">\"Hello, {name}! The answer is {number}. Goodbye, {name}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>,\r\n      arg(<span style=\"color: #cc3300;\">\"name\"<\/span>, name), arg(<span style=\"color: #cc3300;\">\"number\"<\/span>, number));\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Or, more concisely:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">print(<span style=\"color: #cc3300;\">\"Hello, {name}! The answer is {number}. Goodbye, {name}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>,\r\n      <span style=\"color: #cc3300;\">\"name\"<\/span>_a<span style=\"color: #555555;\">=<\/span>name, <span style=\"color: #cc3300;\">\"number\"<\/span>_a<span style=\"color: #555555;\">=<\/span>number);\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>Rainer: C++20 does not have named arguments.<\/strong><\/li>\n<\/ul>\n<p>The example also demonstrates that we can print an argument multiple times.<\/p>\n<p>Reordering arguments is critical in multi-lingual software to provide a natural phrasing.<\/p>\n<p>Now, we want to print the average of two values in five languages:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">print_average<\/span>(<span style=\"color: #007788; font-weight: bold;\">float<\/span> v1, <span style=\"color: #007788; font-weight: bold;\">float<\/span> v2, <span style=\"color: #007788; font-weight: bold;\">int<\/span> language)\r\n\r\n{   \r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">using<\/span> <span style=\"color: #006699; font-weight: bold;\">namespace<\/span> fmt;\r\n\r\n    string formats[]<span style=\"color: #555555;\">=<\/span> {<span style=\"color: #cc3300;\">\"The average of {v1} and {v2} is {result}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>,\r\n\r\n                       <span style=\"color: #cc3300;\">\"{result:.6f} ist der Durchschnitt von {v1} und {v2}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>,\r\n\r\n                       <span style=\"color: #cc3300;\">\"La moyenne de {v1} et {v2} est {result}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>,\r\n\r\n                       <span style=\"color: #cc3300;\">\"El promedio de {v1} y {v2} es {result}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>,\r\n\r\n                       <span style=\"color: #cc3300;\">\"{result} corrisponde alla media di {v1} e {v2}.<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>};\r\n\r\n    print (formats[language], <span style=\"color: #cc3300;\">\"v1\"<\/span>_a<span style=\"color: #555555;\">=<\/span> v1, <span style=\"color: #cc3300;\">\"v2\"<\/span>_a<span style=\"color: #555555;\">=<\/span> v2, <span style=\"color: #cc3300;\">\"result\"<\/span>_a<span style=\"color: #555555;\">=<\/span> (v1<span style=\"color: #555555;\">+<\/span>v2)<span style=\"color: #555555;\">\/<\/span><span style=\"color: #ff6600;\">2.0f<\/span>);\r\n\r\n}   \r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Of course, the German version is the most pedantic one, requesting six decimal digits no matter what:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">The average of 3.5 and 7.3 is 5.4.\r\n\r\n5.400000 ist der Durchschnitt von 3.5 und 7.3.\r\n\r\nLa moyenne de 3.5 et 7.3 est 5.4.\r\n\r\nEl promedio de 3.5 y 7.3 es 5.4.\r\n\r\n5.4 corrisponde alla media di 3.5 e 7.3.<br \/>\r\n<\/pre>\n<\/div>\n<p>Admittedly, this example would have worked without reordering the arguments, but it nicely demonstrates the important possibility of separating the text and the formatting from the values. To store formatted text in a string, we don&#8217;t need&nbsp;&nbsp;<code>stringstream<\/code> any longer but can do it directly with the function format.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>In the <a href=\"https:\/\/www.modernescpp.com\/index.php\/extend-std-format-in-c-20-for-user-defined-types\">next post<\/a>, Peter continues his introduction to <code>std::format<\/code>. He writes about user-defined formatting.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, I&#8217;m happy to present Peter Gottschling&#8217;s guest post to the new formatting library in C++20: std::format. &nbsp;Thanks to&nbsp;std::format, text formatting becomes in C++20 as easy as in Python.<\/p>\n","protected":false},"author":21,"featured_media":5945,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[454],"class_list":["post-5996","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-format"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5996","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5996"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5996\/revisions"}],"predecessor-version":[{"id":6727,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5996\/revisions\/6727"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5945"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5996"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5996"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5996"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}