c++ - std::vector 的范围 View

标签 c++ vector range

在提议的 C++20 (The One) Ranges TS 中,将 View 转换为 std::vector 的提议方法是什么?

以下代码无法编译:

int                                           
main() {                                                        
    std::vector<float> values = {1.0, 2.0, 3.0, 4.0, 5.2, 6.0, 7.0, 8.0, 9.0}; 
    //fmt::print("{}\n", std::experimental::ranges::views::filter(values, [] (float v) { return v < 5.f; })); 
    std::vector<float> foo = vw::filter(values, [] (float v) { return v < 5.f; }); 
    fmt::print("{}\n", foo);                
}

有错误

../src/view.cpp:19:40: error: conversion from     ‘std::experimental::ranges::v1::filter_view<std::experimental::ranges::v1::ref_view<std::vector<float> >, main()::<lambda(float)> >’ to non-scalar type ‘std::vector<float>’ requested
     std::vector<float> foo = vw::filter(values, [] (float v) { return v < 5.f; }); 

(由于某些 CV 限制,注释行也将无法编译)。

那么除了使用基于范围的 for 循环之外,我该如何对 View 执行任何操作呢?

还有一些奖励问题:

  1. 我使用的 cmcSTL2 实现是否符合提案? range-v3 似乎不是。
  2. 有关于 Ranges TS 的任何文档吗?我发现的提案 PDF 几乎是一个 diff 风格的格式非常糟糕的代码转储。事实上,直接阅读 cmcSTL2 源代码对我来说更容易阅读。 cppreference 似乎也缺少......

最佳答案

将 View 转换为 std::vector(或实际上任何其他容器)的 C++20 方法是传递范围的 begin end 成员添加到接受 2 个迭代器(和一个可选分配器)的 vector 构造函数。

我也在寻找这个问题的答案。我真正想要的是接受范围的 std::vector 构造函数的重载。大约:

template <std::ranges::input_range R>
vector(R&& r) : vector(r.begin(), r.end()) {
}

但这不在 C++20 中。

首先,我实现了这个:

namespace rng = std::ranges;

template <rng::range R>
constexpr auto to_vector(R&& r) {
    using elem_t = std::decay_t<rng::range_value_t<R>>;
    return std::vector<elem_t>{r.begin(), r.end()};
}

它可以工作,但不是很“范围”:https://godbolt.org/z/f2xAcd

然后我做得更好一点:

namespace detail {
    // Type acts as a tag to find the correct operator| overload
    template <typename C>
    struct to_helper {
    };
    
    // This actually does the work
    template <typename Container, rng::range R>
    requires std::convertible_to<rng::range_value_t<R>, typename Container::value_type>
    Container operator|(R&& r, to_helper<Container>) {
        return Container{r.begin(), r.end()};
    }
}

// Couldn't find an concept for container, however a
// container is a range, but not a view.
template <rng::range Container>
requires (!rng::view<Container>)
auto to() {
    return detail::to_helper<Container>{};
}

https://godbolt.org/z/G8cEGqeq6

毫无疑问,对于具有 reserve 成员函数的 sized_range 和诸如 std::vector 之类的容器,可以做得更好。

有人提议向 C++23 添加 to 函数 ( https://wg21.link/p1206 ),我确信它会比这做得更好。

关于c++ - std::vector 的范围 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58808030/

相关文章:

c++ - 错误 c2065 : 'filename' : undeclared identifier

c++ - 在 Bjarne 的这个示例中,为什么可以将 const 限定对象传递给非 const 参数?

实体列表的 HTTP 范围 header

c++ - C/C++如何读取设备内存范围(BAR)?

c++ - 哪种数据类型可以容纳 10^31 十进制数?

c++ - QML ScrollView 与 ColumnLayout

c++ - 跨平台 unicode 路径处理

c++11 - 递归计算排序数组中某个键出现的次数

c# - C++ 中的 vector 类是否可以像 C# 中的字典类一样使用?

C++将 vector 的一个元素放入另一个 vector