重新定义C ++ 11中不允许的lambdas,为什么?

例:

#include <functional> int main() { auto test = []{}; test = []{}; return 0; } 

这会在gcc 4.7.2中发出以下错误消息:

 test.cpp: In function 'int main()': test.cpp:5:13: error: no match for 'operator=' in 'test = <lambda closure object>main()::<lambda()>{}' test.cpp:5:13: note: candidate is: test.cpp:4:16: note: main()::<lambda()>& main()::<lambda()>::operator=(const main()::<lambda()>&) <deleted> test.cpp:4:16: note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const main()::<lambda()>&' 

从标准5.1.2.3(重点矿):

一个实现可以定义封闭types与下面描述的不同,只要这不改变程序的可观察行为,而不是改变:

– 封闭types的大小和/或alignment,

– 封闭types是否可以复制 (第9条)

– 封闭types是标准布局类(第9章)还是

– 封闭types是否是POD类(第9章)。

据我所知,这是我所面对的。 它试图使用已删除的赋值运算符并失败。 我很想知道是否有一个简单的解决方法,更广泛地说,允许复制构造性对于lambda一般来说是省略的动机。

你似乎认为这两个lambda具有相同的types,但这不是事实。 每一个创build自己的types:

 #include <functional> #include <type_traits> #include <iostream> int main() { auto test = []{}; auto test2 = []{}; std::cout << std::is_same< decltype( test ), decltype( test2 ) >::value << std::endl; return 0; } 

将打印0 。 当然,从编译器中得到的错误信息在这方面可能会更清晰一些。

lambdaexpression式(也是闭包对象的types)的types是唯一的 ,未命名的非联合类types

所以这就像你在做以下事情:

 struct {} a; struct {} b; a = b; // error, type mismatch 

如果要将具有相同签名的不同lambdaexpression式分配给相同variables,请使用std::function

 std::function<void()> f = []{}; f = []{}; //ok 

Lambda不能被重新定义,因为每个lambda都是不同的,匿名的,不兼容的types。 只有当你将它们传递给模板函数(比如std::function ctor)才能被复制时,它们才能被复制。

如果我们可以将一个lambda分配给另一个不同types的lambda,那么我们如何将这个lambda的函数体/定义复制到另一个? 如果我们如此固执,那么我们可以使用一些std::function liketypes的成员来进行复制。 但是,这将违反奥C ++规则不支付等等等等…

你不能这样做的原因是因为lambdaexpression式的复制赋值运算符被声明为删除,参见标准的第5.1.2 / 20节。 为了更清楚(对于不寻常的清晰定义),请参阅此代码示例

 template<class T> void f(T x1) { T x2 = x1; // copy constructor exists, this operation will succeed. x2 = x1; // assignment operator, deleted and will cause an error } int main() { f([]{}); return 0; } 

其他答案指出,每个lambda都有一个唯一的types,但这不是你得到这个错误的原因。 这个例子表明,即使两个lambda具有相同的types,它仍然不能复制它。 但是你可以将它复制到一个新的variables。 这就是你的错误信息是抱怨缺lessoperator=而不是他们的types不同。 虽然每个lambda拥有它自己的types也不帮你。