fmt icon indicating copy to clipboard operation
fmt copied to clipboard

Compile-time error when mixing named argument with automatic indexing

Open rbrich opened this issue 1 year ago • 2 comments

Minimal reproducer (godbolt):

fmt::print("{} {a}", 1, "a"_a = 2);

I believe this is supposed to compile, but it causes:

on_error("cannot switch from automatic to manual argument indexing");

Are the named arguments considered as "indexed", or is it a bug?

It works with fmt::runtime, so if nothing else, there is a problem with consistency between compile-time and runtime checking.

rbrich avatar Sep 18 '22 08:09 rbrich

Good catch, thanks. We should make the diagnostic consistent but in the meantime you can use manual indexing as a workaround:

fmt::print("{0} {a}", 1, "a"_a = 2);

vitaut avatar Sep 19 '22 18:09 vitaut

Thanks, I know it works with indexed parameters.

Let me add some more details about the use-case: I encountered the issue when I tried to enable compile-time checks for logging in our company, where we already have many messages in code. Changing them to indexed would not practical, nor very nice to the user of such API. The named argument is used to log "strerror", similarly as was common with printf, i.e. original %m is replaced by fmt {m}. This is achieved by adding a named argument "m"_a as the last argument after what user provides in a log function. I also have a similar implementation in open-source here.

It would be nice if such a logging function could have the format checked in compile-time, but I understand that the named argument support is still somewhat experimental.

rbrich avatar Sep 21 '22 12:09 rbrich

@vitaut What do you think about the fix I posted in https://github.com/fmtlib/fmt/pull/3214 ?

rbrich avatar Nov 30 '22 13:11 rbrich

Btw. I don't really understand why it should not work with indexed args.

This doesn't seem any problematic to me:

fmt::format("{} {2}",  1, 2)

Switching back to automatic ({1} {}) should not be allowed, because it's not clear which index should be selected next. But the other way is quite clear (just use the provided index instead of the next automatic one).

rbrich avatar Nov 30 '22 13:11 rbrich

But I see it's the same in Python, so it probably has some reason:

>>> "{} {}".format(1, 2)
'1 2'
>>> "{} {2}".format(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: cannot switch from automatic field numbering to manual field specification
>>> "{} {a}".format(1, a=2)
'1 2'

rbrich avatar Nov 30 '22 13:11 rbrich