范围视图到 std::vector

Ric*_*ock 4 c++ vector range

在建议的 C++20 (The One) Ranges TS 中,建议将视图转换为 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);                
}
Run Code Online (Sandbox Code Playgroud)

有错误

../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; }); 
Run Code Online (Sandbox Code Playgroud)

(由于某些 CV 限制,注释行也不会编译)。

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

还有一些奖金问题:

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

Rup*_*ash 5

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

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

template <std::ranges::input_range R>
vector(R&& r) : vector(r.begin(), r.end()) {
}
Run Code Online (Sandbox Code Playgroud)

但这不在 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()};
}
Run Code Online (Sandbox Code Playgroud)

它有效,但不是很“乱”: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>{};
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/G8cEGqeq6

毫无疑问,对于具有成员函数的sized_ranges 和容器可以做得更好。std::vectorreserve

有一个建议向toC++23 ( https://wg21.link/p1206 )添加一个函数,这会比这做得更好,我敢肯定。

  • 对于 MSVC 用户:https://godbolt.org/z/8bcn8qh8f (2认同)