Search code examples
c++range-v3

c++ range-v3 extract vectors from struct and join them


Given a struct which has a vector member, I would like to extract all of them and then flatten them, without creating new vectors on the heap

I'm using c++17 and librange-v3-dev(0.11.0-2), ubuntu22.10

#include <range/v3/all.hpp>
#include <vector>
#include <iostream>

struct A {
    std::vector<int> vv;
};

int main()
{
    using namespace ranges;
    std::vector<A> As = { A{{1,2,3,4}}, A{{5,6,7}} };
    
    auto getter = [](const auto&r) { return r.vv; };

    auto flattened_range = As | view::transform(getter)| view::join;

    for (auto i : flattened_range){
      std::cout << i << " "; 
    }

    return 0;
}

I would expect it prints

1 2 3 4 5 6 7

I can't figure out how to compile it,

compiled with

c++ --std=c++17 range.cpp

here is the compiling error:

range.cpp: In function 'int main()':                                                                  
range.cpp:16:56: error: no match for 'operator|' (operand types are 'ranges::transform_view<ranges::ref_view<std::vector<A> >, main()::<lambda(const auto:10&)> >' and 'const ranges::views::view_closure<ran
ges::views::join_fn>')                                                                                                                                                                                          16 |     auto flattened_range = As | view::transform(getter)| view::join;
      |                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ ~~~~~~~~~~
      |                               |                                |
      |                               |                                const ranges::views::view_closure<ranges::views::join_fn>
      |                               ranges::transform_view<ranges::ref_view<std::vector<A> >, main()::<lambda(const auto:10&)> >
In file included from /usr/include/c++/11/regex:39,                                                   


Solution

  • This is a limitation in ranges-v3 v0.11. In v0.12 your code works with a slight adjustment: You need to replace ranges::view with ranges::views, like this:

    #include <range/v3/all.hpp>
    
    #include <iostream>
    #include <vector>
    
    struct A {
        std::vector<int> vv;
    };
    
    int main() {
        std::vector<A> As = {A{{1, 2, 3, 4}}, A{{5, 6, 7}}};
    
        auto getter = [](const auto& r) { return r.vv; };
    
        auto flattened_range = As
                             | ranges::views::transform(getter)
                             | ranges::views::join;
    
        for (auto i : flattened_range) {
            std::cout << i << " ";
        }
    }
    

    Demo