【问题标题】:c++20 ranges view to vectorc++20 范围视图到向量
【发布时间】:2020-07-27 13:01:26
【问题描述】:

现在 C++20 范围实现实际上已经发布并在 GCC 10.2 下发布,我想知道如何将范围视图转换回实际容器,如矢量。 我发现这个问题 (Range view to std::vector) 对预发布版本提出了同样的问题,但我想知道自从它发布以来,是否有任何新方法可以从视图转换为容器?还是该问题的单一答案仍然是最佳解决方案?

【问题讨论】:

标签: c++ c++20


【解决方案1】:

最简单的做法是使用 range-v3,它有一个专门用于此目的的转换运算符。来自the examples

using namespace ranges;
auto vi =
    views::for_each(views::ints(1, 10), [](int i) {
        return yield_from(views::repeat_n(i, i));
    })
  | to<std::vector>();
// vi == {1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,...}

否则,链接问题中的答案并不完全准确,因为范围可能没有相同的迭代器和哨兵类型,而答案需要它。所以我们可以做得更好一点:

template <std::ranges::range R>
auto to_vector(R&& r) {
    std::vector<std::ranges::range_value_t<R>> v;

    // if we can get a size, reserve that much
    if constexpr (requires { std::ranges::size(r); }) {
        v.reserve(std::ranges::size(r));
    }

    // push all the elements
    for (auto&& e : r) {
        v.push_back(static_cast<decltype(e)&&>(e));
    }

    return v;
}

上述的较短版本,不一定在所有相同的地方预先保留,通过使用views::common 解决混合哨兵类型问题:

template <std::ranges::range R>
auto to_vector(R&& r) {
    auto r_common = r | std::views::common;
    return std::vector(r_common.begin(), r_common.end());
}

此处错过保留的典型示例是使用 std::list&lt;T&gt; 调用 to_vector() - 它有一个 O(1) size() 可用,可用于保留,但一旦我们进入迭代器。

【讨论】:

  • 感谢您的详细回答,但您是否知道为什么从 c++20 规范中删除了 range-v3 to 和 to_vector 函数?
  • @Foxie 他们没有被丢弃——他们从来没有进去过。
  • 为什么他们从来没有进来过?从视图返回到具体容器,这似乎是一件好事。
  • @Foxie 这是一件好事。但是 Ranges 已经庞大了。有很多好东西不在里面。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
相关资源
最近更新 更多