问题描述
在提出的C ++ 20(The One)Ranges TS中,提出的将视图转换为std :: vector的方法是什么?
In the proposed C++20 (The One) Ranges TS, what is the proposed method for converting the view into a 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; });
(由于某些简历约束,注释行也将无法编译).
(the commented line will also not compile due to some CV constraints).
那么除了使用基于范围的for循环之外,如何对视图做任何事情?
So how do I do anything with a view except for using a range-based for loop?
还有一些奖励问题:
- 即使遵循该建议,我仍使用cmcstl2实现吗?Ranges-v3似乎不是.
- Ranges TS上是否有任何文档?我发现的提案PDF几乎是diff格式的格式错误的代码转储.实际上,直接阅读cmcstl2源代码对我来说更容易阅读.似乎也没有cppreference ...
推荐答案
要通过C ++ 20方法将视图转换为 std :: vector
(或者实际上是任何其他容器)范围的 begin
和 end
成员加入 vector
构造函数,该构造函数接受2个迭代器(和可选的分配器).
The C++20 method to convert a view to a std::vector
(or indeed any other container) is to pass the range's begin
and end
members to the vector
constructor that accepts 2 iterators (and an optional allocator).
我也在寻找这个问题的答案.我真正想要的是 std :: vector
的构造函数的重载,它接受一个范围.大约:
I was also looking for an answer to this question. What I really wanted is an overload of the constructor of std::vector
accepting a range. Approximately:
template <std::ranges::input_range R>
vector(R&& r) : vector(r.begin(), r.end()) {
}
但是C ++ 20中没有.
but that isn't in C++20.
首先,我实现了这一点:
First, I implemented this:
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
which works, but isn't very "rangy": 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
成员函数的 size_range
s和类似 std :: vector
的容器,人们可以做得更好.
No doubt one can do better for sized_range
s and containers like std::vector
that have a reserve
member function.
有人建议向C ++ 23中添加 to
函数( https://wg21.link/p1206 ),我相信这会做得更好.
There is a proposal to add a to
function to C++23 (https://wg21.link/p1206) which will do a better job than this, I'm sure.
这篇关于范围视图到std :: vector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!