Lambda 闭包类型构造函数
Lambda closure type constructors
cppreference表明 lambda 闭包类型构造函数有不同的规则。
默认构造 - 直到 C++14
ClosureType() = delete; (until C++14)
Closure types are not Default Constructible. Closure types have a
deleted (until C++14)no (since C++14) default constructor.
默认构造 - 自 C++14
Closure types have no (since C++14) default constructor.
默认构造 - 自 C++20
If no captures are specified, the closure type has a defaulted default
constructor. Otherwise, it has no default constructor (this includes
the case when there is a capture-default, even if it does not actually
capture anything).
复制赋值运算符 - 直到 C++20
The copy assignment operator is defined as deleted (and the move
assignment operator is not declared). Closure types are not
CopyAssignable.
复制赋值运算符 - C++20 起
If no captures are specified, the closure type has a defaulted copy
assignment operator and a defaulted move assignment operator.
Otherwise, it has a deleted copy assignment operator (this includes
the case when there is a capture-default, even if it does not actually
capture anything).
这种规则变化背后的原因是什么?标准委员会是否发现了 lambda 封闭式结构标准中的一些缺点?如果有,那些缺点是什么?
有个缺点。我们不能像人们希望的那样 "on the fly" 使用 lambda。 C++20(加上允许在未计算的上下文中使用 lambda)使此代码有效:
struct foo {
int x, y;
};
std::map<foo, decltype([](foo const& a, foo const& b) { return a.x < a.y; })> m;
请注意我们是如何定义内联比较函数的?无需创建命名仿函数(否则可能是个好主意,但我们也不是 forced)。而且没有必要将声明一分为二:
// C++17
auto cmp = [](foo const& a, foo const& b) { return a.x < a.y; };
std::map<foo, decltype(cmp)> m(cmp); // And also need to pass and hold it!
像这样(以及更多)的用法是进行此更改的推动因素。在上面的示例中,匿名仿函数类型将带来命名仿函数类型可以带来的所有好处。其中默认初始化和EBO。
cppreference表明 lambda 闭包类型构造函数有不同的规则。
默认构造 - 直到 C++14
ClosureType() = delete; (until C++14)
Closure types are not Default Constructible. Closure types have a deleted (until C++14)no (since C++14) default constructor.
默认构造 - 自 C++14
Closure types have no (since C++14) default constructor.
默认构造 - 自 C++20
If no captures are specified, the closure type has a defaulted default constructor. Otherwise, it has no default constructor (this includes the case when there is a capture-default, even if it does not actually capture anything).
复制赋值运算符 - 直到 C++20
The copy assignment operator is defined as deleted (and the move assignment operator is not declared). Closure types are not CopyAssignable.
复制赋值运算符 - C++20 起
If no captures are specified, the closure type has a defaulted copy assignment operator and a defaulted move assignment operator. Otherwise, it has a deleted copy assignment operator (this includes the case when there is a capture-default, even if it does not actually capture anything).
这种规则变化背后的原因是什么?标准委员会是否发现了 lambda 封闭式结构标准中的一些缺点?如果有,那些缺点是什么?
有个缺点。我们不能像人们希望的那样 "on the fly" 使用 lambda。 C++20(加上允许在未计算的上下文中使用 lambda)使此代码有效:
struct foo {
int x, y;
};
std::map<foo, decltype([](foo const& a, foo const& b) { return a.x < a.y; })> m;
请注意我们是如何定义内联比较函数的?无需创建命名仿函数(否则可能是个好主意,但我们也不是 forced)。而且没有必要将声明一分为二:
// C++17
auto cmp = [](foo const& a, foo const& b) { return a.x < a.y; };
std::map<foo, decltype(cmp)> m(cmp); // And also need to pass and hold it!
像这样(以及更多)的用法是进行此更改的推动因素。在上面的示例中,匿名仿函数类型将带来命名仿函数类型可以带来的所有好处。其中默认初始化和EBO。