mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-31 19:24:48 +02:00
Reintroduce constexpr fmt::formatted_size for C++20 (#4103)
* Reintroduce constexpr fmt::formatted_size for C++20 Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru> * Disable constexpr fmt::formatted_size on Visual Studio 2019 Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru> --------- Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
This commit is contained in:
committed by
GitHub
parent
b9c0e4dd82
commit
5ee14d3508
@@ -494,7 +494,8 @@ struct is_back_insert_iterator<
|
|||||||
|
|
||||||
// Extracts a reference to the container from *insert_iterator.
|
// Extracts a reference to the container from *insert_iterator.
|
||||||
template <typename OutputIt>
|
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 {
|
struct accessor : OutputIt {
|
||||||
accessor(OutputIt base) : OutputIt(base) {}
|
accessor(OutputIt base) : OutputIt(base) {}
|
||||||
using OutputIt::container;
|
using OutputIt::container;
|
||||||
@@ -901,7 +902,7 @@ template <typename T> class buffer {
|
|||||||
FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
|
FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
|
||||||
|
|
||||||
/// Clears this buffer.
|
/// 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
|
// Tries resizing the buffer to contain `count` elements. If T is a POD type
|
||||||
// the new elements may not be initialized.
|
// the new elements may not be initialized.
|
||||||
@@ -924,7 +925,15 @@ template <typename T> class buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Appends data to the end of the 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) {
|
while (begin != end) {
|
||||||
auto count = to_unsigned(end - begin);
|
auto count = to_unsigned(end - begin);
|
||||||
try_reserve(size_ + count);
|
try_reserve(size_ + count);
|
||||||
@@ -1105,7 +1114,9 @@ template <typename T = char> class counting_buffer : public buffer<T> {
|
|||||||
public:
|
public:
|
||||||
FMT_CONSTEXPR counting_buffer() : buffer<T>(grow, data_, 0, buffer_size) {}
|
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
|
} // namespace detail
|
||||||
|
|
||||||
@@ -1155,7 +1166,8 @@ template <typename T> class basic_appender {
|
|||||||
private:
|
private:
|
||||||
detail::buffer<T>* buffer_;
|
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_;
|
return *app.buffer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,13 +1182,13 @@ template <typename T> class basic_appender {
|
|||||||
|
|
||||||
FMT_CONSTEXPR basic_appender(detail::buffer<T>& buf) : buffer_(&buf) {}
|
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);
|
buffer_->push_back(c);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
auto operator*() -> basic_appender& { return *this; }
|
FMT_CONSTEXPR20 auto operator*() -> basic_appender& { return *this; }
|
||||||
auto operator++() -> basic_appender& { return *this; }
|
FMT_CONSTEXPR20 auto operator++() -> basic_appender& { return *this; }
|
||||||
auto operator++(int) -> basic_appender { return *this; }
|
FMT_CONSTEXPR20 auto operator++(int) -> basic_appender { return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
using appender = basic_appender<char>;
|
using appender = basic_appender<char>;
|
||||||
@@ -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).
|
// An optimized version of std::copy with the output value type (T).
|
||||||
template <typename T, typename InputIt, typename OutputIt,
|
template <typename T, typename InputIt, typename OutputIt,
|
||||||
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value)>
|
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);
|
get_container(out).append(begin, end);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@@ -488,7 +488,8 @@ auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args)
|
|||||||
|
|
||||||
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)>
|
||||||
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<>();
|
auto buf = detail::counting_buffer<>();
|
||||||
fmt::format_to(appender(buf), fmt, args...);
|
fmt::format_to(appender(buf), fmt, args...);
|
||||||
return buf.count();
|
return buf.count();
|
||||||
|
@@ -523,7 +523,7 @@ template <typename OutputIt,
|
|||||||
#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
|
#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
|
||||||
__attribute__((no_sanitize("undefined")))
|
__attribute__((no_sanitize("undefined")))
|
||||||
#endif
|
#endif
|
||||||
inline auto
|
FMT_CONSTEXPR20 inline auto
|
||||||
reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* {
|
reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* {
|
||||||
auto& c = get_container(it);
|
auto& c = get_container(it);
|
||||||
size_t size = c.size();
|
size_t size = c.size();
|
||||||
@@ -532,7 +532,8 @@ reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
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);
|
buffer<T>& buf = get_container(it);
|
||||||
buf.try_reserve(buf.size() + n);
|
buf.try_reserve(buf.size() + n);
|
||||||
return it;
|
return it;
|
||||||
@@ -551,7 +552,8 @@ template <typename T, typename OutputIt>
|
|||||||
constexpr auto to_pointer(OutputIt, size_t) -> T* {
|
constexpr auto to_pointer(OutputIt, size_t) -> T* {
|
||||||
return nullptr;
|
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);
|
buffer<T>& buf = get_container(it);
|
||||||
auto size = buf.size();
|
auto size = buf.size();
|
||||||
buf.try_reserve(size + n);
|
buf.try_reserve(size + n);
|
||||||
@@ -929,7 +931,7 @@ class basic_memory_buffer : public detail::buffer<T> {
|
|||||||
|
|
||||||
using detail::buffer<T>::append;
|
using detail::buffer<T>::append;
|
||||||
template <typename ContiguousRange>
|
template <typename ContiguousRange>
|
||||||
void append(const ContiguousRange& range) {
|
FMT_CONSTEXPR20 void append(const ContiguousRange& range) {
|
||||||
append(range.data(), range.data() + range.size());
|
append(range.data(), range.data() + range.size());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -198,7 +198,7 @@ TEST(compile_test, format_to_n) {
|
|||||||
EXPECT_STREQ("2a", buffer);
|
EXPECT_STREQ("2a", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
# if 0
|
# if FMT_USE_CONSTEVAL && (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1930)
|
||||||
TEST(compile_test, constexpr_formatted_size) {
|
TEST(compile_test, constexpr_formatted_size) {
|
||||||
FMT_CONSTEXPR20 size_t size = fmt::formatted_size(FMT_COMPILE("{}"), 42);
|
FMT_CONSTEXPR20 size_t size = fmt::formatted_size(FMT_COMPILE("{}"), 42);
|
||||||
EXPECT_EQ(size, 2);
|
EXPECT_EQ(size, 2);
|
||||||
|
Reference in New Issue
Block a user