使用Range-v3从结构体提取向量并扁平化编译失败求助
使用C++17及Ubuntu22.10上的librange-v3-dev(0.11.0-2),需要从包含vector成员的结构体中提取所有vector并扁平化,且不在堆上创建新vector。编写代码后期望输出「1 2 3 4 5 6 7」,但执行编译命令c++ --std=c++17 range.cpp时出现编译错误:
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 >, main()::<lambda(const auto:10&)> >' and 'const ranges::views::view_closureranges::views::join_fn')
16 | auto flattened_range = As | view::transform(getter)| view::join;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ ~~~~~~~~~~
| | |
| | const ranges::views::view_closureranges::views::join_fn
| ranges::transform_view<ranges::ref_view<std::vector >, main()::<lambda(const auto:10&)> >
In file included from /usr/include/c++/11/regex:39,
对应的代码:
#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; }
错误原因
在range-v3 0.11.0版本中,view::join要求上游transform_view返回的是视图类型或range的引用,而你的lambda通过return r.vv;返回了std::vector<int>的拷贝,这种值类型无法被join正确识别,导致运算符匹配失败。
修改方法
有两种可行的修改方式,都不会在堆上创建新vector:
返回vector的视图
用ranges::views::all将vector包装为视图,这样transform后输出的是视图序列,符合join的要求:#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}} }; // 返回vector的视图而非拷贝 auto getter = [](const auto& r) { return views::all(r.vv); }; auto flattened_range = As | views::transform(getter) | views::join; for (auto i : flattened_range){ std::cout << i << " "; } return 0; }返回vector的const引用
显式让lambda返回const std::vector<int>&,确保transform后传递的是原vector的引用而非拷贝:auto getter = [](const auto& r) -> const std::vector<int>& { return r.vv; };
两种修改方式都能编译通过并输出期望的结果,且不会额外创建堆上的vector,完全符合需求。
内容的提问来源于stack exchange,提问作者XXXXXL

