Repository: fmtlib/fmt
File: include/fmt/format.h (C/C++)

Code before:
 public:
  using value_type = T;
  using const_reference = const T&;

  FMT_CONSTEXPR explicit basic_memory_buffer(
      const Allocator& alloc = Allocator())
      : detail::buffer<T>(grow), alloc_(alloc) {
    this->set(store_, SIZE);
    if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T());
  }
  FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); }

 private:
  // Move data from other to this buffer.
  FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
    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_);
    } else {
      this->set(data, capacity);
      // Set pointer to the inline array so that delete is not called
      // when deallocating.
      other.set(other.store_, 0);
      other.clear();
    }
    this->resize(size);
  }

 public:
  /// Constructs a `basic_memory_buffer` object moving the content of the other
  /// object to it.
  FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept
      : detail::buffer<T>(grow) {
    move(other);
  }

  /// Moves the content of the other `basic_memory_buffer` object to this one.

Review comment (suggestion):
This branch needs to handle the case when `data == other.store_` as well. Otherwise the `store_` buffer optimization is bypassed for the target buffer.

Code after:
    // 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);
  }

 public:
  using value_type = T;
  using const_reference = const T&;

  FMT_CONSTEXPR explicit basic_memory_buffer(
      const Allocator& alloc = Allocator())
      : detail::buffer<T>(grow), alloc_(alloc) {
    this->set(store_, SIZE);
    if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T());
  }
  FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); }

 private:
  template <typename Alloc = Allocator>
  FMT_CONSTEXPR20
      typename std::enable_if<std::allocator_traits<Alloc>::
                                  propagate_on_container_move_assignment::value,
                              bool>::type
      allocator_move_impl(basic_memory_buffer& other) {
    alloc_ = std::move(other.alloc_);
    return true;
  }
  // If the allocator does not propagate,
  // then copy the content from source buffer.
  template <typename Alloc = Allocator>
  FMT_CONSTEXPR20
      typename std::enable_if<!std::allocator_traits<Alloc>::
                                  propagate_on_container_move_assignment::value,
                              bool>::type
      allocator_move_impl(basic_memory_buffer& other) {
    T* data = other.data();
    if (alloc_ != other.alloc_ && data != other.store_) {
      size_t size = other.size();
      // Perform copy operation, allocators are different
      this->resize(size);
      detail::copy<T>(data, data + size, this->data());
      return false;
    }
    return true;
  }

  // Move data from other to this buffer.
  FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
    T* data = other.data();
    size_t size = other.size(), capacity = other.capacity();
    // Replicate the behaviour of std library containers