Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reintroduce constexpr fmt::formatted_size for C++20 #4103

Merged
merged 2 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions include/fmt/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,8 @@ struct is_back_insert_iterator<

// Extracts a reference to the container from *insert_iterator.
template <typename OutputIt>
inline auto get_container(OutputIt it) -> typename OutputIt::container_type& {
inline FMT_CONSTEXPR20 auto get_container(OutputIt it) ->
typename OutputIt::container_type& {
struct accessor : OutputIt {
accessor(OutputIt base) : OutputIt(base) {}
using OutputIt::container;
Expand Down Expand Up @@ -901,7 +902,7 @@ template <typename T> class buffer {
FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }

/// Clears this buffer.
void clear() { size_ = 0; }
FMT_CONSTEXPR void clear() { size_ = 0; }

// Tries resizing the buffer to contain `count` elements. If T is a POD type
// the new elements may not be initialized.
Expand All @@ -924,7 +925,15 @@ template <typename T> class buffer {
}

/// Appends data to the end of the buffer.
template <typename U> void append(const U* begin, const U* end) {
template <typename U>
// Workaround for Visual Studio 2019 to fix error C2893: Failed to specialize
// function template 'void fmt::v11::detail::buffer<T>::append(const U *,const
// U *)'
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1930
FMT_CONSTEXPR20
#endif
void
append(const U* begin, const U* end) {
while (begin != end) {
auto count = to_unsigned(end - begin);
try_reserve(size_ + count);
Expand Down Expand Up @@ -1105,7 +1114,9 @@ template <typename T = char> class counting_buffer : public buffer<T> {
public:
FMT_CONSTEXPR counting_buffer() : buffer<T>(grow, data_, 0, buffer_size) {}

auto count() -> size_t { return count_ + this->size(); }
constexpr auto count() const noexcept -> size_t {
return count_ + this->size();
}
};
} // namespace detail

Expand Down Expand Up @@ -1155,7 +1166,8 @@ template <typename T> class basic_appender {
private:
detail::buffer<T>* buffer_;

friend auto get_container(basic_appender app) -> detail::buffer<T>& {
friend FMT_CONSTEXPR20 auto get_container(basic_appender app)
-> detail::buffer<T>& {
return *app.buffer_;
}

Expand All @@ -1170,13 +1182,13 @@ template <typename T> class basic_appender {

FMT_CONSTEXPR basic_appender(detail::buffer<T>& buf) : buffer_(&buf) {}

auto operator=(T c) -> basic_appender& {
FMT_CONSTEXPR20 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_CONSTEXPR20 auto operator*() -> basic_appender& { return *this; }
FMT_CONSTEXPR20 auto operator++() -> basic_appender& { return *this; }
FMT_CONSTEXPR20 auto operator++(int) -> basic_appender { return *this; }
};

using appender = basic_appender<char>;
Expand All @@ -1188,7 +1200,8 @@ struct is_back_insert_iterator<basic_appender<T>> : std::true_type {};
// An optimized version of std::copy with the output value type (T).
template <typename T, typename InputIt, typename OutputIt,
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value)>
auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
-> OutputIt {
get_container(out).append(begin, end);
return out;
}
Expand Down
3 changes: 2 additions & 1 deletion include/fmt/compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,8 @@ auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args)

template <typename S, typename... Args,
FMT_ENABLE_IF(detail::is_compiled_string<S>::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();
Expand Down
10 changes: 6 additions & 4 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ template <typename OutputIt,
#if FMT_CLANG_VERSION >= 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();
Expand All @@ -532,7 +532,8 @@ reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* {
}

template <typename T>
inline auto reserve(basic_appender<T> it, size_t n) -> basic_appender<T> {
FMT_CONSTEXPR20 inline auto reserve(basic_appender<T> it, size_t n)
-> basic_appender<T> {
buffer<T>& buf = get_container(it);
buf.try_reserve(buf.size() + n);
return it;
Expand All @@ -551,7 +552,8 @@ template <typename T, typename OutputIt>
constexpr auto to_pointer(OutputIt, size_t) -> T* {
return nullptr;
}
template <typename T> auto to_pointer(basic_appender<T> it, size_t n) -> T* {
template <typename T>
FMT_CONSTEXPR20 auto to_pointer(basic_appender<T> it, size_t n) -> T* {
buffer<T>& buf = get_container(it);
auto size = buf.size();
buf.try_reserve(size + n);
Expand Down Expand Up @@ -929,7 +931,7 @@ class basic_memory_buffer : public detail::buffer<T> {

using detail::buffer<T>::append;
template <typename ContiguousRange>
void append(const ContiguousRange& range) {
FMT_CONSTEXPR20 void append(const ContiguousRange& range) {
append(range.data(), range.data() + range.size());
}
};
Expand Down
2 changes: 1 addition & 1 deletion test/compile-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ TEST(compile_test, format_to_n) {
EXPECT_STREQ("2a", buffer);
}

# if 0
# if FMT_USE_CONSTEVAL && (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1930)
TEST(compile_test, constexpr_formatted_size) {
FMT_CONSTEXPR20 size_t size = fmt::formatted_size(FMT_COMPILE("{}"), 42);
EXPECT_EQ(size, 2);
Expand Down