Search code examples
c++containersstdmove

Is it legal to move elements from standard containers?


I am writing a class which requires highly efficient function for filtering member container (lets say std::vector). This function should have interface similar to the following:

void filter(std::vector<SomeType>& items, const std::vector<int>& inds);

The function should leave the container items in the following state: - items that are pointed to by the index from inds should be removed - other items should remain in container keeping initial order.

For simplicity lets assume that inds is a perfect container with O(1) on every operation and all indices are valid with no duplication.

My idea was to create the second container, reserve required space and then move (through std::move) every element not indexed by inds into this new container; and afterwards just swap the old and the new containers.

For example like this:

void filter(std::vector<SomeType>& items, const std::vector<int>& inds)
{
    std::vector<SomeType> new_items{};
    new_items.reserve( items.size() - inds.size() );

    for(size_t i = 0; i < items.size(); ++i)
        if( contains( inds, i ) ) // magic O(1) function, never mind
            new_items.push_back( std::move( items[i] ) );

    items.swap(new_items);
}

My questions are:

1) after using std::move on some element inside the vector (or generally any other standard container) will there be any issues like double destructing of these elements?

2) Is there a standard way to do such filtering efficiently?


Solution

  • It's not the container's responsibility to safeguard from issues that might arise from moving. As long as the type of the items moved has a well-defined and correct move constructor / implicit move constructor then moving the items from items to new_items is the same as any other move operation; containers don't change this.

    In short, this responsibility lays with the class, not the container it's used in.