https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125220
Bug ID: 125220
Summary: std::priority_queue move constructs twice and move
assigns upon emplace
Product: gcc
Version: 16.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: ted at lyncon dot se
Target Milestone: ---
This test program shows the one construction I would expect plus two move
constructions and a final move assignment when using `priority_queue::emplace`:
```
#include <iostream>
#include <queue>
#include <utility>
class foo {
public:
foo(int x) : id(++idcount), value(x) {
++alive;
std::cout << "foo(int)\t\t" << *this << '\n';
}
foo(const foo& rhs) : id(++idcount), value(rhs.value) {
++alive;
std::cout << "foo(const foo&)\t\t" << *this << " <= " << rhs << '\n';
}
foo(foo&& rhs) noexcept
: id(++idcount), value(std::exchange(rhs.value, -rhs.value)) {
++alive;
std::cout << "foo(foo&&)\t\t" << *this << " <= " << rhs << '\n';
}
foo& operator=(const foo& rhs) {
std::cout << "foo& operator=(const foo&)\t" << *this << " <= " << rhs
<< '\n';
value = rhs.value;
return *this;
}
foo& operator=(foo&& rhs) noexcept {
value = std::exchange(rhs.value, -rhs.value);
std::cout << "foo& operator=(foo&&)\t" << *this << " <= " << rhs <<
'\n';
return *this;
}
~foo() {
std::cout << "~foo()\t\t\t" << *this << '\n';
--alive;
}
friend std::ostream& operator<<(std::ostream& os, const foo& f) {
return os << R"aw({"id": )aw" << f.id << R"aw(, "value": )aw" <<
f.value << "}";
}
bool operator<(const foo& rhs) const { return id < rhs.id; }
private:
unsigned id;
int value;
inline static unsigned alive = 0;
inline static unsigned idcount = 0;
};
int main() {
std::priority_queue<foo> pq;
pq.emplace(999);
std::cout << "--------------------------------\n";
}
```
Output:
```
foo(int) {"id": 1, "value": 999}
foo(foo&&) {"id": 2, "value": 999} <= {"id": 1, "value": -999}
foo(foo&&) {"id": 3, "value": 999} <= {"id": 2, "value": -999}
foo& operator=(foo&&) {"id": 1, "value": 999} <= {"id": 3, "value": -999}
~foo() {"id": 3, "value": -999}
~foo() {"id": 2, "value": -999}
--------------------------------
~foo() {"id": 1, "value": 999}
```
The expected output (seen in MSVC and libc++):
```
foo(int) {"id": 1, "value": 999}
--------------------------------
~foo() {"id": 1, "value": 999}
```