简体   繁体   中英

How does the erase-remove idiom work with ranges/constrained algorithms?

I'm trying to use a c++20 constrained algorithm for the erase-remove idiom:

std::vector<int> v;
v.erase(std::unique(std::begin(v), std::end(v)), std::end(v));

but when I do a simple transformation:

v.erase(std::ranges::unique(v), std::end(v));

I get an error that the arguments to erase don't match:

error: no matching function for call to 'std::vector<int>::erase(std::ranges::borrowed_subrange_t<std::vector<int>&>, std::vector<int>::iterator)'

A similar error is produced if the second argument is std::ranges::end(v) .

How can I get this to work?


The question originally used remove instead of unique , but there is an overloaded std::erase for all containers that makes that particular use case less motivating.

std::ranges::unique (and std::ranges::remove ) returns a sub range from the first removed element to the end of the container so you need to use std::begin before passing to std::vector::erase :

v.erase(std::ranges::begin(std::ranges::remove(v, 42)), std::end(v));
v.erase(std::ranges::begin(std::ranges::unique(v)), std::end(v));

It doesn't work since std::ranges::remove() returns not iterator but range. But even if you try v.erase(std::ranges::remove(...)) it will not work, because vector does not have erase() overload which takes range as parameter.

Instead, take a look at std::erase() (defined in <vector> ). What you need is probably just std::erase(v, 42) .

Another option would be decomposing the subrange returned by std::ranges::remove / unique , and use those iterators:

auto [Beg, End] = std::ranges::remove(v, 42);
v.erase(Beg, End);

In C++20, std::ranges::unique/remove returns a std::ranges::subrange which contains the sub-range that we want to erase usually ( begin() point to the first removed element, and end() point to the containers's end() ), so I think the proper erase-remove idiom in C++20 is:

std::vector<int> v;
v.resize(v.size() - std::ranges::unique(v).size());
v.resize(v.size() - std::ranges::remove(v, 42).size());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM