std.format string positions affect all further format specifiers · Issue #10713 · dlang/phobos (original) (raw)

The specification https://dlang.org/library/std/format.html says:
"By default, the arguments are processed in the provided order. With the position parameter it is possible to address arguments directly."

Since every format specifier can have a position, the normal interpretation of these sentences by a programmer is that when one specifies a position, it has an effect on the current format specifier.

What happens at runtime, however, is that the same position is used for all further format specifiers as well!

import std.stdio;
import std.format;

void main (string[] args)
{
  // As expected: Each format specifier consumes the next argument.
  writeln (format ("%*d %d %d %s", 5, 12, 13, 14, 23));
  writeln (format ("%*1$d %d %d %s", 5, 12, 13, 14, 23));
  writeln (format ("%.*d %d %d %s", 5, 12, 13, 14, 23));
  writeln (format ("%.*1$d %d %d %s", 5, 12, 13, 14, 23));

  // BUG: The three format specifiers after %3$d consume the same argument.
  writeln (format ("%3$d %d %d %s %7$d", 5, 12, 23, 24, 25, 26, 99));
  writeln (format ("%d %3$d %d %d %s %7$d", 5, 12, 23, 24, 25, 26, 99));
  writeln (format ("%d %d %3$d %d %d %s %7$d", 5, 12, 23, 24, 25, 26, 99));
  writeln (format ("%d %d %d %3$d %d %d %s %7$d", 5, 12, 23, 24, 25, 26, 99));
}

Compile and run this program (with dmd 2.110).

   12 13 14 23
   12 13 14 23
00012 13 14 23
00012 13 14 23
23 24 25 26 99
5 23 24 25 26 99
5 12 23 24 25 26 99
5 12 23 23 24 25 26 99
   12 13 14 23
   12 13 14 23
00012 13 14 23
00012 13 14 23
23 23 23 23 99
5 23 23 23 23 99
5 12 23 23 23 23 99
5 12 23 23 23 23 23 99