Есть ли вариант back_inserter, который использует преимущество move? - PullRequest
0 голосов
/ 22 января 2019

В общем коде я пытался указать итератору вывода (на практике std::back_inserter_iterator для перемещения диапазона элементов. К моему удивлению это выглядело, как если бы элементы были перемещены в операции move-to-back_inserter.

#include<algorithm> // move
#include<iterator> // back_inserter
#include<vector>
int main(){
    std::vector<std::vector<double> > v(10, std::vector<double>(100));
    std::vector<std::vector<double> > w;

    assert( not v[0].empty() and w.size() == 0 );
    std::copy(v.begin(), v.end(), std::back_inserter(w));
    assert( not v[0].empty() and w.size() == 10 );

    std::move(v.begin(), v.end(), std::back_inserter(w));
    assert( v[0].empty() and w.size() == 20 ); // were v elements moved to w?
}

Однако я не думаю, что возможно, что элементы v действительно были перемещены в w, потому что в конце концов back_inserter сделает push_back, что подразумевает копию в w.

Представляется более вероятным, что в случае std::move элементы v были перемещены во временное и только затем скопированы в w.

Это правильно?std::back_inserter действительно как-то движется?

Есть ли уже вариант std::back_inserter, который использует преимущество перемещения / размещения? Что-то вроде std::back_emplacer?

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Если std::back_insert_iterator ничего не делает, кроме вызова push_back для контейнера, с которым он строится, на вопрос можно ответить, взглянув на набор перегрузки std::vector::push_back:

void push_back(const T& value);
void push_back(T&& value);

Итак, здесь мы явно перегружены ссылками на rvalue. Не было бы странно, если бы соответствующий std::back_insert_iterator копировал свой аргумент при вызове со ссылкой на rvalue? И действительно, у нас снова очень похожий набор перегрузки :

back_insert_iterator<Container>&
    operator=(typename Container::const_reference value);
back_insert_iterator<Container>&
    operator=(const typename Container::value_type& value);

с дополнительным комментарием,

1) Результат в контейнере-> push_back (значение)
2) Результат в контейнере-> push_back (std :: move (value))

Возвращаясь к исходному вопросу

Есть ли в действительности движущийся std :: back_inserter?

Да, итератор, который создает эта функция, использует ссылочные аргументы rvalue.

Есть ли уже вариант std :: back_inserter, который использует преимущество move / emplace?

Нет, но это может быть реализовано. См. этот ответ .

0 голосов
/ 22 января 2019

std::back_inserter() - это шаблон вспомогательной функции для создания объекта std::back_insert_iterator.

Класс std::back_insert_iterator уже перегружен operator= для приема значений r * value типов, т. Е .:

back_insert_iterator<Container>& operator=(typename Container::value_type&& value);

Таким образом, std::back_insert_iterator уже готов использовать семантику перемещения.

...