ranges::actions::transform处理POD结构体的std::vector编译失败问题
问题分析:Ranges Actions Transform 无法处理POD结构体的原因
问题重现
可正常编译的int类型示例
std::vector<int> ints{10, 20, 30}; auto floats = ints | ranges::to_vector | ranges::actions::transform([](auto n){ return 1 / float(n); });
定义的POD结构体
struct Foo { int* hello; int num; float yes; };
无法编译的Foo类型示例
std::vector<Foo> foo; auto bar = foo | ranges::to_vector | ranges::actions::transform([](auto f){ return f.hello; });
编译错误提示不满足invocable_概念,即transform无法作用于Foo类型。但Foo是平凡可复制类型,为何通用lambda无法适用?
核心原因
ranges::actions::transform是原地修改容器的动作,它的约束不仅要求转换函数能被调用,还要求转换函数的返回值可以赋值给原容器的元素类型:
- 第一个示例中,转换函数返回
float,原容器元素类型是int,float可以隐式转换为int,满足赋值要求,因此编译通过。 - 第二个示例中,转换函数返回
int*,原容器元素类型是Foo,int*无法赋值给Foo类型,直接违反了actions::transform的底层约束,导致编译报错。
解决办法
如果目标是生成存储int*的新容器,不要使用原地修改的actions::transform,改用ranges::views::transform生成视图后,再转换为vector:
auto bar = foo | ranges::views::transform([](auto f){ return f.hello; }) | ranges::to_vector;
这样会基于原容器生成一个包含int*的新vector<int*>,而非尝试修改原vector<Foo>的元素。
内容的提问来源于stack exchange,提问作者Romário
相关产品推荐
相关产品推荐

