提问人:Victor 提问时间:9/8/2023 最后编辑:Mark RotteveelVictor 更新时间:9/14/2023 访问量:143
为什么我们不能在作为方法默认参数的 lambda 中捕获它?
Why can't we capture this in a lambda that is the default parameter of a method?
问:
我正在尝试捕获用作方法默认参数的 lambda 函数中的指针。this
我的目标是从 lambda 中调用此类的方法,这需要捕获指针。this
但是,以下代码会导致错误:
错误 C3639:作为默认参数一部分的 lambda 只能具有 init-capture
克服此限制的常见解决方案是什么?
#include <functional>
class A{
public:
void B(std::function<void()> a = [this](){}); //error C3639: a lambda that is part of a default argument can only have an init-capture.
};
答:
7赞
Caleth
9/8/2023
#1
您可以改为重载该函数
class A{
public:
void B(std::function<void()> a);
void B(){ B([this](){}); };
};
评论
1赞
463035818_is_not_an_ai
9/8/2023
请注意,这个问题实际上是两个相关但略有不同的问题,“为什么不呢?(标题)和“用什么代替?这完美地回答了后者,但不是第一个。
1赞
Afshin
9/8/2023
#2
嗯,我认为你不能用捕获列表作为默认参数传递lamda是有道理的。它创建了不应该存在的依赖项。
但是你也许可以通过这样的事情来实现你想做的事情:
#include <functional>
class A{
public:
void B(std::function<void()> a) {
if (!a) {
// do default. You have access to 'this' here.
return;
}
// do non-default with 'a' argument
}
};
评论
0赞
Marek R
9/8/2023
在代码中添加不必要的分支对性能不利。
10赞
Jan Schultke
9/8/2023
#3
线路的问题......
void B(std::function<void()> a = [this](){});
...lambda 表达式是函数参数的默认参数。
函数参数是在调用站点创建的,此时无法捕获任何参数。
C++ 标准禁止默认参数:this
this
[ 注意:该关键字可能不会出现在成员函数的默认参数中;请参阅 [expr.prim.this]。 [ 示例:
this
class A { void f(A* p = this) { } // error };
— 结束示例 ] — 结束语 ]
这只是一个注释,但对于 lambda 也是如此,因为:
默认参数中出现的 lambda 表达式不得隐式或显式捕获任何实体。
- [expr.prim.lambda.capture] 第 9 页
为什么不能在默认参数中使用的理由this
函数调用的处理方式如下:
- 初始化所有函数参数(可能使用默认参数)
- 将控制权移交给功能(现在可用)
this
- 执行函数体并创建返回对象
- 将控制权转回呼叫者(不再可用)
this
- 销毁函数参数
注意:步骤4的顺序。和 5.是实现定义的
您尝试在步骤 1 中访问,这还为时过早,更不用说默认参数中的 lambda 通常不能有捕获。this
溶液
添加第二个重载,例如
void B() { B( [this] {} ); }
可以解决问题,但您最终会得到两个函数而不是一个。
评论
this
this