{"id":28122,"date":"2021-06-09T16:00:28","date_gmt":"2021-06-09T16:00:28","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=28122"},"modified":"2021-06-09T08:31:01","modified_gmt":"2021-06-09T08:31:01","slug":"format-in-visual-studio-2019-version-16-10","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/format-in-visual-studio-2019-version-16-10\/","title":{"rendered":"&lt;format&gt;\u00a0in\u00a0Visual\u00a0Studio\u00a02019 version\u00a016.10"},"content":{"rendered":"<p>C++20 adds a new text formatting facility to the standard library, designed primarily to replace <code>snprintf<\/code> and friends with a fast and type safe interface. The standardized library is based on the existing <a href=\"https:\/\/github.com\/fmtlib\/fmt\">{fmt}<\/a> library, so users of that library will feel at home.<\/p>\n<p>Before diving into how <code>std::format<\/code> works I want to thank Victor Zverovich, Elnar Dakeshov, Casey Carter, and miscco, all of whom made <a href=\"https:\/\/github.com\/microsoft\/STL\/pulls?q=is:pr+label:format+\">substantial contributions<\/a> to this feature, and were the reason why we could complete it so quickly.<\/p>\n<h2>Overview<\/h2>\n<p>To start using <code>&lt;format&gt;<\/code> you just need to be using Visual Studio 2019 version 16.10 or later and you need to be compiling with <code>\/std:c++latest<\/code>. You can get the latest Visual Studio preview <a href=\"https:\/\/visualstudio.microsoft.com\/vs\/preview\/\">here<\/a>.<\/p>\n<p>The simplest and most common way to use <code>&lt;format&gt;<\/code> is to call:<\/p>\n<pre class=\"prettyprint\">template&lt;class... Args&gt;\r\nstring format(string_view fmt, const Args&amp;... args);<\/pre>\n<p><code>fmt<\/code> is the format-string and <code>args<\/code> are the things you\u2019d like to format. The format string consists of some text interspersed with curly brace delimited replacement fields. For example: <code>\"Format arguments: {} {}!\"<\/code> is a format string for formatting two arguments. Each replacement field corresponds to the next argument passed. So <code>std::format(\"Format arguments {} {}!\", 2, 1)<\/code> would produce the string <code>\"Format arguments 2 1!\"<\/code><\/p>\n<p>Format strings can also contain numbered replacement fields, for example <code>\"Format arguments {1} {0}!\"<\/code>. These refer to the numbered argument passed in, starting from zero. Numbered and un-numbered (automatic) replacement fields can not be mixed in the same format string.<\/p>\n<p>There are all sorts of modifiers you can use to change the way a particular parameter is formatted. These are called \u201cformat specifiers\u201d and are specified in the replacement field like so: <code>std::format(\"{:&lt;specifiers&gt;}\", &lt;arg&gt;)<\/code>. Let\u2019s look at an example that has one of everything.<\/p>\n<pre class=\"prettyprint\"><code>std::format(\"{:\ud83d\udc31^+#12.4La}\", 4.f);<\/code><\/pre>\n<p>This returns the string <code>\u201c\ud83d\udc31+1.0000p+2\ud83d\udc31\u201d<\/code> (printing this string out to the console on Windows can be a bit difficult). Let\u2019s go through what each component of the above string told <code>std::format<\/code> to do. First we have<code> \u201c\ud83d\udc31^\u201d<\/code> the \u201cfill and align\u201d part of the format specifiers, saying we\u2019d like our output center aligned and padded with cat emojis. Next we have <code>\u201c+\u201d<\/code>, meaning we\u2019d like a sign character no matter what (the default is <code>\u201c-\u201d<\/code> to only print the<code> \u201c-\u201d<\/code> sign for negatives, and you can also use a space to ask for a minus sign or a space). After that we specify <code>\u201c#\u201d<\/code>, meaning \u201calternate form\u201d. For floats the alternate form causes format to always insert a decimal point. Next we specify <code>\u201c12.4\u201d<\/code> to get a width of 12 and a precision of 4. That means format will use the \u201cfill\u201d and \u201calignment\u201d settings to make sure our output is at least 12 characters wide and the float itself will be printed to 4 digits of precision. Next the <code>\u201cL\u201d<\/code> specifier causes format to use locale specific formatting to print things like decimal separators. Finally <code>\u201ca\u201d<\/code> causes the output to be in hexfloat format. More detailed information about the possible format specifications can be found at <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/format\/formatter#Standard_format_specification\">cppreference<\/a>.<\/p>\n<p>For width and precision specifiers you may reference a format argument instead of using a literal value like so:<\/p>\n<pre class=\"prettyprint\">std::format(\"{0:{1}.{2}}\", 4.2f, 4, 5);<\/pre>\n<p>This results in a width of 4 and a precision of 5. The rules for mixing automatic and manual indexing (don\u2019t do it) still apply, but you can use automatic indexing to reference width and precision as in:<\/p>\n<pre class=\"prettyprint\">std::format(\"{:{}.{}}\", 4.2f, 4, 5);<\/pre>\n<p>The assignment of automatic indices is performed left to right, so the above two examples are equivalent.<\/p>\n<h2>Performance<\/h2>\n<p>In general <code>std::format<\/code> performance should be in the same ballpark as <code>fmt::format<\/code> and <code>snprintf<\/code> if you compile your code with the <code>\/utf-8<\/code> <a href=\"https:\/\/docs.microsoft.com\/en-us\/cpp\/build\/reference\/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-160\">\u00a0<\/a>. If you don\u2019t use the <code>\/utf-8<\/code> option then performance can be significantly degraded because we need to retrieve your system locale to correctly parse the format string. While we\u2019re working to improve performance for this case in a future release we recommend you use <code>\/utf-8<\/code> for the best experience.<\/p>\n<h2>Unicode<\/h2>\n<p><code>std::format<\/code> doesn\u2019t do any transcoding between different text encodings, however it is aware of the \u201cexecution character set\u201d and uses it to interpret the format string. The versions of <code>std::format<\/code> taking a wide (<code>wchar_t<\/code>) format string are <em>always<\/em> interpreted as UTF-16. The versions of <code>std::format<\/code> taking a narrow (char) format string interpret the format string as UTF-8 if we detect the<code> \/utf-8<\/code> (or <code>\/execution-charset:utf-8<\/code>) option. Otherwise we interpret the format string as being encoded in the active system codepage. This means that if you compile your code with a non-UTF-8 execution charset it may not run correctly on systems with a different system codepage setting. There\u2019s also a <em>significant<\/em> performance cost to figuring out the system codepage, so for best performance we recommend you compile with<code> \/utf-8<\/code>. We\u2019re working to improve the performance of format in non-UTF execution character sets in future releases.<\/p>\n<p>Unicode also comes into play when dealing with width and precision specification for strings. When we interpret the format string as UTF-8 or UTF-16 we compute the \u201cestimated width\u201d of a string taking into account a rough estimate of the size of each code-point. If we\u2019re interpreting the format string as a non-Unicode encoding we just estimate the width as the number of code units (not code points) in the string. In a future release we\u2019ll add grapheme clusterization to the width computations for Unicode encodings.<\/p>\n<h2>Locales<\/h2>\n<p>While we always parse the <em>format string<\/em> according to the rules above, the locale used for things like decimal separator positions can be customized. By default no locale is used. If you use the <code>L<\/code> specifier then some locale specific formatting may be used. By default it\u2019s the current global locale as returned by a default constructed <code>std::locale<\/code>, however each formatting function has a version allowing you to pass in your own <code>std::locale<\/code> object to override that behavior.<\/p>\n<h2>Future work<\/h2>\n<p>Over the next few Visual Studio releases we\u2019ll be improving the performance of <code>std::format<\/code>, and fixing bugs. Additionally C++23 will likely add compile time format checking to format literals and we may implement that before 2023 (for code you want to work great in C++23 don\u2019t rely on catching <code>std::format_errors<\/code> from invalid format strings!). C++23 will also make a small change to the definitions of <code>std::vformat_to<\/code> and <code>std::format_to<\/code> that reduces code size but can be observable, for forward compatibility make sure any custom formatters work with all output iterators. More information on these changes can be found in <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2021\/p2216r3.html\">p2216r3<\/a>. C++23 may also bring additional functionality like <code>std::print<\/code> and better ways to handle Unicode text.<\/p>\n<h2>Differences from {fmt} (not exhaustive)<\/h2>\n<p>For those familiar with <code>{fmt}<\/code>, a quick list of differences from the standardized version of the library:<\/p>\n<ul>\n<li>Named arguments are not supported.<\/li>\n<li>None of the miscellaneous formatting functions like <code>fmt::print<\/code> or <code>fmt::printf<\/code> are supported.<\/li>\n<li>Format strings are not checked at compile time<\/li>\n<li>There is no support for automatically formatting types with an <code>std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, const T&amp;)<\/code> overload<\/li>\n<li>The behavior of some format specifiers is slightly different (for example the default alignment for <code>void*<\/code>, and allowing sign specifiers for unsigned types)<\/li>\n<\/ul>\n<h2>Give us feedback<\/h2>\n<p>Try out format in your own code, and file any bugs on our <a href=\"https:\/\/github.com\/microsoft\/STL\/issues\">out GitHub issue tracker<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C++20 adds a new text formatting facility to the standard library, designed primarily to replace snprintf and friends with a fast and type safe interface. The standardized library is based on the existing {fmt} library, so users of that library will feel at home. Before diving into how std::format works I want to thank Victor [&hellip;]<\/p>\n","protected":false},"author":4807,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-28122","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>C++20 adds a new text formatting facility to the standard library, designed primarily to replace snprintf and friends with a fast and type safe interface. The standardized library is based on the existing {fmt} library, so users of that library will feel at home. Before diving into how std::format works I want to thank Victor [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/28122","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/4807"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=28122"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/28122\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=28122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=28122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=28122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}