diff --git a/include/fmt/format.h b/include/fmt/format.h index 1cbd3df4..591a28af 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -751,6 +751,14 @@ template struct allocator : private std::decay { } 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 { 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; 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(data, data + size, this->data()); + this->resize(size); + return; + } + } + if (data == other.store_) { this->set(store_, capacity); detail::copy(other.store_, other.store_ + size, store_); diff --git a/test/mock-allocator.h b/test/mock-allocator.h index 32c4caae..168d02a6 100644 --- a/test/mock-allocator.h +++ b/test/mock-allocator.h @@ -72,6 +72,17 @@ template class allocator_ref { return std::allocator_traits::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_