mirror of
https://github.com/fmtlib/fmt.git
synced 2025-09-08 12:02:51 -04:00
Handle allocator propagation in basic_memory_buffer::move
Update `basic_memory_buffer::move` to respect `propagate_on_container_move_assignment`allocator trait. If the allocator should not propagate and differs from the target's allocator, fallback to copying the buffer instead of transferring ownership. This avoids potential allocator mismatch issues and ensures exception safety.
This commit is contained in:
parent
93f03953af
commit
5deae85b18
@ -751,6 +751,14 @@ template <typename T> struct allocator : private std::decay<void> {
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_t) { std::free(p); }
|
||||
|
||||
friend bool operator==(const allocator&, const allocator&) noexcept {
|
||||
return true; // All instances of this allocator are equivalent.
|
||||
}
|
||||
|
||||
friend bool operator!=(const allocator& a, const allocator& b) noexcept {
|
||||
return !(a == b);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@ -828,9 +836,20 @@ class basic_memory_buffer : public detail::buffer<T> {
|
||||
private:
|
||||
// Move data from other to this buffer.
|
||||
FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
|
||||
alloc_ = std::move(other.alloc_);
|
||||
using alloc_traits = std::allocator_traits<Allocator>;
|
||||
T* data = other.data();
|
||||
size_t size = other.size(), capacity = other.capacity();
|
||||
if constexpr (alloc_traits::propagate_on_container_move_assignment::value) {
|
||||
alloc_ = std::move(other.alloc_);
|
||||
} else {
|
||||
if (alloc_ != other.alloc_) {
|
||||
this->reserve(capacity);
|
||||
detail::copy<T>(data, data + size, this->data());
|
||||
this->resize(size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (data == other.store_) {
|
||||
this->set(store_, capacity);
|
||||
detail::copy<T>(other.store_, other.store_ + size, store_);
|
||||
|
@ -72,6 +72,17 @@ template <typename Allocator> class allocator_ref {
|
||||
return std::allocator_traits<Allocator>::allocate(*alloc_, n);
|
||||
}
|
||||
void deallocate(value_type* p, size_t n) { alloc_->deallocate(p, n); }
|
||||
|
||||
friend bool operator==(const allocator_ref& a, const allocator_ref& b) noexcept {
|
||||
if (a.alloc_ == b.alloc_) return true;
|
||||
if (a.alloc_ == nullptr || b.alloc_ == nullptr) return false;
|
||||
|
||||
return *a.alloc_ == *b.alloc_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const allocator_ref& a, const allocator_ref& b) noexcept {
|
||||
return !(a == b);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // FMT_MOCK_ALLOCATOR_H_
|
||||
|
Loading…
x
Reference in New Issue
Block a user