std::format
has a (compile-time and runtime) format string validation, but one thing not included in this validation is whether there are enough {}
placeholders for all arguments (excessive arguments are silently ignored).
I assume this could be useful in some rare cases (e.g if you generate the format string), but I don’t need it, and I’ve had a few bugs because of this.
Is there anything I can do to check for this compile-time? Possibly by wrapping std::format
in my own function.
Example:
#include <format>
#include <iostream>
int main()
{
std::cout << std::format("{} {}", 1, 2, 3, 4, 5) << '\n'; // Prints `1 2`, no error!
}
NOTE: std::format
does have compile-time format string validation. They just don’t check for this specific issue (excessive arguments).
You might indeed add wrappers:
template <typename... Ts>
struct my_format_string
{
consteval my_format_string(const char* s) :
my_format_string(std::format_string<Ts...>(s))
{}
consteval my_format_string(const std::format_string<Ts...> s) : s(s)
{
// Use proper validation check
// placeholder validation of the placeholders
if (std::count(s.get().begin(), s.get().end(), '{') != sizeof...(Ts)) {
throw 42;
}
}
constexpr auto get() const { return s; }
std::format_string<Ts...> s;
};
template <typename... Ts>
auto my_format(my_format_string<std::type_identity_t<Ts>...> format, Ts... args)
{
return std::vformat(format.getS().get(), std::make_format_args(args...));
}
For std::format you would have to provide everything at compile time so that checking is allready there.
@PepijnKramer This specific thing is not included in the validation, see example: gcc.godbolt.org/z/1q1fGc4Ph
@Someprogrammerdude
std::format
already checks the format string at compile-time using C++20consteval
magic. It’s just that this specific problem isn’t checked. While the compilers might add a warning for this eventually, it should also be possible to do this check from code alone (probably by wrappingstd::format_string<...>
in your own class).FYI github.com/fmtlib/fmt/issues/492
Tried a few ways but it seems that the issue is
std::format
is not failing in a SFINAE-friendly way.Show 4 more comments