From c47161e573ddd0a3a686e7be567959acee3b1020 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Wed, 24 Jul 2024 20:31:22 +0500 Subject: [PATCH] Restore constexpr fmt::formatted_size for C++20 Signed-off-by: Vladislav Shchapov --- include/fmt/base.h | 29 +++++++++++++++++------------ include/fmt/compile.h | 3 ++- include/fmt/format.h | 8 +++++--- test/compile-test.cc | 2 +- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index 19cf4916b1900..1569556dd04eb 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -494,7 +494,8 @@ struct is_back_insert_iterator< // Extracts a reference to the container from *insert_iterator. template -inline auto get_container(OutputIt it) -> typename OutputIt::container_type& { +FMT_CONSTEXPR inline auto get_container(OutputIt it) -> + typename OutputIt::container_type& { struct accessor : OutputIt { accessor(OutputIt base) : OutputIt(base) {} using OutputIt::container; @@ -924,7 +925,8 @@ template class buffer { } /// Appends data to the end of the buffer. - template void append(const U* begin, const U* end) { + template + FMT_CONSTEXPR void append(const U* begin, const U* end) { while (begin != end) { auto count = to_unsigned(end - begin); try_reserve(size_ + count); @@ -1105,7 +1107,7 @@ template class counting_buffer : public buffer { public: FMT_CONSTEXPR counting_buffer() : buffer(grow, data_, 0, buffer_size) {} - auto count() -> size_t { return count_ + this->size(); } + constexpr auto count() const -> size_t { return count_ + this->size(); } }; } // namespace detail @@ -1155,7 +1157,8 @@ template class basic_appender { private: detail::buffer* buffer_; - friend auto get_container(basic_appender app) -> detail::buffer& { + friend constexpr auto get_container(basic_appender app) + -> detail::buffer& { return *app.buffer_; } @@ -1170,13 +1173,13 @@ template class basic_appender { FMT_CONSTEXPR basic_appender(detail::buffer& buf) : buffer_(&buf) {} - auto operator=(T c) -> basic_appender& { + FMT_CONSTEXPR auto operator=(T c) -> basic_appender& { buffer_->push_back(c); return *this; } - auto operator*() -> basic_appender& { return *this; } - auto operator++() -> basic_appender& { return *this; } - auto operator++(int) -> basic_appender { return *this; } + FMT_CONSTEXPR auto operator*() -> basic_appender& { return *this; } + FMT_CONSTEXPR auto operator++() -> basic_appender& { return *this; } + FMT_CONSTEXPR auto operator++(int) -> basic_appender { return *this; } }; using appender = basic_appender; @@ -1188,7 +1191,7 @@ struct is_back_insert_iterator> : std::true_type {}; // An optimized version of std::copy with the output value type (T). template ::value)> -auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { +FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { get_container(out).append(begin, end); return out; } @@ -2898,7 +2901,9 @@ template class basic_format_string { } basic_format_string(runtime_format_string fmt) : str_(fmt.str) {} - FMT_ALWAYS_INLINE operator basic_string_view() const { return str_; } + FMT_ALWAYS_INLINE constexpr operator basic_string_view() const { + return str_; + } auto get() const -> basic_string_view { return str_; } }; @@ -3016,8 +3021,8 @@ FMT_INLINE auto format_to(char (&out)[N], format_string fmt, T&&... args) /// Returns the number of chars in the output of `format(fmt, args...)`. template -FMT_NODISCARD FMT_INLINE auto formatted_size(format_string fmt, - T&&... args) -> size_t { +FMT_NODISCARD FMT_CONSTEXPR20 FMT_INLINE auto formatted_size( + format_string fmt, T&&... args) -> size_t { auto buf = detail::counting_buffer<>(); detail::vformat_to(buf, fmt, fmt::make_format_args(args...), {}); return buf.count(); diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 8a632f635ce8b..49d077e0c8917 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -488,7 +488,8 @@ auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args) template ::value)> -auto formatted_size(const S& fmt, const Args&... args) -> size_t { +FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args) + -> size_t { auto buf = detail::counting_buffer<>(); fmt::format_to(appender(buf), fmt, args...); return buf.count(); diff --git a/include/fmt/format.h b/include/fmt/format.h index 71ae4ac7104a1..a7a7f95c5dc40 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -522,7 +522,7 @@ template = 307 && !FMT_ICC_VERSION __attribute__((no_sanitize("undefined"))) #endif -inline auto +FMT_CONSTEXPR20 inline auto reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* { auto& c = get_container(it); size_t size = c.size(); @@ -531,7 +531,8 @@ reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* { } template -inline auto reserve(basic_appender it, size_t n) -> basic_appender { +FMT_CONSTEXPR20 inline auto reserve(basic_appender it, size_t n) + -> basic_appender { buffer& buf = get_container(it); buf.try_reserve(buf.size() + n); return it; @@ -550,7 +551,8 @@ template constexpr auto to_pointer(OutputIt, size_t) -> T* { return nullptr; } -template auto to_pointer(basic_appender it, size_t n) -> T* { +template +FMT_CONSTEXPR20 auto to_pointer(basic_appender it, size_t n) -> T* { buffer& buf = get_container(it); auto size = buf.size(); buf.try_reserve(size + n); diff --git a/test/compile-test.cc b/test/compile-test.cc index e44eee9f00bd4..dcdd0af684a28 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -198,7 +198,7 @@ TEST(compile_test, format_to_n) { EXPECT_STREQ("2a", buffer); } -# if 0 +# if FMT_USE_CONSTEVAL TEST(compile_test, constexpr_formatted_size) { FMT_CONSTEXPR20 size_t size = fmt::formatted_size(FMT_COMPILE("{}"), 42); EXPECT_EQ(size, 2);