GCC 4.9's unordered_set and std::move

653 Views Asked by At

When moving an unordered_set out on GCC 4.9, and then reusing the moved-from object, I am getting a divide-by-zero when I add to it.

My understanding (from http://en.cppreference.com/w/cpp/utility/move) is that the moved-from object can be used provided none of its preconditions are violated. Calling clear() on the moved-from set is fine (which makes sense in the context of preconditions), but it's not clear to me that I'm violating any precondition by adding a new element.

Example code:

#include <unordered_set>
using namespace std;
void foo(unordered_set<int> &&a) {
  unordered_set<int> copy = std::move(a);
}

void test() {
  unordered_set<int> a;
  for (int i = 0; i < 12; ++i) a.insert(i);
  foo(std::move(a));

  a.clear();
  a.insert(34); // divide by zero here
}

int main() {
  test();
}​

This code works fine on GCC4.7 - is this an issue in GCC4.9's unordered_set implementation, or in my understanding of what it means to violate preconditions on moved-from objects?

2

There are 2 best solutions below

0
On BEST ANSWER

This is PR 61143. It has been fixed for gcc-4.10 and the fix has been backported in time for 4.9.1.

1
On

Marc Glisse has already referred you to the GCC bug, but to answer your question:

is this an issue ... in my understanding of what it means to violate preconditions on moved-from objects?

No, it isn't, your understanding is correct. Making the code in your question work isn't just a GCC extension, your program is perfectly valid. A moved-from object of a type defined in the standard library is supposed to remain usable. You don't know anything about its state, but, as an example, any container is empty, or is non-empty, so a moved-from container is also either empty or non-empty. Which of those is unspecified, but your program can check, and the standard library implementation must behave as appropriate for the result of your program's check.