提问人:glades 提问时间:10/13/2022 更新时间:10/13/2022 访问量:59
将捕获“this”的 lambda 传递给成员初始值设定项列表中的 obj
Pass lambda that captures "this" to obj in member initializer list
问:
我有以下问题:我定义了一个位于另一个类对象中的类。我想在该类中保存一个闭包,以便以后调用它。现在,我应该如何精确地初始化容器类中的对象?我不能在“顶级”使用(例如,当我在直接成员初始化中使用它时。另一方面,当我 decltype() 一个空的 lambda 时,它给了我错误的类型,因为它似乎没有关闭。查看以下代码:task
task
task
this
this
#include <cstdio>
template <typename Callable>
struct task
{
task(Callable fn)
: fn_{fn}
{ }
auto do_stuff() {
fn_();
}
Callable fn_;
};
struct container
{
container()
: task_([this]() -> void { this->print(); })
{ }
auto print() -> void {
printf("Hello World!\n");
}
auto execute() {
task_.do_stuff();
}
task<decltype([](){})> task_;
};
int main()
{
container a;
a.execute();
}
具体而言,这会产生:
<source>:20:12: error: no matching function for call to 'task<container::<lambda()> >::task(container::container()::<lambda()>)'
20 | : task_([this]() -> void { this->print(); })
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如何在直接成员初始化或成员初始值设定项列表中创建闭包?this
答:
2赞
lorro
10/13/2022
#1
如果您希望能够为此分配不同的功能,则需要类型擦除:。此外,您需要在代码中包含 before ctor。task_
std::function<void()> task_;
print()
如果你只需要一个功能,那么基本上是一个成员函数。task_
如果这些都不适合你,你仍然可以在层次结构中引入一个间接层,:containerBase
struct containerBase
{
void print() {
printf("Hello World!\n");
}
auto g() { return [this]() -> void { this->print(); }; }
};
struct container : containerBase
{
container()
: task_(g())
{ }
public:
auto execute() {
task_.do_stuff();
}
task<decltype(std::declval<containerBase>().g())> task_;
};
评论
0赞
glades
10/13/2022
有趣的解决方案,但是第二个示例中的此指针将属于 containerBase 类型。因此,我需要虚拟调用才能访问容器成员函数,这并不理想。难道就没有更直接的解决方案了吗?
0赞
lorro
10/13/2022
@glades 这个想法是,你几乎把所有东西都放在;只有 CTOR(分配 ),调用函数和本身都在 中。containerBase
task_
task_
task_
container
0赞
glades
10/13/2022
我明白这一点,但这实质上意味着每个包含任务对象的容器都会扩展其层次结构以满足其需求。这并不理想。我在想,也许std::bind毕竟不是一个糟糕的解决方案。
评论