[英]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));
我收到一個錯誤,指出要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::unique
(和std::ranges::remove
)返回從第一個移除元素到容器末尾的子范圍,因此您需要在傳遞給std::vector::erase
之前使用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()
返回的不是迭代器而是范圍。 但即使您嘗試v.erase(std::ranges::remove(...))
它也不會工作,因為 vector 沒有將 range 作為參數的erase()
重載。
相反,看看std::erase()
(在<vector>
定義)。 您需要的可能只是std::erase(v, 42)
。
另一種選擇是分解std::ranges::remove
/ unique
返回的子std::ranges::remove
,並使用這些迭代器:
auto [Beg, End] = std::ranges::remove(v, 42);
v.erase(Beg, End);
在 C++20 中, std::ranges::unique/remove
返回一個std::ranges::subrange
,它包含我們通常想要擦除的子范圍( begin()
指向第一個被刪除的元素,而end()
指向容器的end()
),所以我認為 C++20 中正確的擦除-刪除習慣用法是:
std::vector<int> v;
v.resize(v.size() - std::ranges::unique(v).size());
v.resize(v.size() - std::ranges::remove(v, 42).size());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.