* Format enums annotated with fmt::as_identifiers (requires C++26 reflection)
Format an enum as the identifier of the matching enumerator if the enum is
annotated with fmt::as_identifiers:
enum class [[=fmt::as_identifiers]] color { red, green, blue };
fmt::format("{}", color::green); // "green"
Values that don't match any enumerator are represented as their underlying
value in decimal before applying string formatting.
Identifiers are retrieved via C++26 reflection (P2996) and the annotation
via P3394. FMT_USE_REFLECTION is autodetected and can be overridden by the
user; without reflection the header is empty.
The header is also part of the fmt module, but, unlike with headers, whether
it provides anything is decided when the module is compiled, so the module
build detects reflection and enables it if the configured standard allows.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Look up enum identifiers by index when the values are dense
The formatter for enums annotated with fmt::as_identifiers did a linear
search over all enumerators. Build a table indexed by the distance from
the smallest enumerator value instead, with empty string views in the
holes, which reduces the lookup to a bounds check and one load.
The table is only used if at least 70% of its elements are identifiers,
limiting its size to 10/7 of the number of enumerators. Sparser enums
keep using the linear search. Distances are computed in uint64_t so that
enums with negative values and values spanning the whole range of the
underlying type are handled without overflow.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Suppress -Wsfinae-incomplete in format-test on GCC 16
GCC 16 warns when a type is completed after it failed to be complete in a
SFINAE context. format-test does this deliberately to check that formatting
of incomplete types works, so the warning is a false positive there and
breaks the build with -Werror.
* Test GCC 16 on CI
GCC 16 is the first compiler with C++26 reflection support, which is needed
by fmt/enum.h, so add a job that builds with it in C++26 mode. It comes from
the ubuntu-toolchain-r/test PPA since Ubuntu 24.04 only ships GCC 14.
Also report when reflection is not detected to make it visible that
enum-test was skipped.
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The std.h header uses types such as std::atomic and std::atomic_flag.
For the normal build mode, this header does include all the
headers it needs, such as <atomic>.
However when building the C++ module of {fmt}, the std.h header
omits such includes, and instead expects them to be included
beforehand by fmt.cc - which lacked including <atomic>.
This fixes building the C++ module with libc++ 23, which has removed
a number of unnecessary transitive includes.
* use clang-format v17.0.6 to reformat the tree
* tweak some places so that clang-format does not mutate the layout
of code too much
Signed-off-by: Kefu Chai <tchaikov@gmail.com>
2dd4fa8742fdac36468f8d removed all usage of __std_stream because
it is no longer available with clang v17. That commit missed one place
where the header was still used (only used when building with -DFMT_MODULE=ON).
Remove it there too.
See #3654