[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));
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句