https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118088

            Bug ID: 118088
           Summary: std::priority_queue doesn't maintain invariants after
                    being moved
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

#include <queue>
#include <vector>
#include <iostream>

// A vector-like type that has a non-empty moved-from state.
struct Vector : std::vector<int>
{
  using Base = std::vector<int>;

  using Base::Base;

  Vector(const Vector&) = default;
  Vector& operator=(const Vector&) = default;

  Vector(Vector&& v) : Base(static_cast<const Base&>(v))
  {
    invalidate_heap(v);
  }

  Vector(Vector&& v, const std::allocator<int>&)
  : Base(static_cast<const Base&>(v))
  {
    invalidate_heap(v);
  }

  Vector&
  operator=(Vector&& v)
  {
    static_cast<Base&>(*this) = static_cast<const Base&>(v);
    invalidate_heap(v);
    return *this;
  }

  void invalidate_heap(Base& v) { v = {1,2,3}; }
};

int main()
{
  std::priority_queue<int, Vector> p;
  p.push(1);
  p.push(3);
  p.push(5);
  p.push(2);
  p.push(2);
  p.push(2);
  p.push(2);
  std::priority_queue<int, Vector> p2 = std::move(p);
  while (!p.empty())
  {
    std::cout << p.top() << ' ';
    p.pop();
  }
  std::cout << '\n';

  // Allocator-extended move constructor:
  std::priority_queue<int, Vector> p3(std::move(p2), std::allocator<int>());
  while (!p2.empty())
  {
    std::cout << p2.top() << ' ';
    p2.pop();
  }
  std::cout << '\n';

  p2 = std::move(p3);
  while (!p3.empty())
  {
    std::cout << p3.top() << ' ';
    p3.pop();
  }
  std::cout << '\n';
}

This prints:

1 3 2 
1 3 2 
1 3 2 

But a priority_queue should print "3 2 1"

Reply via email to