在建议的 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 循环之外,我如何对视图执行任何操作?
还有一些奖金问题:
将视图转换为 a std::vector
(或实际上任何其他容器)的 C++20 方法是将范围begin
和end
成员传递给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_range
s 和容器可以做得更好。std::vector
reserve
有一个建议向to
C++23 ( https://wg21.link/p1206 )添加一个函数,这会比这做得更好,我敢肯定。