Lambda闭包类型构造函数

时间:2019-04-16 12:28:43

标签: c++ c++11 lambda c++20

cppreference表明,lambda闭包类型构造函数有不同的规则。

默认构造-直到C ++ 14

  

ClosureType()=删除; (直到C ++ 14)

     

关闭类型不是默认可构造的。闭合类型有一个   删除(直到C ++ 14)没有(自C ++ 14起)默认构造函数。

默认构造-自C ++ 14起

  

闭包类型没有(自C ++ 14起)默认构造函数。

默认构造-自C ++ 20起

  

如果未指定捕获,则关闭类型具有默认的默认值   构造函数。否则,它没有默认的构造函数(包括   存在捕获默认值的情况,即使实际上没有   捕获任何东西)。

副本分配运算符-直到C ++ 20

  

将副本分配运算符定义为已删除(以及移动   未声明赋值运算符)。关闭类型不是   CopyAssignable。

副本分配运算符-自C ++ 20起

  

如果未指定捕获,则关闭类型具有默认副本   赋值运算符和默认的移动赋值运算符。   否则,它具有已删除的副本分配运算符(包括   存在捕获默认值的情况,即使实际上没有   捕获任何东西)。

此规则更改背后的原因是什么?标准委员会是否确定了lambda封闭式构造标准的不足之处?如果是这样,那些短处是什么?

1 个答案:

答案 0 :(得分:8)

有一个缺点。我们不能像人们想要的那样“随时随地”使用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。