Constexpr formatted_size (#3026)

* Constexpr formatted_size

* Add C++20 tests for gcc 9 and 10

* Adjust unit test to require __cpp_lib_bit_cast
This commit is contained in:
Mark Santaniello 2022-08-10 09:35:30 -07:00 committed by GitHub
parent 7fb8d33f9d
commit fd93b633b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 13 deletions

View File

@ -14,7 +14,7 @@ FMT_BEGIN_NAMESPACE
namespace detail { namespace detail {
template <typename Char, typename InputIt> template <typename Char, typename InputIt>
inline counting_iterator copy_str(InputIt begin, InputIt end, FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end,
counting_iterator it) { counting_iterator it) {
return it + (end - begin); return it + (end - begin);
} }
@ -568,7 +568,7 @@ format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
template <typename S, typename... Args, template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> FMT_ENABLE_IF(detail::is_compiled_string<S>::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...) return fmt::format_to(detail::counting_iterator(), format_str, args...)
.count(); .count();
} }

View File

@ -1231,7 +1231,7 @@ FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)
template <typename Char, typename UInt, typename Iterator, template <typename Char, typename UInt, typename Iterator,
FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)> FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::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<Iterator> { -> format_decimal_result<Iterator> {
// Buffer is large enough to hold all digits (digits10 + 1). // Buffer is large enough to hold all digits (digits10 + 1).
Char buffer[digits10<UInt>() + 1]; Char buffer[digits10<UInt>() + 1];
@ -2137,29 +2137,29 @@ class counting_iterator {
FMT_UNCHECKED_ITERATOR(counting_iterator); FMT_UNCHECKED_ITERATOR(counting_iterator);
struct value_type { struct value_type {
template <typename T> void operator=(const T&) {} template <typename T> 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_; ++count_;
return *this; return *this;
} }
counting_iterator operator++(int) { FMT_CONSTEXPR counting_iterator operator++(int) {
auto it = *this; auto it = *this;
++*this; ++*this;
return it; 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<size_t>(n); it.count_ += static_cast<size_t>(n);
return it; return it;
} }
value_type operator*() const { return {}; } FMT_CONSTEXPR value_type operator*() const { return {}; }
}; };
template <typename Char, typename OutputIt> template <typename Char, typename OutputIt>

View File

@ -227,10 +227,14 @@ TEST(compile_test, format_to_n) {
EXPECT_STREQ("2a", buffer); EXPECT_STREQ("2a", buffer);
} }
TEST(compile_test, formatted_size) { #ifdef __cpp_lib_bit_cast
EXPECT_EQ(2, fmt::formatted_size(FMT_COMPILE("{0}"), 42)); TEST(compile_test, constexpr_formatted_size) {
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);
} }
#endif
TEST(compile_test, text_and_arg) { TEST(compile_test, text_and_arg) {
EXPECT_EQ(">>>42<<<", fmt::format(FMT_COMPILE(">>>{}<<<"), 42)); EXPECT_EQ(">>>42<<<", fmt::format(FMT_COMPILE(">>>{}<<<"), 42));