diff --git a/external/fmt/.github/workflows/cifuzz.yml b/external/fmt/.github/workflows/cifuzz.yml
index 88144dd9..50182ee9 100644
--- a/external/fmt/.github/workflows/cifuzz.yml
+++ b/external/fmt/.github/workflows/cifuzz.yml
@@ -10,18 +10,20 @@ jobs:
steps:
- name: Build fuzzers
id: build
- uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@92182553173581f871130c71c71b17f003d47b0a # master
+ uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@92182553173581f871130c71c71b17f003d47b0a
with:
oss-fuzz-project-name: 'fmt'
dry-run: false
language: c++
+
- name: Run fuzzers
- uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@92182553173581f871130c71c71b17f003d47b0a # master
+ uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@92182553173581f871130c71c71b17f003d47b0a
with:
oss-fuzz-project-name: 'fmt'
fuzz-seconds: 300
dry-run: false
language: c++
+
- name: Upload crash
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
if: failure() && steps.build.outcome == 'success'
diff --git a/external/fmt/.github/workflows/doc.yml b/external/fmt/.github/workflows/doc.yml
index 3098d458..019a85f1 100644
--- a/external/fmt/.github/workflows/doc.yml
+++ b/external/fmt/.github/workflows/doc.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Add Ubuntu mirrors
run: |
diff --git a/external/fmt/.github/workflows/lint.yml b/external/fmt/.github/workflows/lint.yml
index 51a62f46..cbef56a4 100644
--- a/external/fmt/.github/workflows/lint.yml
+++ b/external/fmt/.github/workflows/lint.yml
@@ -13,14 +13,16 @@ jobs:
format_code:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Install clang-format
- uses: aminya/setup-cpp@290824452986e378826155f3379d31bce8753d76 # v0.37.0
- with:
- clangformat: 17.0.5
+ run: |
+ wget https://apt.llvm.org/llvm.sh
+ sudo bash ./llvm.sh 17
+ sudo apt install clang-format-17
- name: Run clang-format
run: |
- find include src -name '*.h' -o -name '*.cc' | xargs clang-format -i -style=file -fallback-style=none
+ find include src -name '*.h' -o -name '*.cc' | \
+ xargs clang-format-17 -i -style=file -fallback-style=none
git diff --exit-code
diff --git a/external/fmt/.github/workflows/linux.yml b/external/fmt/.github/workflows/linux.yml
index b57814b4..97150467 100644
--- a/external/fmt/.github/workflows/linux.yml
+++ b/external/fmt/.github/workflows/linux.yml
@@ -62,7 +62,7 @@ jobs:
shared: -DBUILD_SHARED_LIBS=ON
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Set timezone
run: sudo timedatectl set-timezone 'Asia/Yekaterinburg'
diff --git a/external/fmt/.github/workflows/macos.yml b/external/fmt/.github/workflows/macos.yml
index 5713c3e8..3543ef57 100644
--- a/external/fmt/.github/workflows/macos.yml
+++ b/external/fmt/.github/workflows/macos.yml
@@ -25,7 +25,7 @@ jobs:
runs-on: '${{ matrix.os }}'
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Set timezone
run: sudo systemsetup -settimezone 'Asia/Yekaterinburg'
diff --git a/external/fmt/.github/workflows/scorecard.yml b/external/fmt/.github/workflows/scorecard.yml
index 9d38f77e..b363a6f8 100644
--- a/external/fmt/.github/workflows/scorecard.yml
+++ b/external/fmt/.github/workflows/scorecard.yml
@@ -29,7 +29,7 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
with:
persist-credentials: false
@@ -60,6 +60,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
+ uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0
with:
sarif_file: results.sarif
diff --git a/external/fmt/.github/workflows/windows.yml b/external/fmt/.github/workflows/windows.yml
index 79ca1814..5403e652 100644
--- a/external/fmt/.github/workflows/windows.yml
+++ b/external/fmt/.github/workflows/windows.yml
@@ -36,7 +36,7 @@ jobs:
standard: 20
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Set timezone
run: tzutil /s "Ekaterinburg Standard Time"
@@ -78,12 +78,12 @@ jobs:
- name: Set timezone
run: tzutil /s "Ekaterinburg Standard Time"
shell: cmd
- - uses: msys2/setup-msys2@5df0ca6cbf14efcd08f8d5bd5e049a3cc8e07fd2 # v2.24.0
+ - uses: msys2/setup-msys2@c52d1fa9c7492275e60fe763540fb601f5f232a1 # v2.25.0
with:
release: false
msystem: ${{matrix.sys}}
pacboy: cc:p cmake:p ninja:p lld:p
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Configure
run: cmake -B ../build -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Debug
env: { LDFLAGS: -fuse-ld=lld }
diff --git a/external/fmt/CMakeLists.txt b/external/fmt/CMakeLists.txt
index 1606e886..586ead51 100644
--- a/external/fmt/CMakeLists.txt
+++ b/external/fmt/CMakeLists.txt
@@ -426,7 +426,9 @@ if (FMT_INSTALL)
endif()
# Install the library and headers.
- install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
+ install(TARGETS ${INSTALL_TARGETS}
+ COMPONENT core
+ EXPORT ${targets_export_name}
LIBRARY DESTINATION ${FMT_LIB_DIR}
ARCHIVE DESTINATION ${FMT_LIB_DIR}
PUBLIC_HEADER DESTINATION "${FMT_INC_DIR}/fmt"
@@ -439,13 +441,15 @@ if (FMT_INSTALL)
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
# Install version, config and target files.
- install(
- FILES ${project_config} ${version_config}
- DESTINATION ${FMT_CMAKE_DIR})
+ install(FILES ${project_config} ${version_config}
+ DESTINATION ${FMT_CMAKE_DIR}
+ COMPONENT core)
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR}
- NAMESPACE fmt::)
+ NAMESPACE fmt::
+ COMPONENT core)
- install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
+ install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}"
+ COMPONENT core)
endif ()
function(add_doc_target)
@@ -481,7 +485,8 @@ function(add_doc_target)
include(GNUInstallDirs)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/
- DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt OPTIONAL)
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt
+ COMPONENT doc OPTIONAL)
endfunction()
if (FMT_DOC)
diff --git a/external/fmt/ChangeLog.md b/external/fmt/ChangeLog.md
index 0eb9ba8e..09ebaed6 100644
--- a/external/fmt/ChangeLog.md
+++ b/external/fmt/ChangeLog.md
@@ -1,6 +1,237 @@
-# 11.1.0 - TBD
+# 11.1.1 - 2024-12-27
-- Improved debug codegen.
+- Fixed ABI compatibility with earlier 11.x versions
+ (https://github.com/fmtlib/fmt/issues/4278).
+
+- Defined CMake components (`core` and `doc`) to allow docs to be installed
+ separately (https://github.com/fmtlib/fmt/pull/4276).
+ Thanks @carlsmedstad.
+
+# 11.1.0 - 2024-12-25
+
+- Improved C++20 module support
+ (https://github.com/fmtlib/fmt/issues/4081,
+ https://github.com/fmtlib/fmt/pull/4083,
+ https://github.com/fmtlib/fmt/pull/4084,
+ https://github.com/fmtlib/fmt/pull/4152,
+ https://github.com/fmtlib/fmt/issues/4153,
+ https://github.com/fmtlib/fmt/pull/4169,
+ https://github.com/fmtlib/fmt/issues/4190,
+ https://github.com/fmtlib/fmt/issues/4234,
+ https://github.com/fmtlib/fmt/pull/4239).
+ Thanks @kamrann and @Arghnews.
+
+- Reduced debug (unoptimized) binary code size and the number of template
+ instantiations when passing formatting arguments. For example, unoptimized
+ binary code size for `fmt::print("{}", 42)` was reduced by ~40% on GCC and
+ ~60% on clang (x86-64).
+
+ GCC:
+ - Before: 161 instructions of which 105 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/s9bGoo4ze)).
+ - After: 116 instructions of which 60 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/r7GGGxMs6)).
+
+ Clang:
+ - Before: 310 instructions of which 251 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/Ts88b7M9o)).
+ - After: 194 instructions of which 135 are in reusable functions
+ ([godbolt](https://www.godbolt.org/z/vcrjP8ceW)).
+
+- Added an experimental `fmt::writer` API that can be used for writing to
+ different destinations such as files or strings
+ (https://github.com/fmtlib/fmt/issues/2354).
+ For example ([godbolt](https://www.godbolt.org/z/rWoKfbP7e)):
+
+ ```c++
+ #include
+
+ void write_text(fmt::writer w) {
+ w.print("The answer is {}.", 42);
+ }
+
+ int main() {
+ // Write to FILE.
+ write_text(stdout);
+
+ // Write to fmt::ostream.
+ auto f = fmt::output_file("myfile");
+ write_text(f);
+
+ // Write to std::string.
+ auto sb = fmt::string_buffer();
+ write_text(sb);
+ std::string s = sb.str();
+ }
+ ```
+
+- Added width and alignment support to the formatter of `std::error_code`.
+
+- Made `std::expected` formattable
+ (https://github.com/fmtlib/fmt/issues/4145,
+ https://github.com/fmtlib/fmt/pull/4148).
+ For example ([godbolt](https://www.godbolt.org/z/hrj5c6G86)):
+
+ ```c++
+ fmt::print("{}", std::expected());
+ ```
+
+ prints
+
+ ```
+ expected()
+ ```
+
+ Thanks @phprus.
+
+- Made `fmt::is_formattable` SFINAE-friendly
+ (https://github.com/fmtlib/fmt/issues/4147).
+
+- Added support for `_BitInt` formatting when using clang
+ (https://github.com/fmtlib/fmt/issues/4007,
+ https://github.com/fmtlib/fmt/pull/4072,
+ https://github.com/fmtlib/fmt/issues/4140,
+ https://github.com/fmtlib/fmt/issues/4173,
+ https://github.com/fmtlib/fmt/pull/4176).
+ For example ([godbolt](https://www.godbolt.org/z/KWjbWec5z)):
+
+ ```c++
+ using int42 = _BitInt(42);
+ fmt::print("{}", int42(100));
+ ```
+
+ Thanks @Arghnews.
+
+- Added the `n` specifier for tuples and pairs
+ (https://github.com/fmtlib/fmt/pull/4107). Thanks @someonewithpc.
+
+- Added support for tuple-like types to `fmt::join`
+ (https://github.com/fmtlib/fmt/issues/4226,
+ https://github.com/fmtlib/fmt/pull/4230). Thanks @phprus.
+
+- Made more types formattable at compile time
+ (https://github.com/fmtlib/fmt/pull/4127). Thanks @AnthonyVH.
+
+- Implemented a more efficient compile-time `fmt::formatted_size`
+ (https://github.com/fmtlib/fmt/issues/4102,
+ https://github.com/fmtlib/fmt/pull/4103). Thanks @phprus.
+
+- Fixed compile-time formatting of some string types
+ (https://github.com/fmtlib/fmt/pull/4065). Thanks @torshepherd.
+
+- Made compiled version of `fmt::format_to` work with
+ `std::back_insert_iterator>`
+ (https://github.com/fmtlib/fmt/issues/4206,
+ https://github.com/fmtlib/fmt/pull/4211). Thanks @phprus.
+
+- Added a formatter for `std::reference_wrapper`
+ (https://github.com/fmtlib/fmt/pull/4163,
+ https://github.com/fmtlib/fmt/pull/4164). Thanks @yfeldblum and @phprus.
+
+- Added experimental padding support (glibc `strftime` extension) to `%m`, `%j`
+ and `%Y` (https://github.com/fmtlib/fmt/pull/4161). Thanks @KKhanhH.
+
+- Made microseconds formatted as `us` instead of `µs` if the Unicode support is
+ disabled (https://github.com/fmtlib/fmt/issues/4088).
+
+- Fixed an unreleased regression in transcoding of surrogate pairs
+ (https://github.com/fmtlib/fmt/issues/4094,
+ https://github.com/fmtlib/fmt/pull/4095). Thanks @phprus.
+
+- Made `fmt::appender` satisfy `std::output_iterator` concept
+ (https://github.com/fmtlib/fmt/issues/4092,
+ https://github.com/fmtlib/fmt/pull/4093). Thanks @phprus.
+
+- Made `std::iterator_traits` standard-conforming
+ (https://github.com/fmtlib/fmt/pull/4185). Thanks @CaseyCarter.
+
+- Made it easier to reuse `fmt::formatter` for types with
+ an implicit conversion to `std::string_view`
+ (https://github.com/fmtlib/fmt/issues/4036,
+ https://github.com/fmtlib/fmt/pull/4055). Thanks @Arghnews.
+
+- Made it possible to disable `` use via `FMT_CPP_LIB_FILESYSTEM`
+ for compatibility with some video game console SDKs, e.g. Nintendo Switch SDK
+ (https://github.com/fmtlib/fmt/issues/4257,
+ https://github.com/fmtlib/fmt/pull/4258,
+ https://github.com/fmtlib/fmt/pull/4259). Thanks @W4RH4WK and @phprus.
+
+- Fixed compatibility with platforms that use 80-bit `long double`
+ (https://github.com/fmtlib/fmt/issues/4245,
+ https://github.com/fmtlib/fmt/pull/4246). Thanks @jsirpoma.
+
+- Added support for UTF-32 code units greater than `0xFFFF` in fill
+ (https://github.com/fmtlib/fmt/issues/4201).
+
+- Fixed handling of legacy encodings on Windows with GCC
+ (https://github.com/fmtlib/fmt/issues/4162).
+
+- Made `fmt::to_string` take `fmt::basic_memory_buffer` by const reference
+ (https://github.com/fmtlib/fmt/issues/4261,
+ https://github.com/fmtlib/fmt/pull/4262). Thanks @sascha-devel.
+
+- Added `fmt::dynamic_format_arg_store::size`
+ (https://github.com/fmtlib/fmt/pull/4270). Thanks @hannes-harnisch.
+
+- Removed the ability to control locale usage via an undocumented
+ `FMT_STATIC_THOUSANDS_SEPARATOR` in favor of `FMT_USE_LOCALE`.
+
+- Renamed `FMT_EXCEPTIONS` to `FMT_USE_EXCEPTIONS` for consistency with other
+ similar macros.
+
+- Improved include directory ordering to reduce the chance of including
+ incorrect headers when using multiple versions of {fmt}
+ (https://github.com/fmtlib/fmt/pull/4116). Thanks @cdzhan.
+
+- Made it possible to compile a subset of {fmt} without the C++ runtime.
+
+- Improved documentation and README
+ (https://github.com/fmtlib/fmt/pull/4066,
+ https://github.com/fmtlib/fmt/issues/4117,
+ https://github.com/fmtlib/fmt/issues/4203,
+ https://github.com/fmtlib/fmt/pull/4235). Thanks @zyctree and @nikola-sh.
+
+- Improved the documentation generator (https://github.com/fmtlib/fmt/pull/4110,
+ https://github.com/fmtlib/fmt/pull/4115). Thanks @rturrado.
+
+- Improved CI (https://github.com/fmtlib/fmt/pull/4155,
+ https://github.com/fmtlib/fmt/pull/4151). Thanks @phprus.
+
+- Fixed various warnings and compilation issues
+ (https://github.com/fmtlib/fmt/issues/2708,
+ https://github.com/fmtlib/fmt/issues/4091,
+ https://github.com/fmtlib/fmt/issues/4109,
+ https://github.com/fmtlib/fmt/issues/4113,
+ https://github.com/fmtlib/fmt/issues/4125,
+ https://github.com/fmtlib/fmt/issues/4129,
+ https://github.com/fmtlib/fmt/pull/4130,
+ https://github.com/fmtlib/fmt/pull/4131,
+ https://github.com/fmtlib/fmt/pull/4132,
+ https://github.com/fmtlib/fmt/issues/4133,
+ https://github.com/fmtlib/fmt/issues/4144,
+ https://github.com/fmtlib/fmt/issues/4150,
+ https://github.com/fmtlib/fmt/issues/4158,
+ https://github.com/fmtlib/fmt/pull/4159,
+ https://github.com/fmtlib/fmt/issues/4160,
+ https://github.com/fmtlib/fmt/pull/4170,
+ https://github.com/fmtlib/fmt/issues/4177,
+ https://github.com/fmtlib/fmt/pull/4187,
+ https://github.com/fmtlib/fmt/pull/4188,
+ https://github.com/fmtlib/fmt/pull/4194,
+ https://github.com/fmtlib/fmt/pull/4200,
+ https://github.com/fmtlib/fmt/issues/4205,
+ https://github.com/fmtlib/fmt/issues/4207,
+ https://github.com/fmtlib/fmt/pull/4208,
+ https://github.com/fmtlib/fmt/pull/4210,
+ https://github.com/fmtlib/fmt/issues/4220,
+ https://github.com/fmtlib/fmt/issues/4231,
+ https://github.com/fmtlib/fmt/issues/4232,
+ https://github.com/fmtlib/fmt/pull/4233,
+ https://github.com/fmtlib/fmt/pull/4236,
+ https://github.com/fmtlib/fmt/pull/4267,
+ https://github.com/fmtlib/fmt/pull/4271).
+ Thanks @torsten48, @Arghnews, @tinfoilboy, @aminya, @Ottani, @zeroomega,
+ @c4v4, @kongy, @vinayyadav3016, @sergio-nsk, @phprus and @YexuanXiao.
# 11.0.2 - 2024-07-20
@@ -272,6 +503,9 @@
- Fixed handling of negative ids in `fmt::basic_format_args::get`
(https://github.com/fmtlib/fmt/pull/3945). Thanks @marlenecota.
+- Fixed handling of a buffer boundary on flush
+ (https://github.com/fmtlib/fmt/issues/4229).
+
- Improved named argument validation
(https://github.com/fmtlib/fmt/issues/3817).
diff --git a/external/fmt/README.md b/external/fmt/README.md
index 5f9249d4..fd845db2 100644
--- a/external/fmt/README.md
+++ b/external/fmt/README.md
@@ -291,6 +291,7 @@ converts to `std::print`.)
- [ccache](https://ccache.dev/): a compiler cache
- [ClickHouse](https://github.com/ClickHouse/ClickHouse): an
analytical database management system
+- [ContextVision](https://www.contextvision.com/): medical imaging software
- [Contour](https://github.com/contour-terminal/contour/): a modern
terminal emulator
- [CUAUV](https://cuauv.org/): Cornell University\'s autonomous
diff --git a/external/fmt/doc/api.md b/external/fmt/doc/api.md
index bf0df731..e86f0b06 100644
--- a/external/fmt/doc/api.md
+++ b/external/fmt/doc/api.md
@@ -269,18 +269,16 @@ that support C++20 `consteval`. On older compilers you can use the
Unused arguments are allowed as in Python's `str.format` and ordinary functions.
-::: basic_format_string
+See [Type Erasure](#type-erasure) for an example of how to enable compile-time
+checks in your own functions with `fmt::format_string` while avoiding template
+bloat.
+
+::: fstring
::: format_string
::: runtime(string_view)
-### Named Arguments
-
-::: arg(const Char*, const T&)
-
-Named arguments are not supported in compile-time checks at the moment.
-
### Type Erasure
You can create your own formatting function with compile-time checks and
@@ -317,6 +315,12 @@ parameterized version.
::: basic_format_arg
+### Named Arguments
+
+::: arg(const Char*, const T&)
+
+Named arguments are not supported in compile-time checks at the moment.
+
### Compatibility
::: basic_string_view
@@ -375,18 +379,17 @@ allocator:
using custom_string =
std::basic_string, custom_allocator>;
- custom_string vformat(custom_allocator alloc, fmt::string_view format_str,
- fmt::format_args args) {
+ auto vformat(custom_allocator alloc, fmt::string_view fmt,
+ fmt::format_args args) -> custom_string {
auto buf = custom_memory_buffer(alloc);
- fmt::vformat_to(std::back_inserter(buf), format_str, args);
+ fmt::vformat_to(std::back_inserter(buf), fmt, args);
return custom_string(buf.data(), buf.size(), alloc);
}
template
- inline custom_string format(custom_allocator alloc,
- fmt::string_view format_str,
- const Args& ... args) {
- return vformat(alloc, format_str, fmt::make_format_args(args...));
+ auto format(custom_allocator alloc, fmt::string_view fmt,
+ const Args& ... args) -> custom_string {
+ return vformat(alloc, fmt, fmt::make_format_args(args...));
}
The allocator will be used for the output container only. Formatting
@@ -410,11 +413,11 @@ locale:
that take `std::locale` as a parameter. The locale type is a template
parameter to avoid the expensive `` include.
-::: format(const Locale&, format_string, T&&...)
+::: format(detail::locale_ref, format_string, T&&...)
-::: format_to(OutputIt, const Locale&, format_string, T&&...)
+::: format_to(OutputIt, detail::locale_ref, format_string, T&&...)
-::: formatted_size(const Locale&, format_string, T&&...)
+::: formatted_size(detail::locale_ref, format_string, T&&...)
### Legacy Compile-Time Checks
@@ -498,10 +501,13 @@ chrono-format-specifications).
- [`std::atomic_flag`](https://en.cppreference.com/w/cpp/atomic/atomic_flag)
- [`std::bitset`](https://en.cppreference.com/w/cpp/utility/bitset)
- [`std::error_code`](https://en.cppreference.com/w/cpp/error/error_code)
+- [`std::exception`](https://en.cppreference.com/w/cpp/error/exception)
- [`std::filesystem::path`](https://en.cppreference.com/w/cpp/filesystem/path)
-- [`std::monostate`](https://en.cppreference.com/w/cpp/utility/variant/monostate)
+- [`std::monostate`](
+ https://en.cppreference.com/w/cpp/utility/variant/monostate)
- [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional)
-- [`std::source_location`](https://en.cppreference.com/w/cpp/utility/source_location)
+- [`std::source_location`](
+ https://en.cppreference.com/w/cpp/utility/source_location)
- [`std::thread::id`](https://en.cppreference.com/w/cpp/thread/thread/id)
- [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant/variant)
@@ -509,7 +515,7 @@ chrono-format-specifications).
::: ptr(const std::shared_ptr&)
-### Formatting Variants
+### Variants
A `std::variant` is only formattable if every variant alternative is
formattable, and requires the `__cpp_lib_variant` [library
@@ -525,15 +531,32 @@ feature](https://en.cppreference.com/w/cpp/feature_test).
fmt::print("{}", std::variant());
// Output: variant(monostate)
+## Bit-Fields and Packed Structs
+
+To format a bit-field or a field of a struct with `__attribute__((packed))`
+applied to it, you need to convert it to the underlying or compatible type via
+a cast or a unary `+` ([godbolt](https://www.godbolt.org/z/3qKKs6T5Y)):
+
+```c++
+struct smol {
+ int bit : 1;
+};
+
+auto s = smol();
+fmt::print("{}", +s.bit);
+```
+
+This is a known limitation of "perfect" forwarding in C++.
+
## Format String Compilation
-`fmt/compile.h` provides format string compilation enabled via the
-`FMT_COMPILE` macro or the `_cf` user-defined literal defined in
-namespace `fmt::literals`. Format strings marked with `FMT_COMPILE`
-or `_cf` are parsed, checked and converted into efficient formatting
-code at compile-time. This supports arguments of built-in and string
-types as well as user-defined types with `format` functions taking
+`fmt/compile.h` provides format string compilation and compile-time
+(`constexpr`) formatting enabled via the `FMT_COMPILE` macro or the `_cf`
+user-defined literal defined in namespace `fmt::literals`. Format strings
+marked with `FMT_COMPILE` or `_cf` are parsed, checked and converted into
+efficient formatting code at compile-time. This supports arguments of built-in
+and string types as well as user-defined types with `format` functions taking
the format context type as a template parameter in their `formatter`
specializations. For example:
diff --git a/external/fmt/doc/get-started.md b/external/fmt/doc/get-started.md
index e61da882..466d1c1b 100644
--- a/external/fmt/doc/get-started.md
+++ b/external/fmt/doc/get-started.md
@@ -202,7 +202,7 @@ For a static build, use the following subproject definition:
For the header-only version, use:
- fmt = subproject('fmt')
+ fmt = subproject('fmt', default_options: ['header-only=true'])
fmt_dep = fmt.get_variable('fmt_header_only_dep')
### Android NDK
diff --git a/external/fmt/doc/index.md b/external/fmt/doc/index.md
index b170f9f2..4f28e114 100644
--- a/external/fmt/doc/index.md
+++ b/external/fmt/doc/index.md
@@ -122,8 +122,8 @@ hide:
The library is highly portable and requires only a minimal subset of
- C++11 features which are available in GCC 4.9, Clang 3.4, MSVC 19.0
- (2015) and later. Newer compiler and standard library features are used
+ C++11 features which are available in GCC 4.9, Clang 3.4, MSVC 19.10
+ (2017) and later. Newer compiler and standard library features are used
if available, and enable additional functionality.
diff --git a/external/fmt/doc/syntax.md b/external/fmt/doc/syntax.md
index 1a44e867..46d7d2fd 100644
--- a/external/fmt/doc/syntax.md
+++ b/external/fmt/doc/syntax.md
@@ -706,12 +706,12 @@ The available padding modifiers (*padding_modifier*) are:
| Type | Meaning |
|-------|-----------------------------------------|
-| `'-'` | Pad a numeric result with spaces. |
-| `'_'` | Do not pad a numeric result string. |
+| `'_'` | Pad a numeric result with spaces. |
+| `'-'` | Do not pad a numeric result string. |
| `'0'` | Pad a numeric result string with zeros. |
These modifiers are only supported for the `'H'`, `'I'`, `'M'`, `'S'`, `'U'`,
-`'V'`, `'W'`, `'m'`, `'j'`, `'Y'` presentation types.
+`'V'`, `'W'`, `'Y'`, `'d'`, `'j'` and `'m'` presentation types.
## Range Format Specifications
diff --git a/external/fmt/include/fmt/args.h b/external/fmt/include/fmt/args.h
index 6ed30c0b..3ff47880 100644
--- a/external/fmt/include/fmt/args.h
+++ b/external/fmt/include/fmt/args.h
@@ -210,6 +210,9 @@ template class dynamic_format_arg_store {
data_.reserve(new_cap);
named_info_.reserve(new_cap_named);
}
+
+ /// Returns the number of elements in the store.
+ size_t size() const noexcept { return data_.size(); }
};
FMT_END_NAMESPACE
diff --git a/external/fmt/include/fmt/base.h b/external/fmt/include/fmt/base.h
index b36faabc..a6948d40 100644
--- a/external/fmt/include/fmt/base.h
+++ b/external/fmt/include/fmt/base.h
@@ -21,7 +21,7 @@
#endif
// The fmt library version in the form major * 10000 + minor * 100 + patch.
-#define FMT_VERSION 110002
+#define FMT_VERSION 110101
// Detect compiler versions.
#if defined(__clang__) && !defined(__ibmxl__)
@@ -146,6 +146,8 @@
// Use the provided definition.
#elif defined(__GNUC__) && !defined(__EXCEPTIONS)
# define FMT_USE_EXCEPTIONS 0
+#elif defined(__clang__) && !defined(__cpp_exceptions)
+# define FMT_USE_EXCEPTIONS 0
#elif FMT_MSC_VERSION && !_HAS_EXCEPTIONS
# define FMT_USE_EXCEPTIONS 0
#else
@@ -159,6 +161,20 @@
# define FMT_CATCH(x) if (false)
#endif
+#ifdef FMT_NO_UNIQUE_ADDRESS
+// Use the provided definition.
+#elif FMT_CPLUSPLUS < 202002L
+// Not supported.
+#elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
+# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
+// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485).
+#elif FMT_MSC_VERSION >= 1929 && !FMT_CLANG_VERSION
+# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
+#endif
+#ifndef FMT_NO_UNIQUE_ADDRESS
+# define FMT_NO_UNIQUE_ADDRESS
+#endif
+
#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
# define FMT_FALLTHROUGH [[fallthrough]]
#elif defined(__clang__)
@@ -332,6 +348,13 @@ struct monostate {
# define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0
#endif
+template constexpr auto min_of(T a, T b) -> T {
+ return a < b ? a : b;
+}
+template constexpr auto max_of(T a, T b) -> T {
+ return a > b ? a : b;
+}
+
namespace detail {
// Suppresses "unused variable" warnings with the method described in
// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
@@ -355,7 +378,9 @@ constexpr auto is_constant_evaluated(bool default_value = false) noexcept
}
// Suppresses "conditional expression is constant" warnings.
-template constexpr auto const_check(T value) -> T { return value; }
+template FMT_ALWAYS_INLINE constexpr auto const_check(T val) -> T {
+ return val;
+}
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
const char* message);
@@ -394,7 +419,7 @@ inline auto map(uint128_opt) -> monostate { return {}; }
#endif
#ifndef FMT_USE_BITINT
-# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1400)
+# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500)
#endif
#if FMT_USE_BITINT
@@ -562,8 +587,8 @@ template class basic_string_view {
// Lexicographically compare this string reference to other.
FMT_CONSTEXPR auto compare(basic_string_view other) const -> int {
- size_t str_size = size_ < other.size_ ? size_ : other.size_;
- int result = detail::compare(data_, other.data_, str_size);
+ int result =
+ detail::compare(data_, other.data_, min_of(size_, other.size_));
if (result != 0) return result;
return size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
}
@@ -714,7 +739,7 @@ class basic_specs {
max_fill_size = 4
};
- unsigned long data_ = 1 << fill_size_shift;
+ size_t data_ = 1 << fill_size_shift;
// Character (code unit) type is erased to prevent template bloat.
char fill_data_[max_fill_size] = {' '};
@@ -793,7 +818,8 @@ class basic_specs {
template constexpr auto fill_unit() const -> Char {
using uchar = unsigned char;
return static_cast(static_cast(fill_data_[0]) |
- (static_cast(fill_data_[1]) << 8));
+ (static_cast(fill_data_[1]) << 8) |
+ (static_cast(fill_data_[2]) << 16));
}
FMT_CONSTEXPR void set_fill(char c) {
@@ -809,12 +835,19 @@ class basic_specs {
unsigned uchar = static_cast>(s[0]);
fill_data_[0] = static_cast(uchar);
fill_data_[1] = static_cast(uchar >> 8);
+ fill_data_[2] = static_cast(uchar >> 16);
return;
}
FMT_ASSERT(size <= max_fill_size, "invalid fill");
for (size_t i = 0; i < size; ++i)
fill_data_[i & 3] = static_cast(s[i]);
}
+
+ FMT_CONSTEXPR void set_fill(const basic_specs& specs) {
+ set_fill_size(specs.fill_size());
+ for (size_t i = 0; i < max_fill_size; ++i)
+ fill_data_[i] = specs.fill_data_[i];
+ }
};
// Format specifiers for built-in and string types.
@@ -842,7 +875,7 @@ template class parse_context {
using char_type = Char;
using iterator = const Char*;
- explicit constexpr parse_context(basic_string_view fmt,
+ constexpr explicit parse_context(basic_string_view fmt,
int next_arg_id = 0)
: fmt_(fmt), next_arg_id_(next_arg_id) {}
@@ -1012,15 +1045,15 @@ template struct named_arg : view {
static_assert(!is_named_arg::value, "nested named arguments");
};
-template constexpr auto count() -> size_t { return B ? 1 : 0; }
-template constexpr auto count() -> size_t {
+template constexpr auto count() -> int { return B ? 1 : 0; }
+template constexpr auto count() -> int {
return (B1 ? 1 : 0) + count();
}
-template constexpr auto count_named_args() -> size_t {
+template constexpr auto count_named_args() -> int {
return count::value...>();
}
-template constexpr auto count_static_named_args() -> size_t {
+template constexpr auto count_static_named_args() -> int {
return count::value...>();
}
@@ -1180,7 +1213,7 @@ class compile_parse_context : public parse_context {
using base = parse_context;
public:
- explicit FMT_CONSTEXPR compile_parse_context(basic_string_view fmt,
+ FMT_CONSTEXPR explicit compile_parse_context(basic_string_view fmt,
int num_args, const type* types,
int next_arg_id = 0)
: base(fmt, next_arg_id), num_args_(num_args), types_(types) {}
@@ -1627,16 +1660,16 @@ template struct arg_pack {};
template
class format_string_checker {
private:
- type types_[NUM_ARGS > 0 ? NUM_ARGS : 1];
- named_arg_info named_args_[NUM_NAMED_ARGS > 0 ? NUM_NAMED_ARGS : 1];
+ type types_[max_of(1, NUM_ARGS)];
+ named_arg_info named_args_[max_of(1, NUM_NAMED_ARGS)];
compile_parse_context context_;
using parse_func = auto (*)(parse_context&) -> const Char*;
- parse_func parse_funcs_[NUM_ARGS > 0 ? NUM_ARGS : 1];
+ parse_func parse_funcs_[max_of(1, NUM_ARGS)];
public:
template
- explicit FMT_CONSTEXPR format_string_checker(basic_string_view fmt,
+ FMT_CONSTEXPR explicit format_string_checker(basic_string_view fmt,
arg_pack)
: types_{mapped_type_constant::value...},
named_args_{},
@@ -1694,7 +1727,7 @@ template class buffer {
protected:
// Don't initialize ptr_ since it is not accessed to save a few cycles.
FMT_MSC_WARNING(suppress : 26495)
- FMT_CONSTEXPR20 buffer(grow_fun grow, size_t sz) noexcept
+ FMT_CONSTEXPR buffer(grow_fun grow, size_t sz) noexcept
: size_(sz), capacity_(sz), grow_(grow) {}
constexpr buffer(grow_fun grow, T* p = nullptr, size_t sz = 0,
@@ -1740,7 +1773,7 @@ template class buffer {
// the new elements may not be initialized.
FMT_CONSTEXPR void try_resize(size_t count) {
try_reserve(count);
- size_ = count <= capacity_ ? count : capacity_;
+ size_ = min_of(count, capacity_);
}
// Tries increasing the buffer capacity to `new_capacity`. It can increase the
@@ -1788,9 +1821,9 @@ template class buffer {
};
struct buffer_traits {
- explicit buffer_traits(size_t) {}
- auto count() const -> size_t { return 0; }
- auto limit(size_t size) -> size_t { return size; }
+ constexpr explicit buffer_traits(size_t) {}
+ constexpr auto count() const -> size_t { return 0; }
+ constexpr auto limit(size_t size) const -> size_t { return size; }
};
class fixed_buffer_traits {
@@ -1799,12 +1832,12 @@ class fixed_buffer_traits {
size_t limit_;
public:
- explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
- auto count() const -> size_t { return count_; }
- auto limit(size_t size) -> size_t {
+ constexpr explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
+ constexpr auto count() const -> size_t { return count_; }
+ FMT_CONSTEXPR auto limit(size_t size) -> size_t {
size_t n = limit_ > count_ ? limit_ - count_ : 0;
count_ += size;
- return size < n ? size : n;
+ return min_of(size, n);
}
};
@@ -1962,15 +1995,37 @@ template class counting_buffer : public buffer {
template
struct is_back_insert_iterator> : std::true_type {};
+template
+struct has_back_insert_iterator_container_append : std::false_type {};
+template
+struct has_back_insert_iterator_container_append<
+ OutputIt, InputIt,
+ void_t())
+ .append(std::declval(),
+ std::declval()))>> : std::true_type {};
+
// An optimized version of std::copy with the output value type (T).
template ::value)>
+ FMT_ENABLE_IF(is_back_insert_iterator::value&&
+ has_back_insert_iterator_container_append<
+ OutputIt, InputIt>::value)>
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
-> OutputIt {
get_container(out).append(begin, end);
return out;
}
+template ::value &&
+ !has_back_insert_iterator_container_append<
+ OutputIt, InputIt>::value)>
+FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
+ -> OutputIt {
+ auto& c = get_container(out);
+ c.insert(c.end(), begin, end);
+ return out;
+}
+
template ::value)>
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
@@ -2146,7 +2201,8 @@ template class value {
template ::value)>
value(const T& named_arg) : value(named_arg.value) {}
- template ::value)>
+ template ::value || !FMT_BUILTIN_TYPES)>
FMT_CONSTEXPR20 FMT_INLINE value(T& x) : value(x, custom_tag()) {}
FMT_ALWAYS_INLINE value(const named_arg_info* args, size_t size)
@@ -2220,9 +2276,12 @@ struct locale_ref {
public:
constexpr locale_ref() : locale_(nullptr) {}
- template explicit locale_ref(const Locale& loc);
- explicit operator bool() const noexcept { return locale_ != nullptr; }
-#endif
+
+ template
+ locale_ref(const Locale& loc);
+
+ inline explicit operator bool() const noexcept { return locale_ != nullptr; }
+#endif // FMT_USE_LOCALE
template auto get() const -> Locale;
};
@@ -2243,16 +2302,15 @@ constexpr auto make_descriptor() -> unsigned long long {
: is_unpacked_bit | NUM_ARGS;
}
-template
+template
using arg_t = conditional_t,
basic_format_arg>;
-template
struct named_arg_store {
// args_[0].named_args points to named_args to avoid bloating format_args.
- // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
- arg_t args[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
+ arg_t args[1 + NUM_ARGS];
named_arg_info named_args[NUM_NAMED_ARGS];
template
@@ -2280,13 +2338,13 @@ struct named_arg_store {
// An array of references to arguments. It can be implicitly converted to
// `basic_format_args` for passing into type-erased formatting functions
// such as `vformat`. It is a plain struct to reduce binary size in debug mode.
-template
struct format_arg_store {
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
using type =
conditional_t[NUM_ARGS != 0 ? NUM_ARGS : +1],
+ arg_t[max_of(1, NUM_ARGS)],
named_arg_store>;
type args;
};
@@ -2372,11 +2430,6 @@ template class basic_appender {
detail::buffer* container;
public:
- using iterator_category = int;
- using value_type = T;
- using pointer = T*;
- using reference = T&;
- using difference_type = decltype(pointer() - pointer());
using container_type = detail::buffer;
FMT_CONSTEXPR basic_appender(detail::buffer& buf) : container(&buf) {}
@@ -2503,7 +2556,7 @@ template class basic_format_args {
return static_cast((desc_ >> shift) & mask);
}
- template
+ template
using store =
detail::format_arg_store;
@@ -2513,14 +2566,14 @@ template class basic_format_args {
constexpr basic_format_args() : desc_(0), args_(nullptr) {}
/// Constructs a `basic_format_args` object from `format_arg_store`.
- template
constexpr FMT_ALWAYS_INLINE basic_format_args(
const store& s)
: desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)),
values_(s.args) {}
- template detail::max_packed_args)>
constexpr basic_format_args(const store& s)
: desc_(DESC | (NUM_NAMED_ARGS != 0 ? +detail::has_named_args_bit : 0)),
@@ -2571,10 +2624,11 @@ template class basic_format_args {
};
// A formatting context.
-class context : private detail::locale_ref {
+class context {
private:
appender out_;
format_args args_;
+ FMT_NO_UNIQUE_ADDRESS detail::locale_ref loc_;
public:
/// The character type for the output.
@@ -2590,24 +2644,26 @@ class context : private detail::locale_ref {
/// in the object so make sure they have appropriate lifetimes.
FMT_CONSTEXPR context(iterator out, format_args args,
detail::locale_ref loc = {})
- : locale_ref(loc), out_(out), args_(args) {}
+ : out_(out), args_(args), loc_(loc) {}
context(context&&) = default;
context(const context&) = delete;
void operator=(const context&) = delete;
FMT_CONSTEXPR auto arg(int id) const -> format_arg { return args_.get(id); }
- auto arg(string_view name) -> format_arg { return args_.get(name); }
- FMT_CONSTEXPR auto arg_id(string_view name) -> int {
+ inline auto arg(string_view name) const -> format_arg {
+ return args_.get(name);
+ }
+ FMT_CONSTEXPR auto arg_id(string_view name) const -> int {
return args_.get_id(name);
}
// Returns an iterator to the beginning of the output range.
- FMT_CONSTEXPR auto out() -> iterator { return out_; }
+ FMT_CONSTEXPR auto out() const -> iterator { return out_; }
// Advances the begin iterator to `it`.
- void advance_to(iterator) {}
+ FMT_CONSTEXPR void advance_to(iterator) {}
- FMT_CONSTEXPR auto locale() -> detail::locale_ref { return *this; }
+ FMT_CONSTEXPR auto locale() const -> detail::locale_ref { return loc_; }
};
template struct runtime_format_string {
@@ -2624,7 +2680,8 @@ template struct runtime_format_string {
*/
inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
-/// A compile-time format string.
+/// A compile-time format string. Use `format_string` in the public API to
+/// prevent type deduction.
template struct fstring {
private:
static constexpr int num_static_named_args =
@@ -2657,8 +2714,9 @@ template struct fstring {
template ::value)>
FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
+ auto sv = string_view(str);
if (FMT_USE_CONSTEVAL)
- detail::parse_format_string(s, checker(s, arg_pack()));
+ detail::parse_format_string(sv, checker(sv, arg_pack()));
#ifdef FMT_ENFORCE_COMPILE_STRING
static_assert(
FMT_USE_CONSTEVAL && sizeof(s) != 0,
@@ -2711,8 +2769,8 @@ struct formatter(),
+ int NUM_ARGS = sizeof...(T),
+ int NUM_NAMED_ARGS = detail::count_named_args(),
unsigned long long DESC = detail::make_descriptor()>
constexpr FMT_ALWAYS_INLINE auto make_format_args(T&... args)
-> detail::format_arg_store {
@@ -2851,7 +2909,7 @@ FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args);
template
FMT_INLINE void print(format_string fmt, T&&... args) {
vargs va = {{args...}};
- if (!detail::use_utf8)
+ if (detail::const_check(!detail::use_utf8))
return detail::vprint_mojibake(stdout, fmt.str, va, false);
return detail::is_locking() ? vprint_buffered(stdout, fmt.str, va)
: vprint(fmt.str, va);
@@ -2868,7 +2926,8 @@ FMT_INLINE void print(format_string fmt, T&&... args) {
template
FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) {
vargs va = {{args...}};
- if (!detail::use_utf8) return detail::vprint_mojibake(f, fmt.str, va, false);
+ if (detail::const_check(!detail::use_utf8))
+ return detail::vprint_mojibake(f, fmt.str, va, false);
return detail::is_locking() ? vprint_buffered(f, fmt.str, va)
: vprint(f, fmt.str, va);
}
@@ -2878,8 +2937,9 @@ FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) {
template
FMT_INLINE void println(FILE* f, format_string fmt, T&&... args) {
vargs va = {{args...}};
- return detail::use_utf8 ? vprintln(f, fmt.str, va)
- : detail::vprint_mojibake(f, fmt.str, va, true);
+ return detail::const_check(detail::use_utf8)
+ ? vprintln(f, fmt.str, va)
+ : detail::vprint_mojibake(f, fmt.str, va, true);
}
/// Formats `args` according to specifications in `fmt` and writes the output
diff --git a/external/fmt/include/fmt/chrono.h b/external/fmt/include/fmt/chrono.h
index 5472eae0..abf3671e 100644
--- a/external/fmt/include/fmt/chrono.h
+++ b/external/fmt/include/fmt/chrono.h
@@ -444,7 +444,7 @@ struct is_same_arithmetic_type
std::is_floating_point::value)> {
};
-inline void throw_duration_error() {
+FMT_NORETURN inline void throw_duration_error() {
FMT_THROW(format_error("cannot format duration"));
}
@@ -540,24 +540,24 @@ inline auto localtime(std::time_t time) -> std::tm {
std::time_t time_;
std::tm tm_;
- dispatcher(std::time_t t) : time_(t) {}
+ inline dispatcher(std::time_t t) : time_(t) {}
- auto run() -> bool {
+ inline auto run() -> bool {
using namespace fmt::detail;
return handle(localtime_r(&time_, &tm_));
}
- auto handle(std::tm* tm) -> bool { return tm != nullptr; }
+ inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
- auto handle(detail::null<>) -> bool {
+ inline auto handle(detail::null<>) -> bool {
using namespace fmt::detail;
return fallback(localtime_s(&tm_, &time_));
}
- auto fallback(int res) -> bool { return res == 0; }
+ inline auto fallback(int res) -> bool { return res == 0; }
#if !FMT_MSC_VERSION
- auto fallback(detail::null<>) -> bool {
+ inline auto fallback(detail::null<>) -> bool {
using namespace fmt::detail;
std::tm* tm = std::localtime(&time_);
if (tm) tm_ = *tm;
@@ -591,24 +591,24 @@ inline auto gmtime(std::time_t time) -> std::tm {
std::time_t time_;
std::tm tm_;
- dispatcher(std::time_t t) : time_(t) {}
+ inline dispatcher(std::time_t t) : time_(t) {}
- auto run() -> bool {
+ inline auto run() -> bool {
using namespace fmt::detail;
return handle(gmtime_r(&time_, &tm_));
}
- auto handle(std::tm* tm) -> bool { return tm != nullptr; }
+ inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
- auto handle(detail::null<>) -> bool {
+ inline auto handle(detail::null<>) -> bool {
using namespace fmt::detail;
return fallback(gmtime_s(&tm_, &time_));
}
- auto fallback(int res) -> bool { return res == 0; }
+ inline auto fallback(int res) -> bool { return res == 0; }
#if !FMT_MSC_VERSION
- auto fallback(detail::null<>) -> bool {
+ inline auto fallback(detail::null<>) -> bool {
std::tm* tm = std::gmtime(&time_);
if (tm) tm_ = *tm;
return tm != nullptr;
@@ -912,7 +912,9 @@ template struct null_chrono_spec_handler {
};
struct tm_format_checker : null_chrono_spec_handler {
- FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); }
+ FMT_NORETURN inline void unsupported() {
+ FMT_THROW(format_error("no format"));
+ }
template
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
@@ -1069,7 +1071,7 @@ void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) {
}
} else if (precision > 0) {
*out++ = '.';
- leading_zeroes = (std::min)(leading_zeroes, precision);
+ leading_zeroes = min_of(leading_zeroes, precision);
int remaining = precision - leading_zeroes;
out = detail::fill_n(out, leading_zeroes, '0');
if (remaining < num_digits) {
@@ -1572,7 +1574,7 @@ class tm_writer {
struct chrono_format_checker : null_chrono_spec_handler {
bool has_precision_integral = false;
- FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); }
+ FMT_NORETURN inline void unsupported() { FMT_THROW(format_error("no date")); }
template
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
@@ -1693,14 +1695,14 @@ class get_locale {
bool has_locale_ = false;
public:
- get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
+ inline get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
if (localized)
::new (&locale_) std::locale(loc.template get());
}
- ~get_locale() {
+ inline ~get_locale() {
if (has_locale_) locale_.~locale();
}
- operator const std::locale&() const {
+ inline operator const std::locale&() const {
return has_locale_ ? locale_ : get_classic_locale();
}
};
diff --git a/external/fmt/include/fmt/compile.h b/external/fmt/include/fmt/compile.h
index c33427ab..68b451c7 100644
--- a/external/fmt/include/fmt/compile.h
+++ b/external/fmt/include/fmt/compile.h
@@ -42,11 +42,10 @@ struct is_compiled_string : std::is_base_of {};
#endif
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
-template Str>
+template Str>
struct udl_compiled_string : compiled_string {
using char_type = Char;
- explicit constexpr operator basic_string_view() const {
+ constexpr explicit operator basic_string_view() const {
return {Str.data, N - 1};
}
};
@@ -525,9 +524,9 @@ FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args)
template ::value)>
void print(std::FILE* f, const S& fmt, const Args&... args) {
- memory_buffer buffer;
- fmt::format_to(std::back_inserter(buffer), fmt, args...);
- detail::print(f, {buffer.data(), buffer.size()});
+ auto buf = memory_buffer();
+ fmt::format_to(appender(buf), fmt, args...);
+ detail::print(f, {buf.data(), buf.size()});
}
template constexpr auto operator""_cf() {
+template constexpr auto operator""_cf() {
using char_t = remove_cvref_t;
return detail::udl_compiled_string();
diff --git a/external/fmt/include/fmt/format-inl.h b/external/fmt/include/fmt/format-inl.h
index e4dd7ea8..14c65a09 100644
--- a/external/fmt/include/fmt/format-inl.h
+++ b/external/fmt/include/fmt/format-inl.h
@@ -26,6 +26,10 @@
# include
#endif
+#ifndef FMT_FUNC
+# define FMT_FUNC
+#endif
+
FMT_BEGIN_NAMESPACE
namespace detail {
@@ -59,8 +63,8 @@ FMT_FUNC void format_error_code(detail::buffer& out, int error_code,
FMT_ASSERT(out.size() <= inline_buffer_size, "");
}
-FMT_FUNC void report_error(format_func func, int error_code,
- const char* message) noexcept {
+FMT_FUNC void do_report_error(format_func func, int error_code,
+ const char* message) noexcept {
memory_buffer full_message;
func(full_message, error_code, message);
// Don't use fwrite_all because the latter may throw.
@@ -80,7 +84,7 @@ using std::locale;
using std::numpunct;
using std::use_facet;
-template
+template >
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
static_assert(std::is_same::value, "");
}
@@ -130,7 +134,9 @@ FMT_FUNC auto write_loc(appender out, loc_value value,
FMT_FUNC void report_error(const char* message) {
#if FMT_USE_EXCEPTIONS
- throw format_error(message);
+ // Use FMT_THROW instead of throw to avoid bogus unreachable code warnings
+ // from MSVC.
+ FMT_THROW(format_error(message));
#else
fputs(message, stderr);
abort();
@@ -1430,7 +1436,7 @@ FMT_FUNC void format_system_error(detail::buffer& out, int error_code,
FMT_FUNC void report_system_error(int error_code,
const char* message) noexcept {
- report_error(format_system_error, error_code, message);
+ do_report_error(format_system_error, error_code, message);
}
FMT_FUNC auto vformat(string_view fmt, format_args args) -> std::string {
diff --git a/external/fmt/include/fmt/format.h b/external/fmt/include/fmt/format.h
index 880d948b..c9a6054d 100644
--- a/external/fmt/include/fmt/format.h
+++ b/external/fmt/include/fmt/format.h
@@ -41,13 +41,12 @@
#include "base.h"
#ifndef FMT_MODULE
-# include // std::signbit
-# include // std::byte
-# include // uint32_t
-# include // std::memcpy
-# include // std::initializer_list
-# include // std::numeric_limits
-# include // std::bad_alloc
+# include // std::signbit
+# include // std::byte
+# include // uint32_t
+# include // std::memcpy
+# include // std::numeric_limits
+# include // std::bad_alloc
# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)
// Workaround for pre gcc 5 libstdc++.
# include // std::allocator_traits
@@ -56,7 +55,7 @@
# include // std::string
# include // std::system_error
-// Checking FMT_CPLUSPLUS for warning suppression in MSVC.
+// Check FMT_CPLUSPLUS to avoid a warning in MSVC.
# if FMT_HAS_INCLUDE() && FMT_CPLUSPLUS > 201703L
# include // std::bit_cast
# endif
@@ -69,7 +68,7 @@
# endif
# if FMT_MSC_VERSION
-# include // _BitScanReverse[64], _BitScanForward[64], _umul128
+# include // _BitScanReverse[64], _umul128
# endif
#endif // FMT_MODULE
@@ -119,11 +118,13 @@
#endif
namespace std {
-template <> struct iterator_traits {
+template struct iterator_traits> {
using iterator_category = output_iterator_tag;
- using value_type = char;
- using reference = char&;
- using difference_type = fmt::appender::difference_type;
+ using value_type = T;
+ using difference_type =
+ decltype(static_cast(nullptr) - static_cast(nullptr));
+ using pointer = void;
+ using reference = void;
};
} // namespace std
@@ -147,22 +148,8 @@ FMT_END_NAMESPACE
# else
# define FMT_THROW(x) \
::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
-# endif
-#endif
-
-#ifdef FMT_NO_UNIQUE_ADDRESS
-// Use the provided definition.
-#elif FMT_CPLUSPLUS < 202002L
-// Not supported.
-#elif FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
-# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
-// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485).
-#elif FMT_MSC_VERSION >= 1929 && !FMT_CLANG_VERSION
-# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
-#endif
-#ifndef FMT_NO_UNIQUE_ADDRESS
-# define FMT_NO_UNIQUE_ADDRESS
-#endif
+# endif // FMT_USE_EXCEPTIONS
+#endif // FMT_THROW
// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
// integer formatter template instantiations to just one by only using the
@@ -172,6 +159,14 @@ FMT_END_NAMESPACE
# define FMT_REDUCE_INT_INSTANTIATIONS 0
#endif
+FMT_BEGIN_NAMESPACE
+
+template
+struct is_contiguous>
+ : std::true_type {};
+
+namespace detail {
+
// __builtin_clz is broken in clang with Microsoft codegen:
// https://github.com/fmtlib/fmt/issues/519.
#if !FMT_MSC_VERSION
@@ -183,49 +178,30 @@ FMT_END_NAMESPACE
# endif
#endif
-// __builtin_ctz is broken in Intel Compiler Classic on Windows:
-// https://github.com/fmtlib/fmt/issues/2510.
-#ifndef __ICL
-# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
- defined(__NVCOMPILER)
-# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
-# endif
-# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
- FMT_ICC_VERSION || defined(__NVCOMPILER)
-# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
-# endif
-#endif
-
-// Some compilers masquerade as both MSVC and GCC-likes or otherwise support
+// Some compilers masquerade as both MSVC and GCC but otherwise support
// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
// MSVC intrinsics if the clz and clzll builtins are not available.
-#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
- !defined(FMT_BUILTIN_CTZLL)
-FMT_BEGIN_NAMESPACE
-namespace detail {
+#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL)
// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
-# if !defined(__clang__)
-# pragma intrinsic(_BitScanForward)
+# ifndef __clang__
# pragma intrinsic(_BitScanReverse)
-# if defined(_WIN64)
-# pragma intrinsic(_BitScanForward64)
+# ifdef _WIN64
# pragma intrinsic(_BitScanReverse64)
# endif
# endif
inline auto clz(uint32_t x) -> int {
+ FMT_ASSERT(x != 0, "");
+ FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
unsigned long r = 0;
_BitScanReverse(&r, x);
- FMT_ASSERT(x != 0, "");
- // Static analysis complains about using uninitialized data
- // "r", but the only way that can happen is if "x" is 0,
- // which the callers guarantee to not happen.
- FMT_MSC_WARNING(suppress : 6102)
return 31 ^ static_cast(r);
}
# define FMT_BUILTIN_CLZ(n) detail::clz(n)
inline auto clzll(uint64_t x) -> int {
+ FMT_ASSERT(x != 0, "");
+ FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
unsigned long r = 0;
# ifdef _WIN64
_BitScanReverse64(&r, x);
@@ -236,48 +212,10 @@ inline auto clzll(uint64_t x) -> int {
// Scan the low 32 bits.
_BitScanReverse(&r, static_cast(x));
# endif
- FMT_ASSERT(x != 0, "");
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
return 63 ^ static_cast(r);
}
# define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
-
-inline auto ctz(uint32_t x) -> int {
- unsigned long r = 0;
- _BitScanForward(&r, x);
- FMT_ASSERT(x != 0, "");
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
- return static_cast(r);
-}
-# define FMT_BUILTIN_CTZ(n) detail::ctz(n)
-
-inline auto ctzll(uint64_t x) -> int {
- unsigned long r = 0;
- FMT_ASSERT(x != 0, "");
- FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
-# ifdef _WIN64
- _BitScanForward64(&r, x);
-# else
- // Scan the low 32 bits.
- if (_BitScanForward(&r, static_cast(x))) return static_cast(r);
- // Scan the high 32 bits.
- _BitScanForward(&r, static_cast(x >> 32));
- r += 32;
-# endif
- return static_cast(r);
-}
-# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
-} // namespace detail
-FMT_END_NAMESPACE
-#endif
-
-FMT_BEGIN_NAMESPACE
-
-template
-struct is_contiguous>
- : std::true_type {};
-
-namespace detail {
+#endif // FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL)
FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) {
ignore_unused(condition);
@@ -372,13 +310,14 @@ class uint128_fallback {
-> uint128_fallback {
return {~n.hi_, ~n.lo_};
}
- friend auto operator+(const uint128_fallback& lhs,
- const uint128_fallback& rhs) -> uint128_fallback {
+ friend FMT_CONSTEXPR auto operator+(const uint128_fallback& lhs,
+ const uint128_fallback& rhs)
+ -> uint128_fallback {
auto result = uint128_fallback(lhs);
result += rhs;
return result;
}
- friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
+ friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs)
-> uint128_fallback {
FMT_ASSERT(lhs.hi_ == 0, "");
uint64_t hi = (lhs.lo_ >> 32) * rhs;
@@ -386,7 +325,7 @@ class uint128_fallback {
uint64_t new_lo = (hi << 32) + lo;
return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
}
- friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
+ friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs)
-> uint128_fallback {
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
}
@@ -466,17 +405,17 @@ template <> constexpr auto num_bits() -> int { return 128; }
// and 128-bit pointers to uint128_fallback.
template sizeof(From))>
inline auto bit_cast(const From& from) -> To {
- constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned));
+ constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned short));
struct data_t {
- unsigned value[static_cast(size)];
+ unsigned short value[static_cast(size)];
} data = bit_cast(from);
auto result = To();
if (const_check(is_big_endian())) {
for (int i = 0; i < size; ++i)
- result = (result << num_bits()) | data.value[i];
+ result = (result << num_bits()) | data.value[i];
} else {
for (int i = size - 1; i >= 0; --i)
- result = (result << num_bits()) | data.value[i];
+ result = (result << num_bits()) | data.value[i];
}
return result;
}
@@ -552,8 +491,8 @@ constexpr auto to_pointer(OutputIt, size_t) -> T* {
template
FMT_CONSTEXPR20 auto to_pointer(basic_appender it, size_t n) -> T* {
buffer& buf = get_container(it);
+ buf.try_reserve(buf.size() + n);
auto size = buf.size();
- buf.try_reserve(size + n);
if (buf.capacity() < size + n) return nullptr;
buf.try_resize(size + n);
return buf.data() + size;
@@ -674,7 +613,8 @@ FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) {
auto num_chars_left = to_unsigned(s.data() + s.size() - p);
if (num_chars_left == 0) return;
- FMT_ASSERT(num_chars_left < block_size, "");
+ // Suppress bogus -Wstringop-overflow.
+ if (FMT_GCC_VERSION) num_chars_left &= 3;
char buf[2 * block_size - 1] = {};
copy(p, p + num_chars_left, buf);
const char* buf_ptr = buf;
@@ -728,8 +668,7 @@ FMT_CONSTEXPR inline auto compute_width(string_view s) -> size_t {
template
inline auto code_point_index(basic_string_view s, size_t n) -> size_t {
- size_t size = s.size();
- return n < size ? n : size;
+ return min_of(n, s.size());
}
// Calculates the index of the nth code point in a UTF-8 string.
@@ -796,11 +735,6 @@ using is_double_double = bool_constant::digits == 106>;
# define FMT_USE_FULL_CACHE_DRAGONBOX 0
#endif
-template
-struct is_locale : std::false_type {};
-template
-struct is_locale> : std::true_type {};
-
// An allocator that uses malloc/free to allow removing dependency on the C++
// standard libary runtime.
template struct allocator {
@@ -862,7 +796,7 @@ class basic_memory_buffer : public detail::buffer {
if (size > new_capacity)
new_capacity = size;
else if (new_capacity > max_size)
- new_capacity = size > max_size ? size : max_size;
+ new_capacity = max_of(size, max_size);
T* old_data = buf.data();
T* new_data = self.alloc_.allocate(new_capacity);
// Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
@@ -880,7 +814,7 @@ class basic_memory_buffer : public detail::buffer {
using value_type = T;
using const_reference = const T&;
- FMT_CONSTEXPR20 explicit basic_memory_buffer(
+ FMT_CONSTEXPR explicit basic_memory_buffer(
const Allocator& alloc = Allocator())
: detail::buffer(grow), alloc_(alloc) {
this->set(store_, SIZE);
@@ -928,7 +862,7 @@ class basic_memory_buffer : public detail::buffer {
/// Resizes the buffer to contain `count` elements. If T is a POD type new
/// elements may not be initialized.
- FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); }
+ FMT_CONSTEXPR void resize(size_t count) { this->try_resize(count); }
/// Increases the buffer capacity to `new_capacity`.
void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
@@ -943,7 +877,7 @@ class basic_memory_buffer : public detail::buffer {
using memory_buffer = basic_memory_buffer;
template
-FMT_NODISCARD auto to_string(basic_memory_buffer& buf)
+FMT_NODISCARD auto to_string(const basic_memory_buffer& buf)
-> std::string {
auto size = buf.size();
detail::assume(size < std::string().max_size());
@@ -960,8 +894,8 @@ class writer {
FILE* file_;
public:
- writer(FILE* f) : buf_(nullptr), file_(f) {}
- writer(detail::buffer& buf) : buf_(&buf) {}
+ inline writer(FILE* f) : buf_(nullptr), file_(f) {}
+ inline writer(detail::buffer& buf) : buf_(&buf) {}
/// Formats `args` according to specifications in `fmt` and writes the
/// output to the file.
@@ -979,24 +913,16 @@ class string_buffer {
detail::container_buffer buf_;
public:
- string_buffer() : buf_(str_) {}
+ inline string_buffer() : buf_(str_) {}
- operator writer() { return buf_; }
- std::string& str() { return str_; }
+ inline operator writer() { return buf_; }
+ inline std::string& str() { return str_; }
};
template
struct is_contiguous> : std::true_type {
};
-FMT_END_EXPORT
-namespace detail {
-FMT_API auto write_console(int fd, string_view text) -> bool;
-FMT_API void print(FILE*, string_view);
-} // namespace detail
-
-FMT_BEGIN_EXPORT
-
// Suppress a misleading warning in older versions of clang.
FMT_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables")
@@ -1006,124 +932,36 @@ class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error {
using std::runtime_error::runtime_error;
};
-namespace detail_exported {
-#if FMT_USE_NONTYPE_TEMPLATE_ARGS
+class loc_value;
+
+FMT_END_EXPORT
+namespace detail {
+FMT_API auto write_console(int fd, string_view text) -> bool;
+FMT_API void print(FILE*, string_view);
+} // namespace detail
+
+namespace detail {
template struct fixed_string {
- constexpr fixed_string(const Char (&str)[N]) {
- detail::copy(static_cast(str),
- str + N, data);
+ FMT_CONSTEXPR20 fixed_string(const Char (&s)[N]) {
+ detail::copy(static_cast(s), s + N,
+ data);
}
Char data[N] = {};
};
-#endif // FMT_USE_NONTYPE_TEMPLATE_ARGS
// Converts a compile-time string to basic_string_view.
-template
+FMT_EXPORT template
constexpr auto compile_string_to_view(const Char (&s)[N])
-> basic_string_view {
// Remove trailing NUL character if needed. Won't be present if this is used
// with a raw character array (i.e. not defined as a string).
return {s, N - (std::char_traits::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
}
-template
+FMT_EXPORT template
constexpr auto compile_string_to_view(basic_string_view s)
-> basic_string_view {
return s;
}
-} // namespace detail_exported
-
-// A generic formatting context with custom output iterator and character
-// (code unit) support. Char is the format string code unit type which can be
-// different from OutputIt::value_type.
-template class generic_context {
- private:
- OutputIt out_;
- basic_format_args args_;
- detail::locale_ref loc_;
-
- public:
- using char_type = Char;
- using iterator = OutputIt;
- using parse_context_type FMT_DEPRECATED = parse_context;
- template
- using formatter_type FMT_DEPRECATED = formatter;
- enum { builtin_types = FMT_BUILTIN_TYPES };
-
- constexpr generic_context(OutputIt out,
- basic_format_args args,
- detail::locale_ref loc = {})
- : out_(out), args_(args), loc_(loc) {}
- generic_context(generic_context&&) = default;
- generic_context(const generic_context&) = delete;
- void operator=(const generic_context&) = delete;
-
- constexpr auto arg(int id) const -> basic_format_arg {
- return args_.get(id);
- }
- auto arg(basic_string_view name) -> basic_format_arg {
- return args_.get(name);
- }
- FMT_CONSTEXPR auto arg_id(basic_string_view name) -> int {
- return args_.get_id(name);
- }
-
- FMT_CONSTEXPR auto out() -> iterator { return out_; }
-
- void advance_to(iterator it) {
- if (!detail::is_back_insert_iterator()) out_ = it;
- }
-
- FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; }
-};
-
-class loc_value {
- private:
- basic_format_arg value_;
-
- public:
- template ::value)>
- loc_value(T value) : value_(value) {}
-
- template ::value)>
- loc_value(T) {}
-
- template auto visit(Visitor&& vis) -> decltype(vis(0)) {
- return value_.visit(vis);
- }
-};
-
-// A locale facet that formats values in UTF-8.
-// It is parameterized on the locale to avoid the heavy include.
-template class format_facet : public Locale::facet {
- private:
- std::string separator_;
- std::string grouping_;
- std::string decimal_point_;
-
- protected:
- virtual auto do_put(appender out, loc_value val,
- const format_specs& specs) const -> bool;
-
- public:
- static FMT_API typename Locale::id id;
-
- explicit format_facet(Locale& loc);
- explicit format_facet(string_view sep = "",
- std::initializer_list g = {3},
- std::string decimal_point = ".")
- : separator_(sep.data(), sep.size()),
- grouping_(g.begin(), g.end()),
- decimal_point_(decimal_point) {}
-
- auto put(appender out, loc_value val, const format_specs& specs) const
- -> bool {
- return do_put(out, val, specs);
- }
-};
-
-FMT_END_EXPORT
-
-namespace detail {
// Returns true if value is negative, false otherwise.
// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
@@ -1302,6 +1140,17 @@ template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
return decimal_point_impl(loc);
}
+#ifndef FMT_HEADER_ONLY
+FMT_BEGIN_EXPORT
+extern template FMT_API auto thousands_sep_impl