3rdparty: Update fmt to 12.1.0

Signed-off-by: SternXD <stern@sidestore.io>
This commit is contained in:
SternXD 2025-11-26 13:18:07 -05:00 committed by Ty
parent 775f381685
commit 98c74b939a
11 changed files with 242 additions and 119 deletions

View File

@ -1,3 +1,77 @@
# 12.1.0 - 2025-10-29
- Optimized `buffer::append`, resulting in up to ~16% improvement on spdlog
benchmarks (https://github.com/fmtlib/fmt/pull/4541). Thanks @fyrsta7.
- Worked around an ABI incompatibility in `std::locale_ref` between clang and
gcc (https://github.com/fmtlib/fmt/issues/4573).
- Made `std::variant` and `std::expected` formatters work with `format_as`
(https://github.com/fmtlib/fmt/issues/4574,
https://github.com/fmtlib/fmt/pull/4575). Thanks @phprus.
- Made `fmt::join<string_view>` work with C++ modules
(https://github.com/fmtlib/fmt/issues/4379,
https://github.com/fmtlib/fmt/pull/4577). Thanks @Arghnews.
- Exported `fmt::is_compiled_string` and `operator""_cf` from the module
(https://github.com/fmtlib/fmt/pull/4544). Thanks @CrackedMatter.
- Fixed a compatibility issue with C++ modules in clang
(https://github.com/fmtlib/fmt/pull/4548). Thanks @tsarn.
- Added support for cv-qualified types to the `std::optional` formatter
(https://github.com/fmtlib/fmt/issues/4561,
https://github.com/fmtlib/fmt/pull/4562). Thanks @OleksandrKvl.
- Added demangling support (used in exception and `std::type_info` formatters)
for libc++ and clang-cl
(https://github.com/fmtlib/fmt/issues/4542,
https://github.com/fmtlib/fmt/pull/4560,
https://github.com/fmtlib/fmt/issues/4568,
https://github.com/fmtlib/fmt/pull/4571).
Thanks @FatihBAKIR and @rohitsutreja.
- Switched to global `malloc`/`free` to enable allocator customization
(https://github.com/fmtlib/fmt/issues/4569,
https://github.com/fmtlib/fmt/pull/4570). Thanks @rohitsutreja.
- Made the `FMT_USE_CONSTEVAL` macro configurable by users
(https://github.com/fmtlib/fmt/pull/4546). Thanks @SnapperTT.
- Fixed compilation with locales disabled in the header-only mode
(https://github.com/fmtlib/fmt/issues/4550).
- Fixed compilation with clang 21 and `-std=c++20`
(https://github.com/fmtlib/fmt/issues/4552).
- Fixed a dynamic linking issue with clang-cl
(https://github.com/fmtlib/fmt/issues/4576,
https://github.com/fmtlib/fmt/pull/4584). Thanks @FatihBAKIR.
- Fixed a warning suppression leakage on gcc
(https://github.com/fmtlib/fmt/pull/4588). Thanks @ZedThree.
- Made more internal color APIs `constexpr`
(https://github.com/fmtlib/fmt/pull/4581). Thanks @ishani.
- Fixed compatibility with clang as a host compiler for NVCC
(https://github.com/fmtlib/fmt/pull/4564). Thanks @valgur.
- Fixed various warnings and lint issues
(https://github.com/fmtlib/fmt/issues/4565,
https://github.com/fmtlib/fmt/pull/4572,
https://github.com/fmtlib/fmt/pull/4557).
Thanks @LiangHuDream and @teruyamato0731.
- Improved documentation
(https://github.com/fmtlib/fmt/issues/4549,
https://github.com/fmtlib/fmt/pull/4551,
https://github.com/fmtlib/fmt/issues/4566,
https://github.com/fmtlib/fmt/pull/4567,
https://github.com/fmtlib/fmt/pull/4578,).
Thanks @teruyamato0731, @petersteneteg and @zimmerman-dev.
# 12.0.0 - 2025-09-17 # 12.0.0 - 2025-09-17
- Optimized the default floating point formatting - Optimized the default floating point formatting

View File

@ -21,7 +21,7 @@
#endif #endif
// The fmt library version in the form major * 10000 + minor * 100 + patch. // The fmt library version in the form major * 10000 + minor * 100 + patch.
#define FMT_VERSION 120000 #define FMT_VERSION 120100
// Detect compiler versions. // Detect compiler versions.
#if defined(__clang__) && !defined(__ibmxl__) #if defined(__clang__) && !defined(__ibmxl__)
@ -114,7 +114,9 @@
#endif #endif
// Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated. // Detect consteval, C++20 constexpr extensions and std::is_constant_evaluated.
#if !defined(__cpp_lib_is_constant_evaluated) #ifdef FMT_USE_CONSTEVAL
// Use the provided definition.
#elif !defined(__cpp_lib_is_constant_evaluated)
# define FMT_USE_CONSTEVAL 0 # define FMT_USE_CONSTEVAL 0
#elif FMT_CPLUSPLUS < 201709L #elif FMT_CPLUSPLUS < 201709L
# define FMT_USE_CONSTEVAL 0 # define FMT_USE_CONSTEVAL 0
@ -234,6 +236,7 @@ FMT_PRAGMA_GCC(optimize("Og"))
# define FMT_GCC_OPTIMIZED # define FMT_GCC_OPTIMIZED
#endif #endif
FMT_PRAGMA_CLANG(diagnostic push) FMT_PRAGMA_CLANG(diagnostic push)
FMT_PRAGMA_GCC(diagnostic push)
#ifdef FMT_ALWAYS_INLINE #ifdef FMT_ALWAYS_INLINE
// Use the provided definition. // Use the provided definition.
@ -414,8 +417,12 @@ inline auto map(int128_opt) -> monostate { return {}; }
inline auto map(uint128_opt) -> monostate { return {}; } inline auto map(uint128_opt) -> monostate { return {}; }
#endif #endif
#ifndef FMT_USE_BITINT #ifdef FMT_USE_BITINT
# define FMT_USE_BITINT (FMT_CLANG_VERSION >= 1500) // Use the provided definition.
#elif FMT_CLANG_VERSION >= 1500 && !defined(__CUDACC__)
# define FMT_USE_BITINT 1
#else
# define FMT_USE_BITINT 0
#endif #endif
#if FMT_USE_BITINT #if FMT_USE_BITINT
@ -918,7 +925,10 @@ class locale_ref {
constexpr locale_ref() : locale_(nullptr) {} constexpr locale_ref() : locale_(nullptr) {}
template <typename Locale, FMT_ENABLE_IF(sizeof(Locale::collate) != 0)> template <typename Locale, FMT_ENABLE_IF(sizeof(Locale::collate) != 0)>
locale_ref(const Locale& loc); locale_ref(const Locale& loc) : locale_(&loc) {
// Check if std::isalpha is found via ADL to reduce the chance of misuse.
isalpha('x', loc);
}
inline explicit operator bool() const noexcept { return locale_ != nullptr; } inline explicit operator bool() const noexcept { return locale_ != nullptr; }
#endif // FMT_USE_LOCALE #endif // FMT_USE_LOCALE
@ -1844,12 +1854,17 @@ template <typename T> class buffer {
void void
append(const U* begin, const U* end) { append(const U* begin, const U* end) {
while (begin != end) { while (begin != end) {
auto size = size_;
auto free_cap = capacity_ - size;
auto count = to_unsigned(end - begin); auto count = to_unsigned(end - begin);
try_reserve(size_ + count); if (free_cap < count) {
auto free_cap = capacity_ - size_; grow_(*this, size + count);
if (free_cap < count) count = free_cap; size = size_;
free_cap = capacity_ - size;
count = count < free_cap ? count : free_cap;
}
// A loop is faster than memcpy on small sizes. // A loop is faster than memcpy on small sizes.
T* out = ptr_ + size_; T* out = ptr_ + size;
for (size_t i = 0; i < count; ++i) out[i] = begin[i]; for (size_t i = 0; i < count; ++i) out[i] = begin[i];
size_ += count; size_ += count;
begin += count; begin += count;
@ -2983,6 +2998,7 @@ FMT_INLINE void println(format_string<T...> fmt, T&&... args) {
return fmt::println(stdout, fmt, static_cast<T&&>(args)...); return fmt::println(stdout, fmt, static_cast<T&&>(args)...);
} }
FMT_PRAGMA_GCC(diagnostic pop)
FMT_PRAGMA_CLANG(diagnostic pop) FMT_PRAGMA_CLANG(diagnostic pop)
FMT_PRAGMA_GCC(pop_options) FMT_PRAGMA_GCC(pop_options)
FMT_END_EXPORT FMT_END_EXPORT

View File

@ -1594,8 +1594,13 @@ class get_locale {
public: public:
inline get_locale(bool localized, locale_ref loc) : has_locale_(localized) { inline get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
if (localized) if (!localized) return;
::new (&locale_) std::locale(loc.template get<std::locale>()); ignore_unused(loc);
::new (&locale_) std::locale(
#if FMT_USE_LOCALE
loc.template get<std::locale>()
#endif
);
} }
inline ~get_locale() { inline ~get_locale() {
if (has_locale_) locale_.~locale(); if (has_locale_) locale_.~locale();

View File

@ -429,7 +429,7 @@ template <typename Char> struct ansi_color_escape {
private: private:
static constexpr size_t num_emphases = 8; static constexpr size_t num_emphases = 8;
Char buffer[7u + 4u * num_emphases]; Char buffer[7u + 4u * num_emphases] = {};
size_t size = 0; size_t size = 0;
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out, static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,

View File

@ -15,9 +15,10 @@
#include "format.h" #include "format.h"
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
FMT_BEGIN_EXPORT
// A compile-time string which is compiled into fast formatting code. // A compile-time string which is compiled into fast formatting code.
FMT_EXPORT class compiled_string {}; class compiled_string {};
template <typename S> template <typename S>
struct is_compiled_string : std::is_base_of<compiled_string, S> {}; struct is_compiled_string : std::is_base_of<compiled_string, S> {};
@ -59,6 +60,8 @@ template <detail::fixed_string Str> constexpr auto operator""_cf() {
} // namespace literals } // namespace literals
#endif #endif
FMT_END_EXPORT
namespace detail { namespace detail {
template <typename T, typename... Tail> template <typename T, typename... Tail>

View File

@ -36,7 +36,7 @@ FMT_BEGIN_NAMESPACE
FMT_FUNC void assert_fail(const char* file, int line, const char* message) { FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
// Use unchecked std::fprintf to avoid triggering another assertion when // Use unchecked std::fprintf to avoid triggering another assertion when
// writing to stderr fails. // writing to stderr fails.
fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message); std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
abort(); abort();
} }
#endif #endif
@ -47,11 +47,6 @@ using std::locale;
using std::numpunct; using std::numpunct;
using std::use_facet; using std::use_facet;
} // namespace detail } // namespace detail
template <typename Locale, enable_if_t<(sizeof(Locale::collate) != 0), int>>
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
static_assert(std::is_same<Locale, std::locale>::value, "");
}
#else #else
namespace detail { namespace detail {
struct locale {}; struct locale {};

View File

@ -40,11 +40,18 @@
#include "base.h" #include "base.h"
// libc++ supports string_view in pre-c++17.
#if FMT_HAS_INCLUDE(<string_view>) && \
(FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
# define FMT_USE_STRING_VIEW
#endif
#ifndef FMT_MODULE #ifndef FMT_MODULE
# include <stdlib.h> // malloc, free
# include <cmath> // std::signbit # include <cmath> // std::signbit
# include <cstddef> // std::byte # include <cstddef> // std::byte
# include <cstdint> // uint32_t # include <cstdint> // uint32_t
# include <cstdlib> // std::malloc, std::free
# include <cstring> // std::memcpy # include <cstring> // std::memcpy
# include <limits> // std::numeric_limits # include <limits> // std::numeric_limits
# include <new> // std::bad_alloc # include <new> // std::bad_alloc
@ -61,11 +68,8 @@
# include <bit> // std::bit_cast # include <bit> // std::bit_cast
# endif # endif
// libc++ supports string_view in pre-c++17. # if defined(FMT_USE_STRING_VIEW)
# if FMT_HAS_INCLUDE(<string_view>) && \
(FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
# include <string_view> # include <string_view>
# define FMT_USE_STRING_VIEW
# endif # endif
# if FMT_MSC_VERSION # if FMT_MSC_VERSION
@ -744,12 +748,12 @@ template <typename T> struct allocator : private std::decay<void> {
auto allocate(size_t n) -> T* { auto allocate(size_t n) -> T* {
FMT_ASSERT(n <= max_value<size_t>() / sizeof(T), ""); FMT_ASSERT(n <= max_value<size_t>() / sizeof(T), "");
T* p = static_cast<T*>(std::malloc(n * sizeof(T))); T* p = static_cast<T*>(malloc(n * sizeof(T)));
if (!p) FMT_THROW(std::bad_alloc()); if (!p) FMT_THROW(std::bad_alloc());
return p; return p;
} }
void deallocate(T* p, size_t) { std::free(p); } void deallocate(T* p, size_t) { free(p); }
constexpr friend auto operator==(allocator, allocator) noexcept -> bool { constexpr friend auto operator==(allocator, allocator) noexcept -> bool {
return true; // All instances of this allocator are equivalent. return true; // All instances of this allocator are equivalent.
@ -759,6 +763,14 @@ template <typename T> struct allocator : private std::decay<void> {
} }
}; };
template <typename Formatter>
FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set)
-> decltype(f.set_debug_format(set)) {
f.set_debug_format(set);
}
template <typename Formatter>
FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {}
} // namespace detail } // namespace detail
FMT_BEGIN_EXPORT FMT_BEGIN_EXPORT
@ -2506,7 +2518,7 @@ FMT_CONSTEXPR20 auto write_fixed(OutputIt out, const DecimalFP& f,
auto grouping = Grouping(loc, specs.localized()); auto grouping = Grouping(loc, specs.localized());
size += grouping.count_separators(exp); size += grouping.count_separators(exp);
return write_padded<Char, align::right>( return write_padded<Char, align::right>(
out, specs, to_unsigned(size), [&](iterator it) { out, specs, static_cast<size_t>(size), [&](iterator it) {
if (s != sign::none) *it++ = detail::getsign<Char>(s); if (s != sign::none) *it++ = detail::getsign<Char>(s);
it = write_significand<Char>(it, f.significand, significand_size, it = write_significand<Char>(it, f.significand, significand_size,
f.exponent, grouping); f.exponent, grouping);

View File

@ -136,10 +136,9 @@ FMT_API std::system_error vwindows_error(int error_code, string_view fmt,
* **Example**: * **Example**:
* *
* // This throws a system_error with the description * // This throws a system_error with the description
* // cannot open file 'madeup': The system cannot find the file * // cannot open file 'foo': The system cannot find the file specified.
* specified. * // or similar (system message may vary) if the file doesn't exist.
* // or similar (system message may vary). * const char *filename = "foo";
* const char *filename = "madeup";
* LPOFSTRUCT of = LPOFSTRUCT(); * LPOFSTRUCT of = LPOFSTRUCT();
* HFILE file = OpenFile(filename, &of, OF_READ); * HFILE file = OpenFile(filename, &of, OF_READ);
* if (file == HFILE_ERROR) { * if (file == HFILE_ERROR) {
@ -365,17 +364,17 @@ FMT_INLINE_VARIABLE constexpr auto buffer_size = detail::buffer_size();
/// A fast buffered output stream for writing from a single thread. Writing from /// A fast buffered output stream for writing from a single thread. Writing from
/// multiple threads without external synchronization may result in a data race. /// multiple threads without external synchronization may result in a data race.
class FMT_API ostream : private detail::buffer<char> { class ostream : private detail::buffer<char> {
private: private:
file file_; file file_;
ostream(cstring_view path, const detail::ostream_params& params); FMT_API ostream(cstring_view path, const detail::ostream_params& params);
static void grow(buffer<char>& buf, size_t); FMT_API static void grow(buffer<char>& buf, size_t);
public: public:
ostream(ostream&& other) noexcept; FMT_API ostream(ostream&& other) noexcept;
~ostream(); FMT_API ~ostream();
operator writer() { operator writer() {
detail::buffer<char>& buf = *this; detail::buffer<char>& buf = *this;

View File

@ -18,6 +18,13 @@
#include "format.h" #include "format.h"
#if FMT_HAS_CPP_ATTRIBUTE(clang::lifetimebound)
# define FMT_LIFETIMEBOUND [[clang::lifetimebound]]
#else
# define FMT_LIFETIMEBOUND
#endif
FMT_PRAGMA_CLANG(diagnostic error "-Wreturn-stack-address")
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
FMT_EXPORT FMT_EXPORT
@ -234,14 +241,6 @@ using range_reference_type =
template <typename Range> template <typename Range>
using uncvref_type = remove_cvref_t<range_reference_type<Range>>; using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
template <typename Formatter>
FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set)
-> decltype(f.set_debug_format(set)) {
f.set_debug_format(set);
}
template <typename Formatter>
FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {}
template <typename T> template <typename T>
struct range_format_kind_ struct range_format_kind_
: std::integral_constant<range_format, : std::integral_constant<range_format,
@ -821,12 +820,12 @@ auto join(Range&& r, string_view sep)
* *
* **Example**: * **Example**:
* *
* auto t = std::tuple<int, char>{1, 'a'}; * auto t = std::tuple<int, char>(1, 'a');
* fmt::print("{}", fmt::join(t, ", ")); * fmt::print("{}", fmt::join(t, ", "));
* // Output: 1, a * // Output: 1, a
*/ */
template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)> template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
FMT_CONSTEXPR auto join(const Tuple& tuple, string_view sep) FMT_CONSTEXPR auto join(const Tuple& tuple FMT_LIFETIMEBOUND, string_view sep)
-> tuple_join_view<Tuple, char> { -> tuple_join_view<Tuple, char> {
return {tuple, sep}; return {tuple, sep};
} }

View File

@ -111,12 +111,17 @@ void write_escaped_path(basic_memory_buffer<Char>& quoted,
#endif // FMT_CPP_LIB_FILESYSTEM #endif // FMT_CPP_LIB_FILESYSTEM
#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT #if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT
template <typename Char, typename OutputIt, typename T>
auto write_escaped_alternative(OutputIt out, const T& v) -> OutputIt { template <typename Char, typename OutputIt, typename T, typename FormatContext>
auto write_escaped_alternative(OutputIt out, const T& v, FormatContext& ctx)
-> OutputIt {
if constexpr (has_to_string_view<T>::value) if constexpr (has_to_string_view<T>::value)
return write_escaped_string<Char>(out, detail::to_string_view(v)); return write_escaped_string<Char>(out, detail::to_string_view(v));
if constexpr (std::is_same_v<T, Char>) return write_escaped_char(out, v); if constexpr (std::is_same_v<T, Char>) return write_escaped_char(out, v);
return write<Char>(out, v);
formatter<std::remove_cv_t<T>, Char> underlying;
maybe_set_debug_format(underlying, true);
return underlying.format(v, ctx);
} }
#endif #endif
@ -139,19 +144,8 @@ template <typename Variant, typename Char> class is_variant_formattable {
#endif // FMT_CPP_LIB_VARIANT #endif // FMT_CPP_LIB_VARIANT
#if FMT_USE_RTTI #if FMT_USE_RTTI
inline auto normalize_libcxx_inline_namespaces(string_view demangled_name_view,
template <typename OutputIt> char* begin) -> string_view {
auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
int status = 0;
size_t size = 0;
std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free);
string_view demangled_name_view;
if (demangled_name_ptr) {
demangled_name_view = demangled_name_ptr.get();
// Normalization of stdlib inline namespace names. // Normalization of stdlib inline namespace names.
// libc++ inline namespaces. // libc++ inline namespaces.
// std::__1::* -> std::* // std::__1::* -> std::*
@ -160,13 +154,12 @@ auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
// std::__cxx11::* -> std::* // std::__cxx11::* -> std::*
// std::filesystem::__cxx11::* -> std::filesystem::* // std::filesystem::__cxx11::* -> std::filesystem::*
if (demangled_name_view.starts_with("std::")) { if (demangled_name_view.starts_with("std::")) {
char* begin = demangled_name_ptr.get();
char* to = begin + 5; // std:: char* to = begin + 5; // std::
for (char *from = to, *end = begin + demangled_name_view.size(); for (const char *from = to, *end = begin + demangled_name_view.size();
from < end;) { from < end;) {
// This is safe, because demangled_name is NUL-terminated. // This is safe, because demangled_name is NUL-terminated.
if (from[0] == '_' && from[1] == '_') { if (from[0] == '_' && from[1] == '_') {
char* next = from + 1; const char* next = from + 1;
while (next < end && *next != ':') next++; while (next < end && *next != ':') next++;
if (next[0] == ':' && next[1] == ':') { if (next[0] == ':' && next[1] == ':') {
from = next + 2; from = next + 2;
@ -177,12 +170,13 @@ auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
} }
demangled_name_view = {begin, detail::to_unsigned(to - begin)}; demangled_name_view = {begin, detail::to_unsigned(to - begin)};
} }
} else { return demangled_name_view;
demangled_name_view = string_view(ti.name());
} }
return detail::write_bytes<char>(out, demangled_name_view);
# elif FMT_MSC_VERSION template <class OutputIt>
const string_view demangled_name(ti.name()); auto normalize_msvc_abi_name(string_view abi_name_view, OutputIt out)
-> OutputIt {
const string_view demangled_name(abi_name_view);
for (size_t i = 0; i < demangled_name.size(); ++i) { for (size_t i = 0; i < demangled_name.size(); ++i) {
auto sub = demangled_name; auto sub = demangled_name;
sub.remove_prefix(i); sub.remove_prefix(i);
@ -201,6 +195,39 @@ auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
if (*sub.begin() != ' ') *out++ = *sub.begin(); if (*sub.begin() != ' ') *out++ = *sub.begin();
} }
return out; return out;
}
template <typename OutputIt>
auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
int status = 0;
size_t size = 0;
std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &free);
string_view demangled_name_view;
if (demangled_name_ptr) {
demangled_name_view = normalize_libcxx_inline_namespaces(
demangled_name_ptr.get(), demangled_name_ptr.get());
} else {
demangled_name_view = string_view(ti.name());
}
return detail::write_bytes<char>(out, demangled_name_view);
# elif FMT_MSC_VERSION && defined(_MSVC_STL_UPDATE)
return normalize_msvc_abi_name(ti.name(), out);
# elif FMT_MSC_VERSION && defined(_LIBCPP_VERSION)
const string_view demangled_name = ti.name();
std::string name_copy(demangled_name.size(), '\0');
// normalize_msvc_abi_name removes class, struct, union etc that MSVC has in
// front of types
name_copy.erase(normalize_msvc_abi_name(demangled_name, name_copy.begin()),
name_copy.end());
// normalize_libcxx_inline_namespaces removes the inline __1, __2, etc
// namespaces libc++ uses for ABI versioning On MSVC ABI + libc++
// environments, we need to eliminate both of them.
const string_view normalized_name =
normalize_libcxx_inline_namespaces(name_copy, name_copy.data());
return detail::write_bytes<char>(out, normalized_name);
# else # else
return detail::write_bytes<char>(out, string_view(ti.name())); return detail::write_bytes<char>(out, string_view(ti.name()));
# endif # endif
@ -255,21 +282,6 @@ template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
#if FMT_CPP_LIB_FILESYSTEM #if FMT_CPP_LIB_FILESYSTEM
class path : public std::filesystem::path {
public:
auto display_string() const -> std::string {
const std::filesystem::path& base = *this;
return fmt::format(FMT_STRING("{}"), base);
}
auto system_string() const -> std::string { return string(); }
auto generic_display_string() const -> std::string {
const std::filesystem::path& base = *this;
return fmt::format(FMT_STRING("{:g}"), base);
}
auto generic_system_string() const -> std::string { return generic_string(); }
};
template <typename Char> struct formatter<std::filesystem::path, Char> { template <typename Char> struct formatter<std::filesystem::path, Char> {
private: private:
format_specs specs_; format_specs specs_;
@ -319,6 +331,21 @@ template <typename Char> struct formatter<std::filesystem::path, Char> {
} }
}; };
class path : public std::filesystem::path {
public:
auto display_string() const -> std::string {
const std::filesystem::path& base = *this;
return fmt::format(FMT_STRING("{}"), base);
}
auto system_string() const -> std::string { return string(); }
auto generic_display_string() const -> std::string {
const std::filesystem::path& base = *this;
return fmt::format(FMT_STRING("{:g}"), base);
}
auto generic_system_string() const -> std::string { return generic_string(); }
};
#endif // FMT_CPP_LIB_FILESYSTEM #endif // FMT_CPP_LIB_FILESYSTEM
template <size_t N, typename Char> template <size_t N, typename Char>
@ -353,25 +380,16 @@ template <typename T, typename Char>
struct formatter<std::optional<T>, Char, struct formatter<std::optional<T>, Char,
std::enable_if_t<is_formattable<T, Char>::value>> { std::enable_if_t<is_formattable<T, Char>::value>> {
private: private:
formatter<T, Char> underlying_; formatter<std::remove_cv_t<T>, Char> underlying_;
static constexpr basic_string_view<Char> optional = static constexpr basic_string_view<Char> optional =
detail::string_literal<Char, 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', detail::string_literal<Char, 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l',
'('>{}; '('>{};
static constexpr basic_string_view<Char> none = static constexpr basic_string_view<Char> none =
detail::string_literal<Char, 'n', 'o', 'n', 'e'>{}; detail::string_literal<Char, 'n', 'o', 'n', 'e'>{};
template <class U>
FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, bool set)
-> decltype(u.set_debug_format(set)) {
u.set_debug_format(set);
}
template <class U>
FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {}
public: public:
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) { FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) {
maybe_set_debug_format(underlying_, true); detail::maybe_set_debug_format(underlying_, true);
return underlying_.parse(ctx); return underlying_.parse(ctx);
} }
@ -407,10 +425,10 @@ struct formatter<std::expected<T, E>, Char,
if (value.has_value()) { if (value.has_value()) {
out = detail::write<Char>(out, "expected("); out = detail::write<Char>(out, "expected(");
if constexpr (!std::is_void<T>::value) if constexpr (!std::is_void<T>::value)
out = detail::write_escaped_alternative<Char>(out, *value); out = detail::write_escaped_alternative<Char>(out, *value, ctx);
} else { } else {
out = detail::write<Char>(out, "unexpected("); out = detail::write<Char>(out, "unexpected(");
out = detail::write_escaped_alternative<Char>(out, value.error()); out = detail::write_escaped_alternative<Char>(out, value.error(), ctx);
} }
*out++ = ')'; *out++ = ')';
return out; return out;
@ -474,7 +492,7 @@ struct formatter<Variant, Char,
FMT_TRY { FMT_TRY {
std::visit( std::visit(
[&](const auto& v) { [&](const auto& v) {
out = detail::write_escaped_alternative<Char>(out, v); out = detail::write_escaped_alternative<Char>(out, v, ctx);
}, },
value); value);
} }
@ -495,6 +513,8 @@ template <> struct formatter<std::error_code> {
bool debug_ = false; bool debug_ = false;
public: public:
FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; }
FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* { FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* {
auto it = ctx.begin(), end = ctx.end(); auto it = ctx.begin(), end = ctx.end();
if (it == end) return it; if (it == end) return it;

View File

@ -10,7 +10,7 @@
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
#if FMT_USE_LOCALE #if FMT_USE_LOCALE
template FMT_API locale_ref::locale_ref(const std::locale& loc); template FMT_API locale_ref::locale_ref(const std::locale& loc); // DEPRECATED!
template FMT_API auto locale_ref::get<std::locale>() const -> std::locale; template FMT_API auto locale_ref::get<std::locale>() const -> std::locale;
#endif #endif