简体   繁体   中英

Why do the new ranges remove_* algorithms move the first iterator?

I was reading through the MSVC STL implementation of std::ranges::remove when I noticed the following line:

_First = _RANGES _Find_if_unchecked(_STD move(_First), _Last, _Pred, _Proj);

Indeed, cppreference has the following line in their 'possible implementation' too:

first = ranges::find_if(std::move(first), last, pred, proj);

What's confusing to me is, I've just about never seen anyone move an iterator; they're typically cheap to copy (or at least should be), and even if this were an issue of copies, we could take a universal reference and std::forward the iterator to find_if instead surely?

What advantage does casting to an rvalue reference have here over simply passing by value?

ranges::find_if accepts input_iterator , which is not necessarily copyable (an example in the standard is basic_istream_view::iterator ).

In the C++20 iterator system, only iterators that model forward_iterator are guaranteed to be copyable, so std::move is necessary here.

and even if this were an issue of copies, we could take a universal reference and std::forward the iterator to find_if instead surely?

Iterators are generally passed by value.

When the first iterator is not guaranteed to be copyable, we need to transfer its ownership to ranges::find_if via std::move , and re-accept its ownership via its return.

(Although in your example std::move can be omitted since ranges::remove already requires forward_iterator )

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