erase-remove 习语如何与 ranges/constrained 算法一起使用?

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

我正在尝试使用 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));

我得到一个 errorerase 的参数不匹配:

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,这使得该特定用例的激励性降低。

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

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

std::ranges::unique(和std::ranges::remove)returns从第一个移除的元素到容器末尾的子范围,所以你需要在传递给之前使用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));

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

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