From 1f0c91e2bd9a37d090e60e7ba886a5de2f130dd5 Mon Sep 17 00:00:00 2001 From: Mark Santaniello Date: Sat, 6 Aug 2022 10:52:47 -0700 Subject: [PATCH 1/5] Constexpr formatted_size --- include/fmt/compile.h | 4 ++-- include/fmt/format.h | 16 ++++++++-------- test/compile-test.cc | 6 ++++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index c09dd6f2a158..50d9ef48faf9 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -14,7 +14,7 @@ FMT_BEGIN_NAMESPACE namespace detail { template -inline counting_iterator copy_str(InputIt begin, InputIt end, +FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end, counting_iterator it) { return it + (end - begin); } @@ -568,7 +568,7 @@ format_to_n_result format_to_n(OutputIt out, size_t n, template ::value)> -size_t formatted_size(const S& format_str, const Args&... args) { +FMT_CONSTEXPR20 size_t formatted_size(const S& format_str, const Args&... args) { return fmt::format_to(detail::counting_iterator(), format_str, args...) .count(); } diff --git a/include/fmt/format.h b/include/fmt/format.h index 2768a037209e..047144cf46b3 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1231,7 +1231,7 @@ FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) template >::value)> -inline auto format_decimal(Iterator out, UInt value, int size) +FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size) -> format_decimal_result { // Buffer is large enough to hold all digits (digits10 + 1). Char buffer[digits10() + 1]; @@ -2137,29 +2137,29 @@ class counting_iterator { FMT_UNCHECKED_ITERATOR(counting_iterator); struct value_type { - template void operator=(const T&) {} + template FMT_CONSTEXPR void operator=(const T&) {} }; - counting_iterator() : count_(0) {} + FMT_CONSTEXPR counting_iterator() : count_(0) {} - size_t count() const { return count_; } + FMT_CONSTEXPR size_t count() const { return count_; } - counting_iterator& operator++() { + FMT_CONSTEXPR counting_iterator& operator++() { ++count_; return *this; } - counting_iterator operator++(int) { + FMT_CONSTEXPR counting_iterator operator++(int) { auto it = *this; ++*this; return it; } - friend counting_iterator operator+(counting_iterator it, difference_type n) { + FMT_CONSTEXPR friend counting_iterator operator+(counting_iterator it, difference_type n) { it.count_ += static_cast(n); return it; } - value_type operator*() const { return {}; } + FMT_CONSTEXPR value_type operator*() const { return {}; } }; template diff --git a/test/compile-test.cc b/test/compile-test.cc index 2a9e16196d01..05952664ed41 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -228,8 +228,10 @@ TEST(compile_test, format_to_n) { } TEST(compile_test, formatted_size) { - EXPECT_EQ(2, fmt::formatted_size(FMT_COMPILE("{0}"), 42)); - EXPECT_EQ(5, fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0)); + static FMT_CONSTEXPR20 size_t s1 = fmt::formatted_size(FMT_COMPILE("{0}"), 42); + EXPECT_EQ(2, s1); + static FMT_CONSTEXPR20 size_t s2 = fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0); + EXPECT_EQ(5, s2); } TEST(compile_test, text_and_arg) { From 4767e72bbaa6f7e2820d5a0a5be5d876867ccbbc Mon Sep 17 00:00:00 2001 From: Mark Santaniello Date: Sat, 6 Aug 2022 10:52:47 -0700 Subject: [PATCH 2/5] Constexpr formatted_size --- include/fmt/compile.h | 4 ++-- include/fmt/format.h | 16 ++++++++-------- test/compile-test.cc | 6 ++++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index c09dd6f2a158..50d9ef48faf9 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -14,7 +14,7 @@ FMT_BEGIN_NAMESPACE namespace detail { template -inline counting_iterator copy_str(InputIt begin, InputIt end, +FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end, counting_iterator it) { return it + (end - begin); } @@ -568,7 +568,7 @@ format_to_n_result format_to_n(OutputIt out, size_t n, template ::value)> -size_t formatted_size(const S& format_str, const Args&... args) { +FMT_CONSTEXPR20 size_t formatted_size(const S& format_str, const Args&... args) { return fmt::format_to(detail::counting_iterator(), format_str, args...) .count(); } diff --git a/include/fmt/format.h b/include/fmt/format.h index 2768a037209e..047144cf46b3 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1231,7 +1231,7 @@ FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) template >::value)> -inline auto format_decimal(Iterator out, UInt value, int size) +FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size) -> format_decimal_result { // Buffer is large enough to hold all digits (digits10 + 1). Char buffer[digits10() + 1]; @@ -2137,29 +2137,29 @@ class counting_iterator { FMT_UNCHECKED_ITERATOR(counting_iterator); struct value_type { - template void operator=(const T&) {} + template FMT_CONSTEXPR void operator=(const T&) {} }; - counting_iterator() : count_(0) {} + FMT_CONSTEXPR counting_iterator() : count_(0) {} - size_t count() const { return count_; } + FMT_CONSTEXPR size_t count() const { return count_; } - counting_iterator& operator++() { + FMT_CONSTEXPR counting_iterator& operator++() { ++count_; return *this; } - counting_iterator operator++(int) { + FMT_CONSTEXPR counting_iterator operator++(int) { auto it = *this; ++*this; return it; } - friend counting_iterator operator+(counting_iterator it, difference_type n) { + FMT_CONSTEXPR friend counting_iterator operator+(counting_iterator it, difference_type n) { it.count_ += static_cast(n); return it; } - value_type operator*() const { return {}; } + FMT_CONSTEXPR value_type operator*() const { return {}; } }; template diff --git a/test/compile-test.cc b/test/compile-test.cc index 2a9e16196d01..0d62fadbc59a 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -228,8 +228,10 @@ TEST(compile_test, format_to_n) { } TEST(compile_test, formatted_size) { - EXPECT_EQ(2, fmt::formatted_size(FMT_COMPILE("{0}"), 42)); - EXPECT_EQ(5, fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0)); + FMT_CONSTEXPR20 size_t s1 = fmt::formatted_size(FMT_COMPILE("{0}"), 42); + EXPECT_EQ(2, s1); + FMT_CONSTEXPR20 size_t s2 = fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0); + EXPECT_EQ(5, s2); } TEST(compile_test, text_and_arg) { From 39c52e45fe85fe40a08217e90da58b3682984b30 Mon Sep 17 00:00:00 2001 From: Mark Santaniello Date: Tue, 9 Aug 2022 11:02:54 -0700 Subject: [PATCH 3/5] Add C++20 tests for gcc 9 and 10 --- .github/workflows/linux.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 70085f5c6778..331eec69a49b 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -28,10 +28,19 @@ jobs: std: 17 install: sudo apt install g++-8 os: ubuntu-18.04 + - cxx: g++-9 + build_type: Debug + std: 20 + install: sudo apt install g++-9 + os: ubuntu-18.04 - cxx: g++-10 build_type: Debug std: 17 os: ubuntu-18.04 + - cxx: g++-10 + build_type: Debug + std: 20 + os: ubuntu-18.04 - cxx: g++-11 build_type: Debug std: 20 From 003ccb427184ffb1c83a7e5b676e8579f4793902 Mon Sep 17 00:00:00 2001 From: Mark Santaniello Date: Tue, 9 Aug 2022 11:02:54 -0700 Subject: [PATCH 4/5] Adjust unit test to require __cpp_lib_bit_cast --- include/fmt/format.h | 2 -- test/compile-test.cc | 10 ++++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 119e36f1538b..047144cf46b3 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -297,8 +297,6 @@ template FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { #ifdef __cpp_lib_bit_cast if (is_constant_evaluated()) return std::bit_cast(from); -#elif FMT_HAS_BUILTIN(__builtin_bit_cast) - return __builtin_bit_cast(To, from); #endif auto to = To(); // The cast suppresses a bogus -Wclass-memaccess on GCC. diff --git a/test/compile-test.cc b/test/compile-test.cc index 0d62fadbc59a..52f61cb859a1 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -228,9 +228,15 @@ TEST(compile_test, format_to_n) { } TEST(compile_test, formatted_size) { - FMT_CONSTEXPR20 size_t s1 = fmt::formatted_size(FMT_COMPILE("{0}"), 42); +#ifdef __cpp_lib_bit_cast + FMT_CONSTEXPR20 +#endif + size_t s1 = fmt::formatted_size(FMT_COMPILE("{0}"), 42); EXPECT_EQ(2, s1); - FMT_CONSTEXPR20 size_t s2 = fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0); +#ifdef __cpp_lib_bit_cast + FMT_CONSTEXPR20 +#endif +size_t s2 = fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0); EXPECT_EQ(5, s2); } From a703799f8caa7b6cb19988a8e38f96299370e324 Mon Sep 17 00:00:00 2001 From: Mark Santaniello Date: Tue, 9 Aug 2022 16:32:08 -0700 Subject: [PATCH 5/5] Address feedback from Victor --- .github/workflows/linux.yml | 9 --------- test/compile-test.cc | 12 ++++-------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 331eec69a49b..70085f5c6778 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -28,19 +28,10 @@ jobs: std: 17 install: sudo apt install g++-8 os: ubuntu-18.04 - - cxx: g++-9 - build_type: Debug - std: 20 - install: sudo apt install g++-9 - os: ubuntu-18.04 - cxx: g++-10 build_type: Debug std: 17 os: ubuntu-18.04 - - cxx: g++-10 - build_type: Debug - std: 20 - os: ubuntu-18.04 - cxx: g++-11 build_type: Debug std: 20 diff --git a/test/compile-test.cc b/test/compile-test.cc index 52f61cb859a1..005c4993098b 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -227,18 +227,14 @@ TEST(compile_test, format_to_n) { EXPECT_STREQ("2a", buffer); } -TEST(compile_test, formatted_size) { #ifdef __cpp_lib_bit_cast - FMT_CONSTEXPR20 -#endif - size_t s1 = fmt::formatted_size(FMT_COMPILE("{0}"), 42); +TEST(compile_test, constexpr_formatted_size) { + FMT_CONSTEXPR20 size_t s1 = fmt::formatted_size(FMT_COMPILE("{0}"), 42); EXPECT_EQ(2, s1); -#ifdef __cpp_lib_bit_cast - FMT_CONSTEXPR20 -#endif -size_t s2 = fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0); + FMT_CONSTEXPR20 size_t s2 = fmt::formatted_size(FMT_COMPILE("{0:<4.2f}"), 42.0); EXPECT_EQ(5, s2); } +#endif TEST(compile_test, text_and_arg) { EXPECT_EQ(">>>42<<<", fmt::format(FMT_COMPILE(">>>{}<<<"), 42));