Closed XZiar closed 1 month ago
Thanks for reporting but compile-time checks are only supported for char
and wchar_t
strings and there are no current plans to implement them for other code unit types. We could make legacy FMT_STRING
be a noop for these but it's probably better to just remove them from your code.
We also hit this while upgrading from 10.2.1 to 11.x.
We try pretty hard to use only char{8,16}_t in our data structures, avoiding things with unspecified/non-portable encoding like std::string and std::wstring, since we build in really interesting environments like winelib (where wchar_t might be libstdc++'s ucs-4, but there's still lots of windows WCHAR
running around that is utf-16 like wchar_t is on MSVC.
compile-time checks are only supported for char and wchar_t strings and there are no current plans to implement them for other code unit types
Interesting. I do see that even where it compiled in fmt 10.x the compile-time check was not actually performed. I.e. a totally incorrect usage like
#include <fmt/format.h>
#include <fmt/xchar.h>
int main() {
(void)fmt::format(FMT_STRING(u8"hello {:x}"),u8"world");
}
compiles just fine in fmt 10.2.x, but crashes at runtime with
terminate called after throwing an instance of 'fmt::v10::format_error' what(): invalid format specifier
whereas changing it to wchar_t detects the problem at compile time
int main() {
(void)fmt::format(FMT_STRING(L"hello {:x}"),L"world");
}
/opt/compiler-explorer/libs/fmt/10.2.1/include/fmt/core.h:2340:27: error: call to non-'constexpr' function 'void fmt::v10::detail::throw_format_error(const char*)' throw_format_error("invalid format specifier");
Interestingly, these did work with char16_t
when we first introduced the use of FMT_STRING
back with fmt 7.1.2
So, just to make the change somewhat more searchable:
FMT_STRING
seems to have actually worked to get compile-time checks with char16_t
, including in c++14 mode. But you did need the macro even in c++20 mode - only char
(not even wchar_t
) seems to get compile-time checking automatically.char
and wchar_t
both get compile time checking even without FMT_STRING
. FMT_STRING
with other types (like char16_t
) still compiles, but quietly became a no-op. Wrong format string/argument pairing for other char types is detected only at runtime.
Seemingly this was intentional, and the functionality to check other kinds of format strings was removed on purpose (might be good documentation update to least mention that in the release notes for 9.0?).FMT_STRING
no longer compiles except with char
or wchar_t
(where it actually works, but is unnecessary since you get that by default in c++20 mode anyway).
It's failing when using
char16_t
orchar32_t
with FMT_STRING infmt 11.x
, but it was working infmt 10.x
.Similar to #3925, PR #3931 only fixed
wchar_t
.godbolt repro: https://godbolt.org/z/q4vqbTEc5
godbolt success for fmt 10.x: https://godbolt.org/z/sT6aKjfjj