Something went wrong. Try again.
A Tour of C++ for experienced programmers, as if C++26 is the only version that ever existed.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432<!DOCTYPE HTML><html lang="en" class="light sidebar-visible" dir="ltr"> <head> <!-- Book generated using mdBook --> <meta charset="UTF-8"> <title>Text: strings, views, and formatting - A Tour of C++26</title>
<!-- Custom HTML head -->
<meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="theme-color" content="#ffffff">
<link rel="icon" href="favicon-de23e50b.svg"> <link rel="shortcut icon" href="favicon-8114d1fc.png"> <link rel="stylesheet" href="css/variables-8adf115d.css"> <link rel="stylesheet" href="css/general-e96d0476.css"> <link rel="stylesheet" href="css/chrome-d279d366.css"> <link rel="stylesheet" href="css/print-9e4910d8.css" media="print">
<!-- Fonts --> <link rel="stylesheet" href="fonts/fonts-9644e21d.css">
<!-- Highlight.js Stylesheets --> <link rel="stylesheet" id="mdbook-highlight-css" href="highlight-493f70e1.css"> <link rel="stylesheet" id="mdbook-tomorrow-night-css" href="tomorrow-night-4c0ae647.css"> <link rel="stylesheet" id="mdbook-ayu-highlight-css" href="ayu-highlight-3fdfc3ac.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root and default themes to javascript --> <script> const path_to_root = ""; const default_light_theme = "light"; const default_dark_theme = "navy"; window.path_to_searchindex_js = "searchindex-7c7963f3.js"; </script> <!-- Start loading toc.js asap --> <script src="toc-0eddcac6.js"></script> </head> <body> <div id="mdbook-help-container"> <div id="mdbook-help-popup"> <h2 class="mdbook-help-title">Keyboard shortcuts</h2> <div> <p>Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters</p> <p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p> <p>Press <kbd>?</kbd> to show this help</p> <p>Press <kbd>Esc</kbd> to hide this help</p> </div> </div> </div> <div id="mdbook-body-container"> <!-- Work around some values being stored in localStorage wrapped in quotes --> <script> try { let theme = localStorage.getItem('mdbook-theme'); let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) { localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); }
if (sidebar.startsWith('"') && sidebar.endsWith('"')) { localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); } } catch (e) { } </script>
<!-- Set the theme before any content is loaded, prevents flash --> <script> const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme; let theme; try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } if (theme === null || theme === undefined) { theme = default_theme; } const html = document.documentElement; html.classList.remove('light') html.classList.add(theme); html.classList.add("js"); </script>
<input type="checkbox" id="mdbook-sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed --> <script> let sidebar = null; const sidebar_toggle = document.getElementById("mdbook-sidebar-toggle-anchor"); if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible'; } else { sidebar = 'hidden'; sidebar_toggle.checked = false; } if (sidebar === 'visible') { sidebar_toggle.checked = true; } else { html.classList.remove('sidebar-visible'); } </script>
<nav id="mdbook-sidebar" class="sidebar" aria-label="Table of contents"> <!-- populated by js --> <mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox> <noscript> <iframe class="sidebar-iframe-outer" src="toc.html"></iframe> </noscript> <div id="mdbook-sidebar-resize-handle" class="sidebar-resize-handle"> <div class="sidebar-resize-indicator"></div> </div> </nav>
<div id="mdbook-page-wrapper" class="page-wrapper">
<div class="page"> <div id="mdbook-menu-bar-hover-placeholder"></div> <div id="mdbook-menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <label id="mdbook-sidebar-toggle" class="icon-button" for="mdbook-sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="mdbook-sidebar"> <span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg></span> </label> <button id="mdbook-theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="mdbook-theme-list"> <span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M371.3 367.1c27.3-3.9 51.9-19.4 67.2-42.9L600.2 74.1c12.6-19.5 9.4-45.3-7.6-61.2S549.7-4.4 531.1 9.6L294.4 187.2c-24 18-38.2 46.1-38.4 76.1L371.3 367.1zm-19.6 25.4l-116-104.4C175.9 290.3 128 339.6 128 400c0 3.9 .2 7.8 .6 11.6c1.8 17.5-10.2 36.4-27.8 36.4H96c-17.7 0-32 14.3-32 32s14.3 32 32 32H240c61.9 0 112-50.1 112-112c0-2.5-.1-5-.2-7.5z"/></svg></span> </button> <ul id="mdbook-theme-list" class="theme-popup" aria-label="Themes" role="menu"> <li role="none"><button role="menuitem" class="theme" id="mdbook-theme-default_theme">Auto</button></li> <li role="none"><button role="menuitem" class="theme" id="mdbook-theme-light">Light</button></li> <li role="none"><button role="menuitem" class="theme" id="mdbook-theme-rust">Rust</button></li> <li role="none"><button role="menuitem" class="theme" id="mdbook-theme-coal">Coal</button></li> <li role="none"><button role="menuitem" class="theme" id="mdbook-theme-navy">Navy</button></li> <li role="none"><button role="menuitem" class="theme" id="mdbook-theme-ayu">Ayu</button></li> </ul> <button id="mdbook-search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="mdbook-searchbar"> <span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z"/></svg></span> </button> </div>
<h1 class="menu-title">A Tour of C++26</h1>
<div class="right-buttons"> <a href="print.html" title="Print this book" aria-label="Print this book"> <span class=fa-svg id="print-button"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M128 0C92.7 0 64 28.7 64 64v96h64V64H354.7L384 93.3V160h64V93.3c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0H128zM384 352v32 64H128V384 368 352H384zm64 32h32c17.7 0 32-14.3 32-32V256c0-35.3-28.7-64-64-64H64c-35.3 0-64 28.7-64 64v96c0 17.7 14.3 32 32 32H64v64c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V384zm-16-88c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/></svg></span> </a>
</div> </div>
<div id="mdbook-search-wrapper" class="hidden"> <form id="mdbook-searchbar-outer" class="searchbar-outer"> <div class="search-wrapper"> <input type="search" id="mdbook-searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="mdbook-searchresults-outer" aria-describedby="searchresults-header"> <div class="spinner-wrapper"> <span class=fa-svg id="fa-spin"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z"/></svg></span> </div> </div> </form> <div id="mdbook-searchresults-outer" class="searchresults-outer hidden"> <div id="mdbook-searchresults-header" class="searchresults-header"></div> <ul id="mdbook-searchresults"> </ul> </div> </div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> <script> document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) { link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); }); </script>
<div id="mdbook-content" class="content"> <main> <h1 id="text-and-formatting"><a class="header" href="#text-and-formatting">Text and formatting</a></h1><p>In this chapter we replace the old C‑style formatting functions with the modern, type‑safe facilities that arrive in C++20 and C++23. The progression mirrors the lessons from the lifetime chapters: first we look at why <code>printf</code> is hazardous, then we introduce owning strings, non‑owning views, and finally the compile‑time checked formatting API.</p><h2 id="the-c-printf-problem"><a class="header" href="#the-c-printf-problem">The C printf problem</a></h2><p><code>printf</code> takes a format string that describes the types of the arguments that follow. The compiler cannot verify that the format string matches the argument list because the string is an ordinary <code>char const *</code>. If the programmer writes a mismatched conversion specifier or omits an argument, the program exhibits <strong>undefined behavior</strong> at run time.</p><pre><code class="language-cpp">// The format string expects an `int` and a `double`, but only one argument is supplied.printf("%d %f\n", 42)</code></pre><p>The above code compiles, but at execution the function reads a non‑existent <code>double</code> from the stack. The result is nondeterministic and leads to memory corruption.</p><h2 id="stdstring-and-stdstring_view"><a class="header" href="#stdstring-and-stdstring_view">std::string and std::string_view</a></h2><p><code>std::string</code> owns the character storage. It allocates memory, frees it when the object is destroyed, and therefore always remains valid for the lifetime of the owning object.</p><p><code>std::string_view</code> does <strong>not</strong> own any characters. It merely holds a pointer and a length. The view is valid only while the underlying characters remain alive. Because a view never copies, it is ideal for function parameters: the caller can pass a <code>std::string</code>, a string literal, or a substring without allocating a new buffer.</p><pre><code class="language-cpp">void greet(std::string_view name) { std::println("Hello, {}!", name);}
greet("Ada") // literal - no allocationstd::string full = "Grace Hopper"greet(full) // temporary view of whole stringgreet(full.substr(0,5)) // view of a prefix</code></pre><p>The function <code>greet</code> never copies the characters it simply reads them through the view.</p><h2 id="stdformat-c20"><a class="header" href="#stdformat-c20"><code>std::format</code> (C++20)</a></h2><p><code>std::format</code> replaces <code>printf</code> with a <strong>type‑safe, variadic</strong> formatting function. The format string contains <code>{}</code> placeholders. The compiler parses the literal at compile time, matches each placeholder with the corresponding argument, and rejects mismatches with a diagnostic.</p><pre><code class="language-cpp">#include <format>#include <print>#include <string>
int main() { std::string name = "Alice"; int age = 30; double score = 95.5; std::println("{}", std::format("Name: {}, Age: {}, Score: {:.2f}", name, age, score)); return 0;}</code></pre><p>Running the program prints a line that contains <code>Name: Alice</code>. The <code>EXPECT</code> test in the build system checks for that substring.</p><h2 id="stdprint-and-stdprintln-c23"><a class="header" href="#stdprint-and-stdprintln-c23"><code>std::print</code> and <code>std::println</code> (C++23)</a></h2><p><code>std::print</code> writes to <code>stdout</code> without appending a newline. <code>std::println</code> does the same but adds a newline automatically. The book uses <code>std::println</code> for line-oriented output. It uses <code>std::print</code> only when the output is a sequence of values on one line, written inside a loop, where a newline after each value is wrong. In that case the loop body calls <code>std::print("{} ", value)</code> and a single <code>std::println()</code> closes the line after the loop.</p><pre><code class="language-cpp">#include <print>
int main() { std::println("{:>10} | {:>8}", "Item", "Value"); std::println("{:>10} | {:>8.2f}", "A", 1.23); std::println("{:>10} | {:>8.2f}", "B", 4.56); std::println("{:>10} | {:>8.2f}", "C", 7.89); return 0;}</code></pre><p>The example prints a small table. The test harness looks for the token <code>A</code> in the output.</p><div class="table-wrapper"><table><thead><tr><th>Facility</th><th>Header</th><th>Type safety</th><th>Format checking</th><th>Returns</th><th>Use when</th></tr></thead><tbody><tr><td><code>std::cout</code></td><td><code><iostream></code></td><td>per insertion</td><td>none</td><td>stream reference</td><td>stream features, custom <code>operator<<</code></td></tr><tr><td><code>printf</code></td><td><code><cstdio></code></td><td>none</td><td>none</td><td>int count</td><td>C interop, legacy code</td></tr><tr><td><code>std::print</code> / <code>std::println</code></td><td><code><print></code></td><td>typed arguments</td><td>compile time</td><td>void</td><td>new code, checked formatting</td></tr></tbody></table></div><h2 id="format-specifiers"><a class="header" href="#format-specifiers">Format specifiers</a></h2><p>The part of the format string after a colon controls alignment, width, fill character, precision, and numeric base.</p><ul><li><strong>Width and alignment</strong>: <code>{:<10}</code> left‑aligns inside a field of ten characters, <code>{:>10}</code> right‑aligns, <code>{:^10}</code> centers.</li><li><strong>Fill character</strong>: <code>{:*^8}</code> pads with <code>*</code> while centering.</li><li><strong>Precision</strong>: <code>{: .2f}</code> prints a floating‑point value with two digits after the decimal point.</li><li><strong>Base</strong>: <code>{:#x}</code> prints an integer in hexadecimal with a <code>0x</code> prefix, <code>{:08b}</code> prints binary padded to eight digits.</li></ul><pre><code class="language-cpp">std::println("{:>10}", "right") // " right"std::println("{:08b}", 5) // "00000101"std::println("{:#x}", 255) // "0xff"std::println("{:.2f}", 3.14159) // "3.14"</code></pre><p>If a specifier is unknown, the compiler issues an error because the format string is a compile‑time constant.</p><p>The specifier syntax mirrors Python’s <code>format</code>. The colon introduces a format‑spec, then optional fill, alignment, sign, alternate form, zero‑pad, width, precision, and type. The order matters. The compiler enforces it.</p><p>Performance of <code>std::format</code> is comparable to hand‑written <code>printf</code> for simple cases. The library avoids temporary allocations for short strings by using a small‑buffer optimisation.</p><p>Custom types can be formatted by specialising <code>std::formatter</code>. The specialization returns a <code>format_to</code> function that writes the representation into the provided output iterator.</p><pre><code class="language-cpp">struct Point { int x; int y; };
template<> struct std::formatter<Point> { constexpr auto parse(auto& ctx) { return ctx.begin(); } auto format(Point const& p, auto& ctx) const { return std::format_to(ctx.out(), "({},{})", p.x, p.y); }};
std::println("{}", Point{3,4}); // prints "(3,4)"</code></pre><p>The same custom formatter works for both <code>std::println</code> and <code>std::format</code> because they share the formatter protocol.</p><h2 id="advanced-formatting-features"><a class="header" href="#advanced-formatting-features">Advanced formatting features</a></h2><p>Beyond the basic width and precision specifiers, <code>std::format</code> supports a rich set of options that let developers tailor the textual representation of values.</p><ul><li><strong>Sign handling</strong>: <code>{: +}</code> forces a leading plus sign for positive numbers, while <code>{: -}</code> (the default) prints a minus sign only for negatives.</li><li><strong>Alternate form</strong>: The <code>#</code> flag adds a prefix for certain types: <code>0x</code> for hexadecimal, <code>0</code> for octal, and a trailing decimal point for floating‑point values.</li><li><strong>Zero padding</strong>: <code>{:08}</code> pads the field with zeros instead of spaces. It is equivalent to <code>{:0>8}</code> but more concise.</li><li><strong>Grouping</strong>: <code>{:L}</code> formats numbers according to the locale’s thousands separator. This works together with a <code>std::locale</code> overload.</li><li><strong>Date and time</strong>: When the <code><chrono></code> library provides a <code>std::chrono::year_month_day</code> or <code>std::chrono::hh_mm_ss</code> object, the formatter can emit ISO‑8601 strings using the <code>{:T}</code> or <code>{:D}</code> specifiers.</li></ul><pre><code class="language-cpp">std::println("{:+08}", 42) // "+0000042"std::println("{:#x}", 255) // "0xff"std::println("{:L}", 1234567) // "1,234,567" in en_US locale
using namespace std::chronoauto now = floor<seconds>(system_clock::now())std::println("{:T}", now) // "2026-08-21T14:35:00"</code></pre><p>These specifiers are composable a format string can combine alignment, fill, width, sign, and type in a single placeholder. The compiler checks that the combination is valid for the argument type, rejecting illegal mixes such as a sign flag on a string.</p><p>Custom types can also honour these flags by inspecting the <code>format_context</code> and the parsed format‑spec. A formatter can honour <code>fill</code> and <code>align</code> by delegating to <code>std::format_to</code> with a constructed format string, or it can implement the formatting logic directly for maximum performance.</p><pre><code class="language-cpp">struct Money { int cents;};
template<> struct std::formatter<Money> { char presentation = 'f'; // f = dollars.cents, e = euros constexpr auto parse(auto& ctx) { auto it = ctx.begin(); if (it != ctx.end() && (*it == 'e' || *it == 'f')) presentation = *it++; return it; } auto format(Myney const& m, auto& ctx) const { if (presentation == 'e') return std::format_to(ctx.out(), "€{:.2f}", m.cents / 100.0); else return std::format_to(ctx.out(), "${:.2f}", m.cents / 100.0); }};std::println("{}", Money{1234}) // prints "$12.34"</code></pre><p>The example demonstrates how a formatter can respect a presentation specifier while still supporting the generic alignment and width options supplied by the surrounding format string.</p><p>Placeholders can refer to arguments by position.</p><pre><code class="language-cpp">std::println("{0} + {0} = {1}", 2, 4) // prints "2 + 2 = 4"</code></pre><p>Named arguments are not part of the core standard, but a user can achieve them by providing a custom <code>std::formatter</code> specialization or by using <code>std::make_format_args</code> together with a format string that references names via a library such as {fmt}. The book mentions the technique briefly because it is useful in larger projects.</p><pre><code class="language-cpp">// Using a custom formatter (illustrative - not compiled here)struct Point { int x int y }template<> struct std::formatter<Point> : std::formatter<std::string> { auto format(Point const& p, auto& ctx) const { return std::formatter<std::string>::format( std::format("({},{})", p.x, p.y), ctx) }}</code></pre><h2 id="compiletime-checking-is-the-point"><a class="header" href="#compiletime-checking-is-the-point">Compile‑time checking is the point</a></h2><p><code>std::format</code> only accepts a <strong>compile‑time constant</strong> format string for full checking. If a program needs a run‑time format, the library provides <code>std::runtime_format</code>, which disables compile‑time verification. This design forces the programmer to choose safety whenever possible.</p><p>Contrast the two approaches:</p><ul><li><code>printf("%d %f\n", 42)</code>: compiles, can crash at run time.</li><li><code>std::format("%d %f\n", 42)</code>: fails to compile because <code>%</code> is not a valid placeholder.</li><li><code>std::format(std::runtime_format(fmt), 42)</code>: compiles, but the format string is unchecked.</li></ul><p>The book’s theme is to let the compiler catch what it can, and <code>std::format</code> embodies that principle.</p><h2 id="performance-and-constexpr-formatting"><a class="header" href="#performance-and-constexpr-formatting">Performance and constexpr formatting</a></h2><p><code>std::format</code> is designed to be fast. The implementation parses the format string at compile time when the literal is a constant expression, eliminating runtime parsing overhead. This makes it comparable to hand‑written <code>printf</code> for simple cases while providing safety.</p><p>When the format string cannot be known at compile time, the library falls back to a runtime parser. The cost is modest: a single pass over the format string plus the usual formatting work. For tight loops where every nanosecond matters, developers can still write a custom <code>printf</code>‑style loop, but the safety trade‑off must be justified.</p><p>C++23 extends <code>std::format</code> with <code>constexpr</code> support. A <code>constexpr</code> function can call <code>std::format</code> to produce a compile‑time constant string that can be used as a non‑type template parameter or in a <code>static_assert</code>.</p><pre><code class="language-cpp">constexpr std::string_view make_label(int id) { return std::format("Item-{:03}", id)}static_assert(make_label(7) == "Item-007")</code></pre><p>The example illustrates how formatting can participate in compile‑time computation, enabling expressive metaprogramming without sacrificing safety.</p><p>Locale‑aware formatting is optional. By default <code>std::format</code> uses the “C” locale, which formats numbers with a period as the decimal separator. Passing a <code>std::locale</code> object to the overload selects the suitable digit grouping and decimal marks for the target locale.</p><pre><code class="language-cpp">std::locale german("de_DE")std::println(std::format(german, "{:L}", 1234567.89)) // prints "1.234.567,89"</code></pre><p>Custom formatters, shown earlier, work uniformly with locale‑aware overloads because the formatter receives the locale via its <code>format</code> method.</p><h2 id="error-handling-in-formatting"><a class="header" href="#error-handling-in-formatting">Error handling in formatting</a></h2><p>When a format string is ill‑formed, <code>std::format</code> throws a <code>std::format_error</code>. This exception type is a subclass of <code>std::runtime_error</code> and carries a message that identifies the problem, for example, “argument index out of range” or “invalid format specifier”.</p><pre><code class="language-cpp">try { std::println(std::format("{0} {2}", 1, 2)) // index 2 does not exist} catch (const std::format_error& e) { std::cerr << "Formatting failed: " << e.what() << '\n'}</code></pre><p>The library also provides the non‑throwing overload <code>std::format_to_n</code> which writes into a pre‑allocated buffer and returns the number of characters written. This is useful in low‑latency or embedded contexts where exceptions are disabled.</p><pre><code class="language-cpp">char buf[32]auto result = std::format_to_n(buf, sizeof(buf), "{:04x}", 0x1A3)std::println("{} characters written", result.out - buf)</code></pre><p><code>result.out</code> points just past the last character written, allowing the caller to construct a <code>std::string_view</code> without an extra copy.</p><p>The library also defines <code>std::vformat</code> and <code>std::vprint</code> which take a <code>std::format_args</code> object generated by <code>std::make_format_args</code>. These functions enable runtime‑determined argument lists while still performing compile‑time checks on the format string itself.</p><pre><code class="language-cpp">auto args = std::make_format_args(42, 3.14)std::println(std::vformat("int={}, double={}", args))</code></pre><p>If the format string itself is not a constant expression, the parser cannot validate the placeholders against the arguments at compile time. In that case, the same run‑time checks apply, and mismatches still result in a <code>std::format_error</code>.</p><p>The distinction between compile‑time guarantees and run‑time safety mirrors the earlier discussion of <code>printf</code>. By default the library favours compile‑time safety developers can opt into run‑time flexibility when the application requires it.</p><hr><h2 id="try-this"><a class="header" href="#try-this">Try this</a></h2><p>Write a program that prints a three‑row table. Each column must have a fixed width. The second column contains floating‑point numbers printed with two decimal places and right‑aligned.</p><pre><code class="language-cpp">// Insert your own code here - use std::println and format specifiers.</code></pre><p>When you run the program, the output must look like a tidy table with aligned columns.</p><hr><blockquote><p><strong>NOTE</strong>: All examples in this chapter are compiled and tested with the Clang 22 toolchain using <code>-std=c++26</code>. The <code>book_example</code> macro registers each source file as a test target, and the <code>EXPECT</code> strings verify that the output contains the expected fragments.</p></blockquote>
</main>
<nav class="nav-wrapper" aria-label="Page navigation"> <!-- Mobile navigation buttons --> <a rel="prev" href="ch09-errors-contracts.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span> </a>
<a rel="next prefetch" href="ch11-containers.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span> </a>
<div style="clear: both"></div> </nav> </div> </div>
<nav class="nav-wide-wrapper" aria-label="Page navigation"> <a rel="prev" href="ch09-errors-contracts.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span> </a>
<a rel="next prefetch" href="ch11-containers.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span> </a> </nav>
</div>
<template id=fa-eye><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z"/></svg></span></template> <template id=fa-eye-slash><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z"/></svg></span></template> <template id=fa-copy><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/></svg></span></template> <template id=fa-play><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z"/></svg></span></template> <template id=fa-clock-rotate-left><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z"/></svg></span></template>
<script> window.playground_copyable = true; </script>
<script src="elasticlunr-ef4e11c1.min.js"></script> <script src="mark-09e88c2c.min.js"></script> <script src="searcher-09f2665d.js"></script>
<script src="clipboard-1626706a.min.js"></script> <script src="highlight-abc7f01d.js"></script> <script src="book-609e4cb8.js"></script>
<!-- Custom JS scripts -->
</div> </body></html>