Почему идиома удаления-удаления не работает для обратного итератора
Моей целью было попытаться решить этот вопрос: удалить все пустые элементы в векторе с конца. используя стирание-удаление идиомы.
Идея состоит в том, чтобы удалить все элементы, начиная с конца, которые являются пустыми (равными пробелу) в данном std::vector<std::string>
струн. Удаление элементов должно прекратиться, когда будет найден непустой элемент.
Пример:
vec = { " ", "B", " ", "D", "E", " ", " ", " " };
После удаления:
vec = { " ", "B", " ", "D", "E"};
Вот решение, которое я попробовал:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <iterator>
int main()
{
std::vector<std::string> vec = { " ", "B", " ", "D", "E", " ", " ", " " };
bool notStop = true;
auto removeSpaceFromLast = [&](const std::string& element)-> bool
{
if(element != " " ) notStop = false;
return ( (element == " ") && (notStop) );
};
vec.erase(
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast),
vec.rend() );
std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(std::cout,","));
return 0;
}
Это дало мне ошибку:
no matching function for call to std::vector<std::__cxx11::basic_string<char> >::erase(std::reverse_iterator<__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >, std::vector<std::__cxx11::basic_string<char> >::reverse_iterator)'|
Затем я прочитал о работе std::vector::erase()
здесь: vector:: erase не работает с обратными итераторами?
И изменил код:
vec.erase(
std::remove_if(vec.rbegin().base(), vec.rend().base(), removeSpaceFromLast),
vec.rend().base() );
На этот раз он скомпилирован, но дал мне вывод = оригинальный вектор.
Кто-нибудь может объяснить:
- Почему это случилось?
- Если это возможно, как мы можем это исправить?
1 ответ
Вы пропустили звонки base()
, remove_if
переместит все найденные пробелы, начиная с конца, в начальную часть вектора (как при перемещении найденных пробелов, начиная с начала, переместится в конец, если использовались прямые итераторы) и вернет итератор, указывающий на конечную позицию переменной to -be-стерли последовательность (то есть начало пространства, которое будет сохранено, так как мы изменили значения итератора), то есть:
" ", " ", " ", "B", " ", "D", "E"
Затем вы должны стереть с самого начала, т.е. rend().base()
,
vec.erase(vec.rend().base(),
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast).base()
);