Why isn't it an error if the arguments are more than required in std::format?
B

1

5

The cppref page on std::format says:

It is not an error to provide more arguments than the format string requires:

// OK, produces "Hello world!"
std::format("{} {}!", "Hello", "world", "something"); 

Since std::format has a compile-time check to see if fmt and arguments mismatch, why isn't the example code above taken as an error?

What's the rationale behind?

Buckeye answered 1/2 at 9:58 Comment(8)
"Since std::format has a compile-time check to see if fmt and arguments mismatch" It's because the format string is not required to be available at compile time and it would be a bit annoying if it worked differently for dynamic and static strings.Cordiacordial
No matter fmt is static or dynamic, std::format("{} {}!", "Hello", "world", "something"); seems buggy, and the programmer should be notified. And consider std::format("{}{}", "Hello") is explicitly an error.Buckeye
@n.m.couldbeanAI yes, because it would be super annoying if this is OK: format(msg, arg1, arg2) but it's not OK to write format("value of msg", arg1, arg2). If it's not an error to not use all arguments in the dynamic case (which it's not, for good reason – this would make cases like translation where you might not need all arguments for all languages super annoying), it shouldn't be an error statically either.Cordiacordial
Dynamic strings are actually not allowed in std::format (you need std::vformat for that). The reason why extra arguments are allowed in both cases has nothing to do with compile-time vs run-time checks.Manaker
I didn't even see that this was changed, appears to be a new constraint in C++23? Very odd change.Cordiacordial
If I was to post this as an answer, it would be frowned upon; therefore, here it is as a comment: The spec allows this due to capriciousness.Maddeu
It's not capriciousness just because one finds the result disagreeable. :) It was a fairly well thought out decision. There are some trade-offs and the choice was reasonable.Faggoting
Does this answer your question? How do I check at compile-time if there's enough `{}` placeholders for all arguments?Outcome
M
12

A couple of reasons.

  1. You can use the same argument any number of times in the format string:

     std::fomat("{1},{0},{1}", x, y);
    

    There is no reason to exclude mentioning it zero times.

  2. It actually comes handy in providing localized strings:

     std::vformat(get_string("Preheat the oven to {} degrees"), temp, temp*9/5+32);
    

    The string returned by get_string would contain either {0} or {1}.

Note this has nothing to do with having or not having compile-time or run-time checks. It is (should be) either considered an error or not, regardless of which checks are performed when.

Manaker answered 1/2 at 10:35 Comment(4)
Point 2 is useless since this format string is only runtime evaluated so no checks can be performed at compile time (no matter if there is to many or not enough arguments).Mainly
@MarekR Checks could have been performed at run time, but they are not, for the reason given. Actually the phrasing in the original question "Since std::format has a compile-time check" is dubious. If it should be an error, then it should be an error regardless of having or not having compile-time checks.Manaker
Neither point 1 nor point 2 are valid. Point 1 is about the ability to pass fewer arguments, but the question is asking why the spec allows more arguments. Point 2 is about vformat() but the question is about format().Maddeu
@MikeNakis Point 2 is not. First, the compile-time and run-time versions really should have the same requirements - but also you could still do translation via format (not vformat) by way of a template parameter or the preprocessor.Fallonfallout

© 2022 - 2024 — McMap. All rights reserved.