首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >contiguous_range总是sized_range吗?

contiguous_range总是sized_range吗?
EN

Stack Overflow用户
提问于 2020-10-19 18:36:30
回答 3查看 1K关注 0票数 21

关于C++20中的ranges库,我有以下问题:

std::ranges::contiguous_range<T>为任意类型T。

我可以假设std::ranges::sized_range<T>

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-10-19 18:48:29

不,不是每个contiguous_range都是sized_range

最简单的例子是以空结尾的字符串。它是连续的,但在O(1)时我们不知道它的大小。我们可以很容易地用哨兵来表示这样的东西:

代码语言:javascript
复制
struct ntbs_sentinel {
    bool operator==(char const* p) const {
        return *p == '\0';
    }
};

struct ntbs {
    char const* p;
    char const* begin() const { return p; }
    ntbs_sentinel end() const { return {}; }
};

static_assert(std::ranges::contiguous_range<ntbs>);
static_assert(!std::ranges::sized_range<ntbs>);

另一个例子是,给定一些std::string对象s和一些谓词p,或者:

  • s | std::views::take_while(p)
  • s | std::views::drop_while(p)

这里的结果范围仍然是连续的,但是我们不知道它在哪里结束(在第一种情况下)或者从哪里开始(在第二种情况下),所以我们不知道它的大小。

票数 26
EN

Stack Overflow用户

发布于 2020-10-19 21:03:13

由于哨兵的存在,contiguous_range<T>不足以被视为sized_range<T>。但是,如果将contiguous_range<T>common_range<T>组合(这要求哨兵是迭代器),那么sized_range<T>也必须是真的。

这是逻辑。contiguous_range<T>也是random_access_range<T>random_access_range<T>在一定程度上意味着是真的。 is_same, sentinel_t>。因此,random_access_iterator<sentinel_t<T>>也必须是真。

现在,random_access_iterator<It>强加于人std::sized_sentinel_for<I, I>是真的。因为iterator_t<T>sentinel_t<T>是相同的类型,这意味着std::sized_sentinel_for<sentinel_t<T>, iterator_t<T>>也必须是真。

那么,让我们来看看sized_range<T>。这要求std::ranges::size(t)对于类型为Tt有效。

是有效的 if T建模ranges::forward_range<T> (它确实建模),sentinel_t<T>iterator_t<T>建模std::sized_sentinel_for<sentinel_t<T>, iterator_t<T>>

如前所述,确实如此。

票数 11
EN

Stack Overflow用户

发布于 2020-10-19 18:49:07

不是的。

contiguous_range是:

代码语言:javascript
复制
template<class T>
concept contiguous_range =
  ranges::random_access_range<T> &&
  std::contiguous_iterator<ranges::iterator_t<T>> &&
  requires(T& t) {
    { ranges::data(t) } ->
      std::same_as<std::add_pointer_t<ranges::range_reference_t<T>>>;
  };

正如您所看到的,它是requires random_access_range,即:

代码语言:javascript
复制
template<class T>
concept random_access_range =
  ranges::bidirectional_range<T> && std::random_access_iterator<ranges::iterator_t<T>>;

另一方面,requires bidirectional_range,也就是:

代码语言:javascript
复制
template<class T>
concept bidirectional_range =
  ranges::forward_range<T> && std::bidirectional_iterator<ranges::iterator_t<T>>;

哪个requires forward_range,即:

代码语言:javascript
复制
template<class T>
concept forward_range =
  range::input_range<T> && std::forward_iterator<ranges::iterator_t<T>>;

以及requires input_range,所以它需要:

代码语言:javascript
复制
template<class T>
concept input_range =
  ranges::range<T> && std::input_iterator<ranges::iterator_t<T>>;

rangerequires std::ranges::begin()std::ranges::end()对于给定的T有效。

你可以和那些std::XXX_iterator玩类似的游戏,没有任何std::ranges::size (支持sized_range)的东西。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64433293

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档