malloc-based fmt::detail::allocator is not constexpr aware in C++20.
|
template <typename T> struct allocator : private std::decay<void> { |
|
using value_type = T; |
|
|
|
T* allocate(size_t n) { |
|
FMT_ASSERT(n <= max_value<size_t>() / sizeof(T), ""); |
|
T* p = static_cast<T*>(malloc(n * sizeof(T))); |
|
if (!p) FMT_THROW(std::bad_alloc()); |
|
return p; |
|
} |
|
|
|
void deallocate(T* p, size_t) { free(p); } |
|
}; |
Without constexpr fmt::detail::allocator support for constexpr formatting will be limited because fmt::basic_memory_buffer depends on the fmt::detail::allocator.
|
template <typename T, size_t SIZE = inline_buffer_size, |
|
typename Allocator = detail::allocator<T>> |
|
class basic_memory_buffer : public detail::buffer<T> { |
|
private: |
|
T store_[SIZE]; |
|
|
|
// Don't inherit from Allocator to avoid generating type_info for it. |
|
FMT_NO_UNIQUE_ADDRESS Allocator alloc_; |
|
|
|
// Deallocate memory allocated by the buffer. |
|
FMT_CONSTEXPR20 void deallocate() { |
|
T* data = this->data(); |
|
if (data != store_) alloc_.deallocate(data, this->capacity()); |
|
} |
|
|
|
static FMT_CONSTEXPR20 void grow(detail::buffer<T>& buf, size_t size) { |
|
detail::abort_fuzzing_if(size > 5000); |
|
auto& self = static_cast<basic_memory_buffer&>(buf); |
|
const size_t max_size = |
|
std::allocator_traits<Allocator>::max_size(self.alloc_); |
|
size_t old_capacity = buf.capacity(); |
|
size_t new_capacity = old_capacity + old_capacity / 2; |
|
if (size > new_capacity) |
|
new_capacity = size; |
|
else if (new_capacity > max_size) |
|
new_capacity = max_of(size, max_size); |
|
T* old_data = buf.data(); |
|
T* new_data = self.alloc_.allocate(new_capacity); |
|
// Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). |
|
detail::assume(buf.size() <= new_capacity); |
|
// The following code doesn't throw, so the raw pointer above doesn't leak. |
|
memcpy(new_data, old_data, buf.size() * sizeof(T)); |
|
self.set(new_data, new_capacity); |
|
// deallocate must not throw according to the standard, but even if it does, |
|
// the buffer already uses the new storage and will deallocate it in |
|
// destructor. |
|
if (old_data != self.store_) self.alloc_.deallocate(old_data, old_capacity); |
|
} |
This may also limit the functionality of PR #4456.
malloc-basedfmt::detail::allocatoris not constexpr aware in C++20.fmt/include/fmt/format.h
Lines 773 to 784 in 730fd4d
Without
constexpr fmt::detail::allocatorsupport for constexpr formatting will be limited becausefmt::basic_memory_bufferdepends on thefmt::detail::allocator.fmt/include/fmt/format.h
Lines 807 to 844 in 730fd4d
This may also limit the functionality of PR #4456.