C++20 引入了一个std::common_iterator
能够将非公共元素范围(迭代器和哨兵的类型不同)表示为公共范围(它们相同)的元素,其概要定义为:
template<input_or_output_iterator I, sentinel_for<I> S>
requires (!same_as<I, S> && copyable<I>)
class common_iterator {
// ...
private:
variant<I, S> v_; // exposition only
};
它对于与期望范围的开始和结束具有相同类型的遗留代码交互很有用。
在[iterators.common#common.iter.types-1.1]中,其iterator_concept
定义为:
iterator_concept
表示forward_iterator_tag
如果I
模型forward_iterator
;否则表示input_iterator_tag
。
为什么common_iterator
最多只能是 a forward_iterator
,而不能完全iterator_concept
基于I
's来定义它iterator_category
?例如,如果I
是random_asscess_iterator
,那么common_iterator<I, S>
是random_asscess_iterator
,等等。
似乎这在技术上是可行的,因为common_iterator
仅用于std::variant
键入擦除I
和S
.
考虑以下(godbolt):
auto r = views::iota(0) | std::views::take(5);
static_assert( ranges::random_access_range<decltype(r)>);
auto cr = r | views::common;
static_assert(!ranges::random_access_range<decltype(cr)>);
static_assert( ranges::forward_range<decltype(cr)>);
r
是random_access_range
,所以 C++20 约束算法比如ranges::binary_search
可以使用这个 trait 对其执行更高效的操作,但是为了使旧std
算法能够应用它,我们需要使用views::common
将它转换为common_range
. 但是,它也会退化为 a forward_range
,这会降低算法的效率。
为什么标准最多只定义common_iterator
为forward_iterator
?这背后的考虑是什么?