Difference between revisions of "cpp/utility/format/format to n"
m (→Example: updated.) |
m (→Notes: I mention the bug-110990 because people report it from time to time.) |
||
(13 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
− | {{cpp/title|format_to_n}} | + | {{cpp/title|format_to_n|format_to_n_result}} |
{{cpp/utility/format/navbar}} | {{cpp/utility/format/navbar}} | ||
− | |||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | format }} | + | {{dcl header|format}} |
− | {{dcl | num=1 | since=c++20 |1= | + | {{dcl|num=1|since=c++20|1= |
template< class OutputIt, class... Args > | template< class OutputIt, class... Args > | ||
std::format_to_n_result<OutputIt> | std::format_to_n_result<OutputIt> | ||
format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | ||
− | + | std::format_string<Args...> fmt, Args&&... args ); | |
}} | }} | ||
− | {{dcl | num=2 | since=c++20 |1= | + | {{dcl|num=2|since=c++20|1= |
template< class OutputIt, class... Args > | template< class OutputIt, class... Args > | ||
std::format_to_n_result<OutputIt> | std::format_to_n_result<OutputIt> | ||
format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | ||
− | + | std::wformat_string<Args...> fmt, Args&&... args ); | |
}} | }} | ||
− | {{dcl | num=3 | since=c++20 |1= | + | {{dcl|num=3|since=c++20|1= |
template< class OutputIt, class... Args > | template< class OutputIt, class... Args > | ||
std::format_to_n_result<OutputIt> | std::format_to_n_result<OutputIt> | ||
format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | ||
− | const std::locale& loc, | + | const std::locale& loc, |
+ | std::format_string<Args...> fmt, Args&&... args ); | ||
}} | }} | ||
− | {{dcl | num=4 | since=c++20 |1= | + | {{dcl|num=4|since=c++20|1= |
template< class OutputIt, class... Args > | template< class OutputIt, class... Args > | ||
std::format_to_n_result<OutputIt> | std::format_to_n_result<OutputIt> | ||
format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | format_to_n( OutputIt out, std::iter_difference_t<OutputIt> n, | ||
− | const std::locale& loc, | + | const std::locale& loc, |
+ | std::wformat_string<Args...> fmt, Args&&... args ); | ||
}} | }} | ||
− | {{dcl | num=5 | since=c++20 |1= | + | {{dcl h|Helper types}} |
+ | {{dcl|num=5|since=c++20|1= | ||
template< class OutputIt > | template< class OutputIt > | ||
struct format_to_n_result { | struct format_to_n_result { | ||
Line 37: | Line 39: | ||
{{dcl end}} | {{dcl end}} | ||
− | Format {{ | + | Format {{c|args}} according to the format string {{c|fmt}}, and write the result to the output iterator {{c|out}}. At most {{c|n}} characters are written. If present, {{c|loc}} is used for locale-specific formatting. |
− | Let {{tt|CharT}} be {{c|char}} for overloads {{v|1,3}}, {{ | + | Let {{tt|CharT}} be {{c/core|char}} for overloads {{v|1,3}}, {{co|wchar_t}} for overloads {{v|2,4}}. |
{{cpp/enable if|plural=true| | {{cpp/enable if|plural=true| | ||
{{tt|OutputIt}} satisfies the concept {{c|std::output_iterator<const CharT&>}}. | {{tt|OutputIt}} satisfies the concept {{c|std::output_iterator<const CharT&>}}. | ||
}} | }} | ||
− | The behavior is undefined if {{tt|OutputIt}} does not model (meet the semantic requirements of) the concept {{c|std::output_iterator<const CharT&>}}, or if {{c|std::formatter<Ti, CharT>}} does not meet the {{named req| | + | The behavior is undefined if {{tt|OutputIt}} does not model (meet the semantic requirements of) the concept {{c|std::output_iterator<const CharT&>}}, or if {{c|std::formatter<std::remove_cvref_t<Ti>, CharT>}} does not meet the {{named req|BasicFormatter}} requirements for any {{tt|Ti}} in {{tt|Args}}. |
− | @5@ {{tt|std::format_to_n_result}} has no base classes, or members other than {{ | + | @5@ {{tt|std::format_to_n_result}} has no base classes, or members other than {{c|out}}, {{tt|size}} and implicitly declared special member functions. |
===Parameters=== | ===Parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | out | iterator to the output buffer}} | + | {{par|out|iterator to the output buffer}} |
− | {{par | n | maximum number of characters to be written to the buffer}} | + | {{par|n|maximum number of characters to be written to the buffer}} |
− | {{par | fmt | {{include|cpp/utility/format/format string|const}} }} | + | {{par|fmt|{{include|cpp/utility/format/format string|const}}}} |
− | {{par | args... | arguments to be formatted}} | + | {{par|args...|arguments to be formatted}} |
− | {{par | loc | {{lc|std::locale}} used for locale-specific formatting}} | + | {{par|loc|{{lc|std::locale}} used for locale-specific formatting}} |
{{par end}} | {{par end}} | ||
===Return value=== | ===Return value=== | ||
− | A {{tt|format_to_n_result}} such that the {{ | + | A {{tt|format_to_n_result}} such that the {{c|out}} member is an iterator past the end of the output range, and the {{tt|size}} member is the total (not truncated) output size. |
===Exceptions=== | ===Exceptions=== | ||
Propagates any exception thrown by formatter or iterator operations. | Propagates any exception thrown by formatter or iterator operations. | ||
+ | |||
+ | ===Notes=== | ||
+ | The libstdc++ implementation prior to GCC-13.3 had a [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110990 bug] in reporting the correct {{c|format_to_n_result::out}} value. | ||
===Example=== | ===Example=== | ||
− | {{example | | + | {{example |
− | + | |At Godbolt's Compiler Explorer: [https://godbolt.org/z/s7a5d76ET clang (trunk) + libc++], [https://godbolt.org/z/bdvxnPb1T GCC (trunk) + libstdc++]. | |
+ | |code= | ||
#include <format> | #include <format> | ||
+ | #include <initializer_list> | ||
+ | #include <iomanip> | ||
#include <iostream> | #include <iostream> | ||
#include <string_view> | #include <string_view> | ||
Line 74: | Line 82: | ||
char buffer[64]; | char buffer[64]; | ||
− | + | for (std::size_t max_chars_to_write : {std::size(buffer) - 1, 23uz, 21uz}) | |
− | + | { | |
− | + | const std::format_to_n_result result = | |
− | + | std::format_to_n( | |
− | + | buffer, max_chars_to_write, | |
− | + | "Hubble's H{2} {3} {0}{4}{1} km/sec/Mpc.", // 24 bytes w/o formatters | |
− | + | 71, // {0}, occupies 2 bytes | |
− | + | 8, // {1}, occupies 1 byte | |
− | + | "\u2080", // {2}, occupies 3 bytes, '₀' (SUBSCRIPT ZERO) | |
− | + | "\u2245", // {3}, occupies 3 bytes, '≅' (APPROXIMATELY EQUAL TO) | |
+ | "\u00B1" // {4}, occupies 2 bytes, '±' (PLUS-MINUS SIGN) | ||
+ | ); // 24 + 2 + 1 + 3 + 3 + 2 == 35, no trailing '\0' | ||
− | + | *result.out = '\0'; // adds terminator to buffer | |
− | + | const std::string_view str(buffer, result.out); | |
− | + | ||
− | + | std::cout << "Buffer until '\\0': " << std::quoted(str) << '\n' | |
+ | << "Max chars to write: " << max_chars_to_write << '\n' | ||
+ | << "result.out offset: " << result.out - buffer << '\n' | ||
+ | << "Untruncated output size: " << result.size << "\n\n"; | ||
+ | } | ||
} | } | ||
− | + | |output= | |
− | Buffer: "Hubble's H₀ ≅ 71±8 km/sec/Mpc." | + | Buffer until '\0': "Hubble's H₀ ≅ 71±8 km/sec/Mpc." |
− | Buffer size | + | Max chars to write: 63 |
− | Untruncated output size | + | result.out offset: 35 |
+ | Untruncated output size: 35 | ||
+ | |||
+ | Buffer until '\0': "Hubble's H₀ ≅ 71±8" | ||
+ | Max chars to write: 23 | ||
+ | result.out offset: 23 | ||
+ | Untruncated output size: 35 | ||
+ | |||
+ | Buffer until '\0': "Hubble's H₀ ≅ 71�" | ||
+ | Max chars to write: 21 | ||
+ | result.out offset: 21 | ||
+ | Untruncated output size: 35 | ||
}} | }} | ||
Line 100: | Line 125: | ||
{{dr list begin}} | {{dr list begin}} | ||
{{dr list item|paper=P2216R3|std=C++20|before=throws {{lc|std::format_error}} for invalid format string|after=invalid format string results in compile-time error}} | {{dr list item|paper=P2216R3|std=C++20|before=throws {{lc|std::format_error}} for invalid format string|after=invalid format string results in compile-time error}} | ||
+ | {{dr list item|paper=P2418R2|std=C++20|before=objects that are neither const-usable nor copyable<br>(such as generator-like objects) are not formattable|after=allow formatting these objects}} | ||
+ | {{dr_p2508}} | ||
{{dr list end}} | {{dr list end}} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/utility/format/dsc format}} | + | {{dsc inc|cpp/utility/format/dsc format}} |
− | {{dsc inc | cpp/utility/format/dsc format_to}} | + | {{dsc inc|cpp/utility/format/dsc format_to}} |
− | {{dsc inc | cpp/utility/format/dsc formatted_size}} | + | {{dsc inc|cpp/utility/format/dsc formatted_size}} |
{{dsc end}} | {{dsc end}} | ||
{{langlinks|es|ja|ru|zh}} | {{langlinks|es|ja|ru|zh}} |
Latest revision as of 12:37, 9 July 2024
Defined in header <format>
|
||
template< class OutputIt, class... Args > std::format_to_n_result<OutputIt> |
(1) | (since C++20) |
template< class OutputIt, class... Args > std::format_to_n_result<OutputIt> |
(2) | (since C++20) |
template< class OutputIt, class... Args > std::format_to_n_result<OutputIt> |
(3) | (since C++20) |
template< class OutputIt, class... Args > std::format_to_n_result<OutputIt> |
(4) | (since C++20) |
Helper types |
||
template< class OutputIt > struct format_to_n_result { |
(5) | (since C++20) |
Format args according to the format string fmt, and write the result to the output iterator out. At most n characters are written. If present, loc is used for locale-specific formatting.
Let CharT
be char for overloads (1,3), wchar_t for overloads (2,4).
These overloads participate in overload resolution only if
OutputIt
satisfies the concept std::output_iterator<const CharT&>.
The behavior is undefined if OutputIt
does not model (meet the semantic requirements of) the concept std::output_iterator<const CharT&>, or if std::formatter<std::remove_cvref_t<Ti>, CharT> does not meet the BasicFormatter requirements for any Ti
in Args
.
std::format_to_n_result
has no base classes, or members other than out, size
and implicitly declared special member functions.Contents |
[edit] Parameters
out | - | iterator to the output buffer | ||||||||||||||||||||||||||||||||||||||||||||||
n | - | maximum number of characters to be written to the buffer | ||||||||||||||||||||||||||||||||||||||||||||||
fmt | - |
Each replacement field has the following format:
1) replacement field without a format specification
2) replacement field with a format specification
| ||||||||||||||||||||||||||||||||||||||||||||||
args... | - | arguments to be formatted | ||||||||||||||||||||||||||||||||||||||||||||||
loc | - | std::locale used for locale-specific formatting |
[edit] Return value
A format_to_n_result
such that the out member is an iterator past the end of the output range, and the size
member is the total (not truncated) output size.
[edit] Exceptions
Propagates any exception thrown by formatter or iterator operations.
[edit] Notes
The libstdc++ implementation prior to GCC-13.3 had a bug in reporting the correct format_to_n_result::out value.
[edit] Example
At Godbolt's Compiler Explorer: clang (trunk) + libc++, GCC (trunk) + libstdc++.
#include <format> #include <initializer_list> #include <iomanip> #include <iostream> #include <string_view> int main() { char buffer[64]; for (std::size_t max_chars_to_write : {std::size(buffer) - 1, 23uz, 21uz}) { const std::format_to_n_result result = std::format_to_n( buffer, max_chars_to_write, "Hubble's H{2} {3} {0}{4}{1} km/sec/Mpc.", // 24 bytes w/o formatters 71, // {0}, occupies 2 bytes 8, // {1}, occupies 1 byte "\u2080", // {2}, occupies 3 bytes, '₀' (SUBSCRIPT ZERO) "\u2245", // {3}, occupies 3 bytes, '≅' (APPROXIMATELY EQUAL TO) "\u00B1" // {4}, occupies 2 bytes, '±' (PLUS-MINUS SIGN) ); // 24 + 2 + 1 + 3 + 3 + 2 == 35, no trailing '\0' *result.out = '\0'; // adds terminator to buffer const std::string_view str(buffer, result.out); std::cout << "Buffer until '\\0': " << std::quoted(str) << '\n' << "Max chars to write: " << max_chars_to_write << '\n' << "result.out offset: " << result.out - buffer << '\n' << "Untruncated output size: " << result.size << "\n\n"; } }
Output:
Buffer until '\0': "Hubble's H₀ ≅ 71±8 km/sec/Mpc." Max chars to write: 63 result.out offset: 35 Untruncated output size: 35 Buffer until '\0': "Hubble's H₀ ≅ 71±8" Max chars to write: 23 result.out offset: 23 Untruncated output size: 35 Buffer until '\0': "Hubble's H₀ ≅ 71�" Max chars to write: 21 result.out offset: 21 Untruncated output size: 35
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
P2216R3 | C++20 | throws std::format_error for invalid format string | invalid format string results in compile-time error |
P2418R2 | C++20 | objects that are neither const-usable nor copyable (such as generator-like objects) are not formattable |
allow formatting these objects |
P2508R1 | C++20 | there's no user-visible name for this facility | the name basic_format_string is exposed
|
[edit] See also
(C++20) |
stores formatted representation of the arguments in a new string (function template) |
(C++20) |
writes out formatted representation of its arguments through an output iterator (function template) |
(C++20) |
determines the number of characters necessary to store the formatted representation of its arguments (function template) |