我有这个函数,它使用 std::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; });
但它甚至没有编译,现在如果使用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::partition
使用移出的范围进行呼叫:Object&&
这意味着您拥有的 lambda 将通过某些or来调用const Object&&
。const auto&
在任何一种情况下都可以绑定到它。const auto&
是通用的,因为它可以绑定到任何值类别(左值、x值、纯右值)。例如:
这段代码编译为
这意味着没有
S
调用 的构造函数,const&
只是绑定到任何东西。由于您正在使用std::move_iterator
(这对于比较的目的毫无意义),因此您的情况是r1
orr3
。auto&
并不是那么强大:非常量左值引用不能绑定到常量x值。这r3
就是您遇到的情况。- [dcl.init.ref] p5.2
解决方案
const auto&
只需在您的 lambda 中接受即可。它更正确,因为您只是比较元素而不修改它们。