Lambda闭包类型构造函数

cpp*_*ast 9 c++ lambda c++11 c++20

cppreference表明,对于拉姆达闭合类型构造不同的规则。

默认构造-直到C ++ 14

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

闭包类型不是默认可构造的。闭包类型的默认构造函数已删除(直到C ++ 14)否(自C ++ 14起)。

默认构造-自C ++ 14起

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

默认构造-自C ++ 20起

如果未指定捕获,则闭包类型具有默认的默认构造函数。否则,它没有默认构造函数(包括捕获默认值,即使它实际上没有捕获任何内容也是如此)。

复制分配运算符-直到C ++ 20

副本分配运算符定义为已删除(并且未声明移动分配运算符)。闭包类型不是CopyAssignable。

复制分配运算符-自C ++ 20起

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

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

Sto*_*ica 9

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

注意我们如何内联定义比较函数?无需创建命名函子(否则可能是个好主意,但我们也不必强求)。无需将声明分为两部分:

// 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!
Run Code Online (Sandbox Code Playgroud)

如此(以及更多)的用法是进行此更改的推动因素。在上面的示例中,匿名仿函数类型将带来命名仿函数类型可以带来的所有好处。其中包括默认初始化和EBO。

  • @ AImx1-注意。lambda表达式是一个新功能,并非其行为的所有方面都一开始就很清楚。随着用户和编译器作者经验的增长,委员会将重新评估以前禁止的功能。如果遵循标准化过程,您将开始注意到它是一个重复出现的主题。如果不确定,最好禁用某些功能。因为将来可能总是启用它:) (3认同)
  • @ AImx1-您需要将“ compare”作为参数传递给构造函数。将其传递给初始化程序列表后:`test({“ BS”,“ CA”,“ PR”,“ US”},作比较);`-这就是在C ++ 20之前需要完成的工作。 (2认同)