问题描述
我正在实现某种嵌套的平面 for_each(人为的例子):
template <class InputIt,class UnaryFunction>
UnaryFunction flat_nested_for_each_of_sorts(InputIt first,InputIt last,UnaryFunction f) {
while (first != last) {
f = std::for_each(begin(*first),end(*first),std::move(f));
}
return f;
}
我想返回 f
,因为它可能是一个包含一些数据的结构体。但我希望这个函数也能与 lambda 一起使用。例如,
int example1() {
int acc = 0;
std::vector<std::vector<int>> values{{1,2},{3,4}};
auto l = [&acc](int i) {acc += i;};
l = flat_nested_for_each_of_sorts(begin(values),end(values),std::move(l));
return acc;
}
问题是,编译器不喜欢这段代码:
error: use of deleted function 'example1()::<lambda(int)>& example1()::<lambda(int)>::operator=(const example1()::<lambda(int)>&)'
我知道在这种情况下,带有捕获的 lambda 的复制赋值运算符被删除。我不明白的是为什么不调用移动赋值运算符?如果我们要“手动”编写 lambda,一切正常:
struct Lambda_sustitution {
int* acc;
Lambda_sustitution() = default;
Lambda_sustitution(int& acc) : acc{&acc} {}
Lambda_sustitution(const Lambda_sustitution&) = delete;
Lambda_sustitution& operator=(const Lambda_sustitution&) = delete;
Lambda_sustitution(Lambda_sustitution&& s) {
acc = s.acc;
s.acc = nullptr;
}
Lambda_sustitution& operator=(Lambda_sustitution&& s) {
acc = s.acc;
s.acc = nullptr;
return *this;
}
void operator()(int i) {*acc += i; };
};
int example2() {
int acc = 0;
std::vector<std::vector<int>> values{{1,4}};
Lambda_sustitution l{acc};
l = flat_nested_for_each_of_sorts(begin(values),std::move(l));
return *l.acc;
}
编译器资源管理器链接:https://godbolt.org/z/6Tb5WYqxj
解决方法
我不明白的是为什么不调用移动赋值运算符?
因为 lambda 也没有移动赋值运算符(而且它有一个复制构造函数)。
事实上,你不需要做任何重新分配,你可以简单地做:
template <class InputIt,class UnaryFunction>
UnaryFunction flat_nested_for_each_of_sorts(InputIt first,InputIt last,UnaryFunction f) {
while (first != last) {
std::for_each(begin(*first),end(*first),f);
++first;
}
return f;
}
并称之为:
int example1() {
int acc = 0;
std::vector<std::vector<int>> values{{1,2},{3,4}};
auto l = [&acc](int i) {acc += i;};
flat_nested_for_each_of_sorts(begin(values),end(values),l);
return acc;
}