jeudi 30 juin 2016

Should STL map::insert support move semantics with move_iterators?

I have a large amount of data to load into a map from file, which is already in sorted order (because it was serialized from the map). I've discovered it is faster to first load the data into a vector, and then bulk-load into a map with insert. This saves just over a second in a 19sec load time.

The value_type is a structure that contains vectors of other structures. I don't need the vector after the load completes, so I use move_iterators in my call to map::insert. Using MSVC 2015 (VC14), the data isn't moved into the map, but instead is copied via const_reference deep inside the STL code.

Is this a standard-compliant implementation, to ignore the moving of data?

template<typename Stream, typename Key, typename Type, typename Traits, typename Allocator>
bool const read(Stream &is, std::map<Key, Type, Traits, Allocator> &map)
{
    size_t size;
    read(is, size);

    std::vector<std::pair<Key, Type>> items(size);
    for (size_t i=0; i<size; ++i)
    {
        auto &item = items[i];
        if (!read(is, item.first)  ||  !read(is, item.second))
            return false;
    }
    map.insert(std::make_move_iterator(items.begin()), std::make_move_iterator(items.end()));

    return !!is;
}

I've overcome the problem replacing the map.insert with

for (auto &item : items)
    map.insert(std::move(item));

but it isn't so neat, but does save another 0.6 seconds.

Aucun commentaire:

Enregistrer un commentaire