Использование erase-remove идиома в неуникальных коллекциях

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
enum class En{A, B};
std::vector<En> vec{En::A, En::B, En::A, En::B, En::A, En::B, En::A};

for(const auto& i : vec) std::cout << int(i) << ", ";
std::cout << std::endl;

vec.erase(std::remove(std::begin(vec), std::end(vec), vec.front()),
std::end(vec));

for(const auto& i : vec) std::cout << int(i) << ", ";
std::cout << std::endl;

return 0;
}

Ideone: http://ideone.com/NTPVyE

Печать:

0, 1, 0, 1, 0, 1, 0,

1, 0, 0, 0,

Почему это происходит? Разве не должен быть удален только первый элемент вектора?

Я полагаю std::remove не останавливается на первом элементе, но проходит через весь вектор. Есть ли способ, которым я могу использовать стереть-удалить идиому на коллекциях с неуникальными элементами?

3

Решение

Третий аргумент std::remove это const ссылка. При перемещении элементов вы меняете значение элемента, на который ссылаются, что приводит к неопределенному поведению.

Это будет хорошо себя вести:

auto elem = vec.front(); // copy front element
vec.erase(std::remove(std::begin(vec), std::end(vec), elem),
std::end(vec));

Выход:

1, 1, 1,

7

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector