-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Hi,
I'm using {fmt} v12.0.0 with C++20 and have encountered a compilation issue when defining both FMT_HEADER_ONLY and FMT_USE_LOCALE=0.
The Problem
When these two macros are defined simultaneously, the compilation fails with a static_assert error in fmt/format-inl.h:69.
The error seems to be triggered by including <fmt/chrono.h>. It appears that some part of the chrono formatting functionality attempts to get a std::locale, but since FMT_USE_LOCALE=0 is active, fmt::locale is a dummy detail::locale type. This type mismatch causes the static_assert(std::is_same<Locale, locale>::value, ""); to fail.
Compilation Error Log:
In file included from /path/to/project/build/_deps/fmt-src/include/fmt/format.h:4375,
from /path/to/project/build/_deps/fmt-src/include/fmt/base.h:2992,
from /path/to/project/Core/App/app.cpp:3:
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h: In instantiation of 'Locale fmt::v12::locale_ref::get() const [with Locale = std::locale]':
/path/to/project/build/_deps/fmt-src/include/fmt/chrono.h:1598:65: required from here
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h:69:47: error: static assertion failed
69 | static_assert(std::is_same<Locale, locale>::value, "");
| ^~~~~
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h:69:47: note: 'std::integral_constant<bool, false>::value' evaluates to false
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h:73:10: error: could not convert 'fmt::v12::detail::locale()' from 'fmt::v12::detail::locale' to 'std::locale'
73 | return locale();
| ^~~~~~~~
| |
| fmt::v12::detail::locale
make[2]: *** [CMakeFiles/nucleo-g474re.dir/build.make:229: CMakeFiles/nucleo-g474re.dir/Core/App/app.cpp.obj] Error 1
make[1]: *** [CMakeFiles/Makefile2:119: CMakeFiles/nucleo-g474re-dokata.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Related ODR Violation Warning
As a related issue, if I do not define FMT_HEADER_ONLY but still define FMT_USE_LOCALE=0 in my application code (while the {fmt} library itself is likely compiled with default settings), I receive ODR (One Definition Rule) violation warnings.
This is because the layout of locale_ref and context changes based on FMT_USE_LOCALE, leading to inconsistencies between translation units.
Warning Log:
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:912:7: warning: type 'struct locale_ref' violates the C++ One Definition Rule [-Wodr]
912 | class locale_ref {
| ^
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:912:7: note: a different type is defined in another translation unit
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:915:15: note: the first difference of corresponding definitions is field 'locale_'
915 | const void* locale_; // A type-erased pointer to std::locale.
| ^
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:2668:7: warning: type 'struct context' violates the C++ One Definition Rule [-Wodr]
2668 | class context {
| ^
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:2668:7: note: a different type is defined in another translation unit
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:2672:36: note: the first difference of corresponding definitions is field 'loc_'
2672 | FMT_NO_UNIQUE_ADDRESS locale_ref loc_;
| ^
It seems the combination of FMT_HEADER_ONLY and FMT_USE_LOCALE=0 is not fully compatible, especially when headers like <fmt/chrono.h> are used. Is this an intended limitation, or a bug?
Thank you