Pergunta

In c++11, std::unordered_set container provides both an insert overload and a new function emplace so that it can be used with non copy-constructible keys, for example std::unique_ptr.

What happens when you want to remove one of these keys? Is auto temp = std::move(*some_iterator) valid? Is there some function that allows us to erase an element and move it into a temp simultaneously?

Edit: I tried to keep it short, sweet and simple, but to be more clear:

  • Is there an iterator adapter (possibly move_iterator?) that will let me move an element from a container, and erase that iterator?
  • If not, why not? Shouldn't future c++ include this kind of interface?

The situation seems to be impossible: you cannot invalidate a key before removing it, and you cannot access it after removing it.

Foi útil?

Solução

For std::unordered_set<T> the member emplace() makes it unnecessary for the objects to be movable, either: you can emplace() non-movable objects into the container.

To answer the question: you can't std::move() elements out of a std::unordered_set<T> because the elements are all const and const objects can't be moved. When you erase() an std::unique_ptr<T> from an std::unordered_set<std::unique_ptr<T>> the pointed to object will be deleted: there is no interface which allows you to recover the pointer while erase()ing the element. Nor is there a splice() member to stick the element into another container where it can be ignored until it is time to get rid of it.

Outras dicas

My solution is simply to put the elements in std::shared_ptr. This way you can copy them around, and then eventually move the element out of the shared_ptr.

The cost of this, programming-wise, is that you have to define the hash function yourself.

Assuing you're putting std::string in the set:

struct MyHasher
{
    size_t operator()(const std::shared_ptr<std::string>& element) const
    {
        return std::hash<std::string>()(*element);
    }
};

And then you make the unordered_set like this:

std::unordered_set<std::string,MyHasher> the_set;

And now, you can move the elements around all you want.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top