From 3a663dff345b272518caf2e0879064039102696c Mon Sep 17 00:00:00 2001
From: Victor Zverovich The argument visitation API can be used to implement dynamic format
specifiers, for example, width and precision passed as additional formatting
@@ -680,43 +680,48 @@ In many cases formatting can be delegated to standard formatters which makes
manual handling of dynamic specifiers unneccessary, but the latter is still
important for more complex cases. This API can also be used to implement a custom formatting engine, such as
-the one compatible with the Compile-time processing of format strings
T
if the formatter<T>::parse
function is
constexpr
.
-Argument visitation API
+Argument visitation
Argument visitation API
struct Answer {};
template <>
-struct formatter<Answer> {
- int width_arg_index = 0;
-
- // Parses dynamic width in the format "{<digit>}".
- auto parse(parse_context& parse_ctx) {
- auto iter = parse_ctx.begin();
- auto get_char = [&]() { return iter != parse_ctx.end() ? *iter : 0; };
-
- if (get_char() != '{')
- return iter;
- ++iter;
- char c = get_char();
- if (!std::isdigit(c) || (++iter, get_char()) != '}')
- throw format_error("invalid format");
- width_arg_index = c - '0';
- return ++iter;
- }
+ struct formatter<Answer> {
+ int width_arg_index = 0;
+
+ // Parses dynamic width in the format "{<digit>}".
+ auto parse(parse_context& parse_ctx) {
+ auto iter = parse_ctx.begin();
+ auto get_char = [&]() { return iter != parse_ctx.end() ? *iter : 0; };
+
+ if (get_char() != '{')
+ return iter;
+ ++iter;
+ char c = get_char();
+ if (!std::isdigit(c) || (++iter, get_char()) != '}')
+ throw format_error("invalid format");
+ width_arg_index = c - '0';
+ return ++iter;
+ }
- auto format(Answer, format_context& format_ctx) {
- format_arg arg = format_ctx.args().get(width_arg_index);
- int width = visit([](auto value) -> int {
- if constexpr (std::is_integral_v
+ auto format(Answer, format_context& format_ctx) {
+ auto arg = format_ctx.args().get(width_arg_index);
+ int width = visit([](auto value) -> int {
+ if constexpr (!std::is_integral_v<decltype(value)>)
+ throw format_error("width is not integral");
+ else if (value < 0 || value > std::numeric_limits<int>::max())
+ throw format_error("invalid width");
+ else
+ return value;
+ }, arg);
+ return format_to(format_ctx.out(), "{:{}}", 42, width);
+ }
+ };
+
+std::string s = format("{0:{1}}", Answer(), 10);
+// s == " 42"
printf
syntax, to simplify migration
-from legacy formatting methods.printf
syntax, to provide some of the
+benefits of the current proposal to the legacy code.