range v3 展平序列
range v3 flattening a sequence
所以我最近看了这个关于 c++ 的演讲:
https://www.youtube.com/watch?v=mFUXNMfaciE
而且我非常有兴趣尝试一下。因此,在一些玩具程序之后,我一直在研究如何将向量的向量正确地展平为一个向量。根据此处的文档:https://ericniebler.github.io/range-v3/ 这可以使用 ranges::view::for_each
。但是我似乎无法让它工作。这是一些最小的代码。
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
int main()
{
auto nums = std::vector<std::vector<int>>{
{0, 1, 2, 3},
{5, 6, 7, 8},
{10, 20},
{30},
{55}
};
auto filtered = nums
| ranges::view::for_each([](std::vector<int> num) { return ranges::yield_from(num); })
| ranges::view::remove_if([](int i) { return i % 2 == 1; })
| ranges::view::transform([](int i) { return std::to_string(i); });
for (const auto i : filtered)
{
std::cout << i << std::endl;
}
}
range-v3 错误消息往往非常可怕,以至于这个实际上比大多数都好:
prog.cc: In lambda function:
prog.cc:16:90: error: no match for call to '(const ranges::v3::yield_from_fn) (std::vector<int>&)'
| ranges::view::for_each([](std::vector<int> num) { return ranges::yield_from(num); })
^
In file included from /opt/wandbox/range-v3/include/range/v3/view.hpp:38:0,
from /opt/wandbox/range-v3/include/range/v3/all.hpp:21,
from prog.cc:1:
/opt/wandbox/range-v3/include/range/v3/view/for_each.hpp:133:17: note: candidate: template<class Rng, int _concept_requires_132, typename std::enable_if<((_concept_requires_132 == 43) || ranges::v3::concepts::models<ranges::v3::concepts::View, T>()), int>::type <anonymous> > Rng ranges::v3::yield_from_fn::operator()(Rng) const
Rng operator()(Rng rng) const
^~~~~~~~
对于对 range-v3 的仿真层概念有一点了解的人来说,这个 "clearly" 声明对 yield_from
的调用失败,因为您传递给它的参数类型 - std::vector<int>
- 不满足 View
概念。
View
概念描述了不拥有其元素的范围子集,因此具有所有操作 - move/copy construction/assignment、开始、结束和默认构造 - 可计算在 O(1) 中。 range-v3 中的范围组合代数仅适用于视图,以避免必须处理元素生命周期并提供可预测的性能。
yield_from
拒绝您尝试传递的 std::vector
s,因为它们不是视图,但您可以通过 (1) 将向量作为左值而不是 for_each
,以及 (2) 产生这些左值 [DEMO]:
的 view::all
auto filtered = nums
| ranges::view::for_each([](std::vector<int>& num) {
return ranges::yield_from(ranges::view::all(num)); })
| ranges::view::remove_if([](int i) { return i % 2 == 1; })
| ranges::view::transform([](int i) { return std::to_string(i); });
但在这种简单的情况下,将一系列元素的范围展平为一系列元素已经在 range-v3 中具有特定用途的视图:view::join
。您也可以使用 [DEMO]:
auto filtered = nums
| ranges::view::join
| ranges::view::remove_if([](int i) { return i % 2 == 1; })
| ranges::view::transform([](int i) { return std::to_string(i); });
所以我最近看了这个关于 c++ 的演讲: https://www.youtube.com/watch?v=mFUXNMfaciE
而且我非常有兴趣尝试一下。因此,在一些玩具程序之后,我一直在研究如何将向量的向量正确地展平为一个向量。根据此处的文档:https://ericniebler.github.io/range-v3/ 这可以使用 ranges::view::for_each
。但是我似乎无法让它工作。这是一些最小的代码。
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
int main()
{
auto nums = std::vector<std::vector<int>>{
{0, 1, 2, 3},
{5, 6, 7, 8},
{10, 20},
{30},
{55}
};
auto filtered = nums
| ranges::view::for_each([](std::vector<int> num) { return ranges::yield_from(num); })
| ranges::view::remove_if([](int i) { return i % 2 == 1; })
| ranges::view::transform([](int i) { return std::to_string(i); });
for (const auto i : filtered)
{
std::cout << i << std::endl;
}
}
range-v3 错误消息往往非常可怕,以至于这个实际上比大多数都好:
prog.cc: In lambda function: prog.cc:16:90: error: no match for call to '(const ranges::v3::yield_from_fn) (std::vector<int>&)' | ranges::view::for_each([](std::vector<int> num) { return ranges::yield_from(num); }) ^ In file included from /opt/wandbox/range-v3/include/range/v3/view.hpp:38:0, from /opt/wandbox/range-v3/include/range/v3/all.hpp:21, from prog.cc:1: /opt/wandbox/range-v3/include/range/v3/view/for_each.hpp:133:17: note: candidate: template<class Rng, int _concept_requires_132, typename std::enable_if<((_concept_requires_132 == 43) || ranges::v3::concepts::models<ranges::v3::concepts::View, T>()), int>::type <anonymous> > Rng ranges::v3::yield_from_fn::operator()(Rng) const Rng operator()(Rng rng) const ^~~~~~~~
对于对 range-v3 的仿真层概念有一点了解的人来说,这个 "clearly" 声明对 yield_from
的调用失败,因为您传递给它的参数类型 - std::vector<int>
- 不满足 View
概念。
View
概念描述了不拥有其元素的范围子集,因此具有所有操作 - move/copy construction/assignment、开始、结束和默认构造 - 可计算在 O(1) 中。 range-v3 中的范围组合代数仅适用于视图,以避免必须处理元素生命周期并提供可预测的性能。
yield_from
拒绝您尝试传递的 std::vector
s,因为它们不是视图,但您可以通过 (1) 将向量作为左值而不是 for_each
,以及 (2) 产生这些左值 [DEMO]:
view::all
auto filtered = nums
| ranges::view::for_each([](std::vector<int>& num) {
return ranges::yield_from(ranges::view::all(num)); })
| ranges::view::remove_if([](int i) { return i % 2 == 1; })
| ranges::view::transform([](int i) { return std::to_string(i); });
但在这种简单的情况下,将一系列元素的范围展平为一系列元素已经在 range-v3 中具有特定用途的视图:view::join
。您也可以使用 [DEMO]:
auto filtered = nums
| ranges::view::join
| ranges::view::remove_if([](int i) { return i % 2 == 1; })
| ranges::view::transform([](int i) { return std::to_string(i); });