7

所以我最近看了这个关于 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;
    }
}
4

1 回答 1

10

range-v3 错误消息往往非常可怕,以至于这个实际上比大多数错误消息要好:

prog.cc:在 lambda 函数中:
prog.cc:16:90:错误:不匹配调用 '(const 范围::v3::yield_from_fn) (std::vector<int>&)'
         | 范围::视图::for_each([](std::vector<int> num) { 返回范围::yield_from(num); })
                                                                                          ^
在 /opt/wandbox/range-v3/include/range/v3/view.hpp:38:0 包含的文件中,
                 来自/opt/wandbox/range-v3/include/range/v3/all.hpp:21,
                 来自 prog.cc:1:
/opt/wandbox/range-v3/include/range/v3/view/for_each.hpp:133:17:注意:候选:模板<class Rng,int _concept_requires_132,类型名std::enable_if<((_concept_requires_132 == 43) || 范围::v3::concepts::models<ranges::v3::concepts::View, T>()), int>::type <anonymous> > Rng 范围::v3::yield_from_fn::operator ()(Rng) 常量
             Rng operator()(Rng rng) 常量
                 ^~~~~~~~

对于对 range-v3 的概念仿真层有一点了解的人,这“清楚地”表明调用yield_from失败是因为您传递给它的参数的类型std::vector<int>- 不满足View概念。

View概念表征了不拥有其元素的范围子集,因此具有所有操作 - 移动/复制构造/赋值,开始,结束和默认构造 - 可在 O(1) 中计算。range-v3 中的范围组合代数仅适用于视图,以避免必须处理元素寿命并提供可预测的性能。

yield_from拒绝std::vector您尝试传递的 s,因为它们不是视图,但您可以通过以下方式轻松提供视图:(1) 将向量作为左值而不是按 in 的值for_each,以及 (2) 产生view::all这些左值 [ DEMO ]:

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); });
于 2017-04-24T05:00:48.970 回答