[ranges.subrange]中`iterator-sentinel-pair`概念的目的是什么?

[range.subrange] 中iterator-sentinel-pair定义的仅展示概念的目的是什么?

template<class T> 
concept iterator-sentinel-pair = // exposition only 
  !range<T> && pair-like<T> && 
  sentinel_for<tuple_element_t<1, T>, tuple_element_t<0, T>>;

据我所知,它唯一使用的时间是用于 CTAD,例如在

template<iterator-sentinel-pair P>
  subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;

但是,没有任何构造函数std::ranges::subrange适用于这个概念:唯一可能适合这个参数列表的真正构造函数是这个:

template<not-same-as<subrange> R> 
  requires borrowed_range<R> &&
           convertible-to-non-slicing<iterator_t<R>, I> &&
           convertible_to<sentinel_t<R>, S>
constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);

这需要(通过borrowed_range<R>)我们拥有range<R>......但iterator-sentinel-pair 明确要求not range<R>

在我看来,目的是允许代码沿着

std::multiset foo = // ...
auto result = foo.equal_range(key);  // an iterator-sentinel pair
for (auto value : std::ranges::subrange(result)) {
  // ...
}

但这显然不会编译,因为std::pair<It, It>不满足std::range. 也许允许这个用例的构造函数被忽略了?

我还有其他什么目的吗?

回答

[range.subrange] 中定义的仅展示迭代器-哨兵对概念的目的是什么?

不再有任何目的,它们已从上次全体会议通过的LWG 3404 中删除,并将很快从草案中删除。在LWG 3281中删除了所有使用它们的东西之后,它们只是残留的监督。


最初,这个概念的目的正是为了允许:

for (auto value : std::ranges::subrange(foo.equal_range(key))) {
    // ...
}

但是基于以下推理删除了隐含性:

仅仅因为一对持有两个迭代器,并不意味着这两个迭代器表示一个有效的范围。将这种类似对的类型隐式转换为子范围是危险的,应该被禁止。

尽管至少进行显式转换似乎很有用。值得庆幸的是,编写我们自己很简单:

template <typename P>
    requires (std::tuple_size_v<P> == 2)
          && std::ranges::sentinel_for<std::tuple_element_t<1, P>,
                                       std::tuple_element_t<0, P>>
auto make_subrange_from_pair(P pair) {
    // either this
    auto [b, e] = pair;
    return subrange(b, e);
    // or that
    return subrange(std::get<0>(pair), std::get<1>(pair));
}


以上是[ranges.subrange]中`iterator-sentinel-pair`概念的目的是什么?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>