调用自定义split_partition函数时,为何需使用const lambda?
为什么用非const引用Lambda调用split_partition会编译失败?
我实现了一个基于std::partition_copy的模板函数split_partition,用来根据谓词把容器元素分割到原容器和目标容器中,代码如下:
template<class Container, class Predicate> void split_partition(Container& src, Container& dest, Predicate p) { auto ends = std::partition_copy( std::make_move_iterator( src.begin() ), std::make_move_iterator( src.end() ), src.begin(), std::back_inserter(dest), p ); src.erase(ends.first, src.end()); }
我用以下方式调用时编译失败:
split_partition(a, b, [](auto& t) {return t.i > 4; });
但把Lambda参数改成const引用后就能正常编译:
split_partition(a, b, [](const auto& t) {return t.i > 4; });
补充说明:测试用的容器定义为
std::vector<Thing> a = { {0, "foo"}, {1, "bar"}, {5, "what"}, {8, "yo"}, {2, ""} }; std::vector<Thing> b;
原因分析
问题核心在于std::make_move_iterator的特性:它返回的迭代器解引用后得到的是右值引用(准确来说,std::move_iterator的operator*会返回std::move(*base),也就是右值)。
你最初使用的Lambda参数auto&是非const左值引用,而C++语法明确禁止非const左值引用绑定到右值上,这直接导致编译报错。
当把Lambda参数改为const auto&后,const左值引用是可以绑定到右值的(这是C++标准特性,用于延长临时对象的生命周期),此时谓词能正常接收std::move_iterator解引用后的右值,编译自然通过。
另外补充:你用std::make_move_iterator来移动元素以避免拷贝开销的思路本身没问题,但要注意谓词参数的类型必须匹配移动迭代器产生的值类别。
内容的提问来源于stack exchange,提问作者IRP_HANDLER
相关产品推荐
相关产品推荐

