mirror of
https://github.com/fmtlib/fmt.git
synced 2026-07-30 16:26:27 +08:00
Compare commits
7 Commits
89bb4b5dd1
...
b7fb3c686e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7fb3c686e | ||
|
|
17500e457b | ||
|
|
26c01df3bd | ||
|
|
caf5e48b1c | ||
|
|
2a2d9edb25 | ||
|
|
90567e92d4 | ||
|
|
c851fbe658 |
15
.github/workflows/linux.yml
vendored
15
.github/workflows/linux.yml
vendored
@ -13,6 +13,10 @@ jobs:
|
|||||||
${{matrix.shared && 'Shared' || ''}}
|
${{matrix.shared && 'Shared' || ''}}
|
||||||
${{matrix.cxxflags_extra && 'Sanitize' || ''}}
|
${{matrix.cxxflags_extra && 'Sanitize' || ''}}
|
||||||
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
|
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
|
||||||
|
env:
|
||||||
|
# Run tests in a non-UTC timezone. glibc localtime/strftime honor TZ, so
|
||||||
|
# there is no need for timedatectl, which fails without systemd-timedated.
|
||||||
|
TZ: Europe/Kyiv
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
cxx: [g++-4.9, g++-11, clang++-3.6, clang++-11]
|
cxx: [g++-4.9, g++-11, clang++-3.6, clang++-11]
|
||||||
@ -75,15 +79,14 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
|
||||||
- name: Set timezone
|
|
||||||
run: sudo timedatectl set-timezone 'Europe/Kyiv'
|
|
||||||
|
|
||||||
- name: Install GCC 4.9
|
- name: Install GCC 4.9
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install libatomic1 libc6-dev libgomp1 libitm1 libmpc3
|
sudo apt install libatomic1 libc6-dev libgomp1 libitm1 libmpc3
|
||||||
# https://launchpad.net/ubuntu/xenial/amd64/g++-4.9/4.9.3-13ubuntu2
|
# https://launchpad.net/ubuntu/xenial/amd64/g++-4.9/4.9.3-13ubuntu2
|
||||||
wget --no-verbose \
|
# launchpad periodically returns 503s, so retry to avoid flaky CI.
|
||||||
|
wget --no-verbose --tries=5 --waitretry=10 \
|
||||||
|
--retry-connrefused --retry-on-http-error=503 \
|
||||||
http://launchpadlibrarian.net/230069137/libmpfr4_3.1.3-2_amd64.deb \
|
http://launchpadlibrarian.net/230069137/libmpfr4_3.1.3-2_amd64.deb \
|
||||||
http://launchpadlibrarian.net/253728424/libasan1_4.9.3-13ubuntu2_amd64.deb \
|
http://launchpadlibrarian.net/253728424/libasan1_4.9.3-13ubuntu2_amd64.deb \
|
||||||
http://launchpadlibrarian.net/445346135/libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
http://launchpadlibrarian.net/445346135/libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
||||||
@ -114,7 +117,9 @@ jobs:
|
|||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install libtinfo5
|
sudo apt install libtinfo5
|
||||||
# https://code.launchpad.net/ubuntu/xenial/amd64/clang-3.6/1:3.6.2-3ubuntu2
|
# https://code.launchpad.net/ubuntu/xenial/amd64/clang-3.6/1:3.6.2-3ubuntu2
|
||||||
wget --no-verbose \
|
# launchpad periodically returns 503s, so retry to avoid flaky CI.
|
||||||
|
wget --no-verbose --tries=5 --waitretry=10 \
|
||||||
|
--retry-connrefused --retry-on-http-error=503 \
|
||||||
http://launchpadlibrarian.net/230019046/libffi6_3.2.1-4_amd64.deb \
|
http://launchpadlibrarian.net/230019046/libffi6_3.2.1-4_amd64.deb \
|
||||||
http://launchpadlibrarian.net/445346109/libasan2_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
http://launchpadlibrarian.net/445346109/libasan2_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
||||||
http://launchpadlibrarian.net/445346135/libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
http://launchpadlibrarian.net/445346135/libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
||||||
|
|||||||
67
ChangeLog.md
67
ChangeLog.md
@ -1,3 +1,70 @@
|
|||||||
|
# 12.2.1 - TBD
|
||||||
|
|
||||||
|
- Added a formatter for `std::exception_ptr` that formats the referenced
|
||||||
|
exception (or `none` when null)
|
||||||
|
(https://github.com/fmtlib/fmt/issues/4808,
|
||||||
|
https://github.com/fmtlib/fmt/pull/4819).
|
||||||
|
Thanks @avikivity and @Atlas-Zero.
|
||||||
|
|
||||||
|
- Added unwinding of nested exceptions created via
|
||||||
|
`std::throw_with_nested` to the `std::exception` formatter, joining each
|
||||||
|
level with `": "` (https://github.com/fmtlib/fmt/pull/4844).
|
||||||
|
Thanks @avikivity.
|
||||||
|
|
||||||
|
- Exported the ostream formatters (`fmt::basic_ostream_formatter`,
|
||||||
|
`fmt::ostream_formatter`) and `fmt::streamed` from the C++20 module
|
||||||
|
(https://github.com/fmtlib/fmt/pull/4861). Thanks @avikivity.
|
||||||
|
|
||||||
|
- Optimized 128-bit integer formatting by reducing the value to 64-bit
|
||||||
|
chunks instead of doing repeated 128-bit division, giving a ~5x speedup
|
||||||
|
on full-range values.
|
||||||
|
|
||||||
|
- Fixed handling of out-of-range floating-point durations in chrono
|
||||||
|
formatting (https://github.com/fmtlib/fmt/pull/4802). Thanks @aizu-m.
|
||||||
|
|
||||||
|
- Fixed a hang and assertion failure when printing to a pipe whose read
|
||||||
|
end is closed (https://github.com/fmtlib/fmt/issues/4797).
|
||||||
|
Thanks @nikola-sh.
|
||||||
|
|
||||||
|
- Fixed formatting of out-of-range integers with the `c` presentation
|
||||||
|
type, which previously mangled negative values and silently truncated
|
||||||
|
out-of-range ones (https://github.com/fmtlib/fmt/issues/4839).
|
||||||
|
Thanks @igoloe.
|
||||||
|
|
||||||
|
- Fixed an `FMT_COMPILE` failure for user-defined types formatted via
|
||||||
|
`format_as` (https://github.com/fmtlib/fmt/issues/4794,
|
||||||
|
https://github.com/fmtlib/fmt/pull/4836).
|
||||||
|
Thanks @mjerabek and @upadhyay74aman.
|
||||||
|
|
||||||
|
- Fixed the fallback `uint128` bitwise-not implementation
|
||||||
|
(https://github.com/fmtlib/fmt/pull/4813). Thanks @Vcode2407.
|
||||||
|
|
||||||
|
- Fixed a false positive in `fmt::is_contiguous` by explicitly checking
|
||||||
|
for `operator[]` on the container itself
|
||||||
|
(https://github.com/fmtlib/fmt/pull/4825). Thanks @tearfur.
|
||||||
|
|
||||||
|
- Generated the build-tree CMake export set regardless of `FMT_INSTALL`,
|
||||||
|
so projects consuming {fmt} via `add_subdirectory` or `FetchContent` can
|
||||||
|
export their own `fmt::*`-dependent targets
|
||||||
|
(https://github.com/fmtlib/fmt/issues/4806,
|
||||||
|
https://github.com/fmtlib/fmt/pull/4850). Thanks @Krzmbrzl and @hexonal.
|
||||||
|
|
||||||
|
- Made the `fmt-c` library respect `BUILD_SHARED_LIBS` like the main
|
||||||
|
{fmt} library (https://github.com/fmtlib/fmt/pull/4812). Thanks @jengelh.
|
||||||
|
|
||||||
|
- Skipped `VERSION`/`SOVERSION`/`DEBUG_POSTFIX` on the header-only
|
||||||
|
`INTERFACE` target (https://github.com/fmtlib/fmt/pull/4830).
|
||||||
|
Thanks @soumik15630m.
|
||||||
|
|
||||||
|
- Suppressed the MSVC C4702 (unreachable code) warning
|
||||||
|
(https://github.com/fmtlib/fmt/pull/4822). Thanks @torsten48.
|
||||||
|
|
||||||
|
- Documented that the hexfloat `a`/`A` presentation types always emit the
|
||||||
|
`0x` prefix (https://github.com/fmtlib/fmt/pull/4862). Thanks @ny000815.
|
||||||
|
|
||||||
|
- Fixed a minor formatting issue in the documentation
|
||||||
|
(https://github.com/fmtlib/fmt/pull/4826). Thanks @brooklynwidz.
|
||||||
|
|
||||||
# 12.2.0 - 2026-06-16
|
# 12.2.0 - 2026-06-16
|
||||||
|
|
||||||
- Added a C11 API that brings fast, type-safe formatting to C. The new
|
- Added a C11 API that brings fast, type-safe formatting to C. The new
|
||||||
|
|||||||
@ -92,6 +92,10 @@ Use `format_as` if you want to make your type formattable as some other
|
|||||||
type with the same format specifiers. The `format_as` function should
|
type with the same format specifiers. The `format_as` function should
|
||||||
take an object of your type and return an object of a formattable type.
|
take an object of your type and return an object of a formattable type.
|
||||||
It should be defined in the same namespace as your type.
|
It should be defined in the same namespace as your type.
|
||||||
|
`format_as` cannot be used when a type also matches another `formatter`
|
||||||
|
specialization, such as the range `formatter`, because the specializations
|
||||||
|
would be ambiguous. Disable the conflicting specialization, if possible,
|
||||||
|
or provide an explicit `formatter` specialization instead.
|
||||||
|
|
||||||
Example ([run](https://godbolt.org/z/nvME4arz8)):
|
Example ([run](https://godbolt.org/z/nvME4arz8)):
|
||||||
|
|
||||||
|
|||||||
@ -1059,6 +1059,10 @@ template <typename T> struct is_static_named_arg : std::false_type {};
|
|||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
struct is_named_arg<named_arg<T, Char>> : std::true_type {};
|
struct is_named_arg<named_arg<T, Char>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T> struct is_named_arg<const T> : is_named_arg<T> {};
|
||||||
|
template <typename T>
|
||||||
|
struct is_static_named_arg<const T> : is_static_named_arg<T> {};
|
||||||
|
|
||||||
template <typename T, typename Char = char> struct named_arg : view {
|
template <typename T, typename Char = char> struct named_arg : view {
|
||||||
const Char* name;
|
const Char* name;
|
||||||
const T& value;
|
const T& value;
|
||||||
|
|||||||
@ -165,7 +165,6 @@ void println(std::ostream& os, format_string<T...> fmt, T&&... args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FMT_END_EXPORT
|
FMT_END_EXPORT
|
||||||
|
|
||||||
FMT_END_NAMESPACE
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // FMT_OSTREAM_H_
|
#endif // FMT_OSTREAM_H_
|
||||||
|
|||||||
@ -19,6 +19,5 @@ endif ()
|
|||||||
# Test that a target depending on fmt can itself be exported (#4806).
|
# Test that a target depending on fmt can itself be exported (#4806).
|
||||||
add_library(export-test INTERFACE)
|
add_library(export-test INTERFACE)
|
||||||
target_link_libraries(export-test INTERFACE fmt::fmt)
|
target_link_libraries(export-test INTERFACE fmt::fmt)
|
||||||
export(
|
export(TARGETS export-test
|
||||||
TARGETS export-test
|
FILE ${CMAKE_CURRENT_BINARY_DIR}/export-test-targets.cmake)
|
||||||
FILE ${CMAKE_CURRENT_BINARY_DIR}/export-test-targets.cmake)
|
|
||||||
|
|||||||
@ -163,6 +163,10 @@ TEST(compile_test, named) {
|
|||||||
fmt::format(FMT_COMPILE("{a0} {a1}"), "a0"_a = 41, "a1"_a = 43));
|
fmt::format(FMT_COMPILE("{a0} {a1}"), "a0"_a = 41, "a1"_a = 43));
|
||||||
EXPECT_EQ("41 43",
|
EXPECT_EQ("41 43",
|
||||||
fmt::format(FMT_COMPILE("{a1} {a0}"), "a0"_a = 43, "a1"_a = 41));
|
fmt::format(FMT_COMPILE("{a1} {a0}"), "a0"_a = 43, "a1"_a = 41));
|
||||||
|
|
||||||
|
// A statically-named argument with a format spec compiles to spec_field,
|
||||||
|
// which passes the argument to make_format_args as const (#4866).
|
||||||
|
EXPECT_EQ("4.2", fmt::format(FMT_COMPILE("{arg:3.1f}"), "arg"_a = 4.2));
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,12 +484,13 @@ TEST(compile_test, constexpr_string_format) {
|
|||||||
}
|
}
|
||||||
#endif // FMT_USE_CONSTEXPR_STRING
|
#endif // FMT_USE_CONSTEXPR_STRING
|
||||||
|
|
||||||
namespace {
|
struct type_with_format_as {
|
||||||
struct compile_format_as_type {
|
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
int format_as(compile_format_as_type f) { return f.value; }
|
int format_as(type_with_format_as v) { return v.value; }
|
||||||
}
|
|
||||||
TEST(compile_test, format_as) {
|
TEST(compile_test, format_as) {
|
||||||
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), compile_format_as_type{42}));
|
// Use a format string other than "{}" so that formatting goes through the
|
||||||
}
|
// compiled field path rather than the to_string fast path.
|
||||||
|
EXPECT_EQ("[42]", fmt::format(FMT_COMPILE("[{}]"), type_with_format_as{42}));
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user