18

我正在尝试对擦除删除习语使用 c++20 约束算法:

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

但是当我做一个简单的转换时:

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

我收到一个参数不匹配的错误:erase

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

如果第二个参数是 ,则会产生类似的错误std::ranges::end(v)

我怎样才能让它工作?


该问题最初用于remove代替unique,但std::erase所有容器都存在重载,这使得该特定用例的动机降低。

4

3 回答 3

12

std::ranges::unique(and std::ranges::remove) 返回从第一个删除元素到容器末尾的子范围,因此您需要std::begin在传递给之前使用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));
于 2020-10-10T20:20:15.780 回答
4

它不起作用,因为std::ranges::remove()返回的不是迭代器而是范围。但即使你尝试v.erase(std::ranges::remove(...))它也不起作用,因为向量没有erase()以范围为参数的重载。

相反,请看一下std::erase()(在 中定义<vector>)。您需要的可能只是std::erase(v, 42).

于 2020-10-10T19:36:11.403 回答
4

另一种选择是分解std::ranges::remove/返回的子范围unique,并使用这些迭代器:

auto [Beg, End] = std::ranges::remove(v, 42);
v.erase(Beg, End);
于 2020-10-13T07:11:26.237 回答