Skip to content

Commit

Permalink
Constexpr formatted_size (fmtlib#3026)
Browse files Browse the repository at this point in the history
* Constexpr formatted_size

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

* Adjust unit test to require __cpp_lib_bit_cast
  • Loading branch information
marksantaniello authored Aug 10, 2022
1 parent 7fb8d33 commit fd93b63
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 13 deletions.
4 changes: 2 additions & 2 deletions include/fmt/compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ FMT_BEGIN_NAMESPACE
namespace detail {

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) {
return it + (end - begin);
}
Expand Down Expand Up @@ -568,7 +568,7 @@ format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,

template <typename S, typename... Args,
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...)
.count();
}
Expand Down
16 changes: 8 additions & 8 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)

template <typename Char, typename UInt, typename Iterator,
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> {
// Buffer is large enough to hold all digits (digits10 + 1).
Char buffer[digits10<UInt>() + 1];
Expand Down Expand Up @@ -2137,29 +2137,29 @@ class counting_iterator {
FMT_UNCHECKED_ITERATOR(counting_iterator);

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_;
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<size_t>(n);
return it;
}

value_type operator*() const { return {}; }
FMT_CONSTEXPR value_type operator*() const { return {}; }
};

template <typename Char, typename OutputIt>
Expand Down
10 changes: 7 additions & 3 deletions test/compile-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,14 @@ TEST(compile_test, format_to_n) {
EXPECT_STREQ("2a", buffer);
}

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));
#ifdef __cpp_lib_bit_cast
TEST(compile_test, constexpr_formatted_size) {
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) {
EXPECT_EQ(">>>42<<<", fmt::format(FMT_COMPILE(">>>{}<<<"), 42));
Expand Down

0 comments on commit fd93b63

Please sign in to comment.