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));
我得到一个 error,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
,这使得该特定用例的激励性降低。
它不起作用,因为 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);
我正在尝试使用 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));
我得到一个 error,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
,这使得该特定用例的激励性降低。
它不起作用,因为 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);