在类构造函数体内初始化 lambda 函数

MaP*_*aPo 2 c++ lambda constructor member-initialization

我可以毫无问题地编译以下代码(使用 gcc 11.1.0):

\n
#include <iostream>\n\ntemplate <typename Func>\nclass K {\n    Func f;\npublic:\n    K(Func _f): f{_f} {};\n    void do_thing(int x) {f(x);};\n};\n\nint main()\n{\n    auto f = [](int x) {std::cout << x << std::endl;};\n    K kl{f};\n    kl.do_thing(5);\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但是我想在类的构造函数中执行一些检查K(例如某些函数std::is_convertible_v内部的一些bool检查),所以我尝试将代码修改为

\n
#include <iostream>\n\ntemplate <typename Func>\nclass K {\n    Func f;\n    \npublic:\n    K(Func _f) {\n    ...\n    f = _f;};\n    void do_thing(int x) {f(x);};\n};\n\nint main()\n{\n    auto f = [](int x) {std::cout << x << std::endl;};\n    K kl{f};\n    kl.do_thing(5);\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但这给了我一些错误消息

\n
error: use of deleted function \xe2\x80\x98main()::<lambda(int)>::<lambda>()\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n

进而

\n
note: a lambda closure type has a deleted default constructor\n
Run Code Online (Sandbox Code Playgroud)\n

这让我很困惑,因为我无法理解前一段代码如何能够编译,因为 lambda 函数没有默认构造函数。

\n

问题\n如何在构造函数体内设置
我的内容?(这只是一个 MWE,在我的例子中,该类有点复杂,我之前提到的检查是有意义的。)f

\n

son*_*yao 5

如何初始化f构造函数体内的内容?

你不能。f = _f;构造函数体内是赋值,但不是初始化。所以f会先默认初始化,然后进入构造函数体(进行赋值)。

你可以改用std::function;它可以是默认初始化的,然后您可以在构造函数体中分配它。


顺便说一句:由于 C++20,您的代码可以很好地编译,即使它可能无法按您的预期工作(取决于部分...)。对于lambda来说,

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