重新定义 C++11 中不允许的 lambda,为什么
Redefining lambdas not allowed in C++11, why?
示例:
#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(强调我的):
实现可以定义与下面描述的不同闭包类型,前提是这不会改变程序的可观察行为,除了通过更改:
— 封盖类型的尺寸和/或对齐方式,
— 闭包类型是否易于复制(第 9 条)
— 闭包类型是否为标准布局类(第 9 条),或
— 闭包类型是否为 POD 类(第 9 条)。
据我所知,这就是我遇到的问题。 它正在尝试使用已删除的赋值运算符并失败。我很想知道是否有一个简单的解决方法,更广泛地说,允许通常省略 lambda 的复制可构造性的动机是什么。
您似乎认为这两个 lambda 具有相同的类型,但事实并非如此。每个都创建自己的类型:
#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
.当然,您从编译器获得的错误消息在这方面可能会更清晰一些......
的类型 λ表达式 (这也是闭包对象的类型)是一个唯一的、未命名的非 联合类类型
所以就像你在做以下事情:
struct {} a;
struct {} b;
a = b; // error, type mismatch
如果要将具有相同签名的不同 lambda 分配给同一变量,请使用 std::function
。
std::function<void()> f = []{};
f = []{}; //ok
Lambda 无法重新定义,因为每个 lambda 都是不同的、匿名的、不兼容的类型。仅当您将它们传递给能够推断该类型的模板化函数(如 std::function
ctor 时,才能复制它们。
您无法执行此操作的原因是 lambda 表达式的复制赋值运算符被声明为已删除,请参阅标准的第 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都有一个唯一的类型,但这不是您收到该错误的原因。 此示例表明,即使两个 lambda 具有相同的类型,它仍然无法复制它。 但是,您可以将其复制到新变量。 这就是您的错误消息抱怨缺少operator=
而不是它们的类型不同的原因。 尽管每个 lambda 都有自己的类型,但对您也没有多大帮助。
如果我们可以将一个 lambda 分配给另一个不同类型的 lambda,我们如何将函数体/定义从该 lambda 复制到另一个?如果我们如此固执,那么我们可以使用一些类似成员std::function
类型来复制。但这违背了不支付废话的C++规则......
- 为什么 Clang 不允许"and"作为函数名称?
- 不允许在向量中添加更多元素
- std::带有自定义缓冲区的 iostream 不允许我写入
- Visual Studio 2017 不允许我创建 C++ 专用模板
- 返回时不允许隐式转换
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 为什么 c++ 不允许(自动)强制转换?
- 为什么 c++11 不允许使用自动
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 为什么不允许使用可变长度数组作为向量元素?
- 余数除法和不允许除以零 (c++) 时遇到问题
- 为什么在lambda参数中不允许自动
- 在 QGraphicsScene 中拖动 QPixmap:如何避免 lambda 参数中不允许'auto'
- 为什么在未评估的操作数中不允许使用lambda表达式,而是允许在恒定表达式的未评估部分中
- 重新定义 C++11 中不允许的 lambda,为什么
- ::运算符 new 是不允许在 lambda 表达式中还是编译器错误?(更新!
- MSVC和boost::lambda::绑定错误:T0:不允许使用标准参数
- 为什么不允许使用=和this的lambda(但GCC接受)
- 为什么允许使用通用 lambda,而不允许使用具有模板化方法的嵌套结构?
- G++ 不允许在 lambda 中通过引用对 const 对象进行广义捕获?