阅读 cppreference.com,我注意到 ranges::find_last_if 不返回迭代器,但 ranges::find_if 却返回迭代器。我想知道这个决定是否有充分的理由?
显然,正确的用法是使用
ranges::find_if
并反转范围:
const auto it = std::ranges::find_if(data | std::views::reverse, func);
也就是说,
ranges::find_last_if
返回迭代器对我来说似乎更直观,所以我对其目的很好奇。
基本上,
std::ranges
算法会尽可能返回结束迭代器。
例如,
std::ranges::for_each
返回 in_fun_result
。 in
组件是到源范围末尾的迭代器。std::ranges::copy
返回 in_out_result
。 in
是到源范围末尾的迭代器,out
是到目标范围末尾的迭代器。 (std::copy
仅返回目标范围的末尾。)std::ranges::fill
和 std::ranges::generate
将迭代器返回到目标范围的末尾。 (std
算法什么也不返回。)原因是,与传统的
std
算法不同,ranges
算法需要一个迭代器和一个 sentinel。使用哨兵(它本身不是迭代器)唯一可以做的就是将其与迭代器进行比较。如果它们比较相等,则表示已到达范围末尾。
由于哨兵不如迭代器有用,并且这些算法无论如何都需要获取结束迭代器,因此它们返回该迭代器以免丢失有价值的信息。
对于
std::ranges::find_last_if
,这意味着它应该返回一个迭代器到它找到的元素,和一个结束迭代器。它们自然地形成 subrange
,这就是 std::ranges::find_last_if
实际返回的内容。
如果不需要结束迭代器,可以使用
subrange::begin
提取第一个迭代器。
const auto it = std::ranges::find_last_if(data, func).begin();