gpt4 book ai didi

c++11 - 是否可以覆盖 C++11 lambda/closure 析构函数?

转载 作者:行者123 更新时间:2023-12-01 00:53:30 25 4
gpt4 key购买 nike

我正在使用 C++11 lambda/closure 功能,尝试编写一个半协程(生成器)函数。

以下代码是我的实验。它们按预期工作(GCC 4.9/Linux)。

我已经阅读了几篇介绍 C++ lambda/closure 的在线文章,现在我将 lambda 函数理解为仿函数或函数对象。

我的问题是:我可以将闭包对象的析构函数代码放在哪里?如何覆盖默认析构函数?

我需要这个函数,因为当我调用构造和返回闭包对象(代表协程)的函数时,某些协程可能会请求某些系统资源。但是如果调用者函数决定取消/终止操作,应该有一种机制来通知协程对象采取一些行动。放置代码的理想位置是在析构函数中,但我找不到如何。

有什么建议么?

#include <iostream>
#include <functional>
#include <time.h>

#define CONCAT01(a, b) a##b
#define CONCAT02(a, b) CONCAT01(a, b)
#define YIELD() \
do { \
CONCAT02(ENTRY, __LINE__): \
if (EP == && CONCAT02(ENTRY, __LINE__)) \
EP = 0; \
else \
{ \
EP = && CONCAT02(ENTRY, __LINE__); \
return true; \
} \
} while (0)

using namespace std;

typedef std::function<bool(void)> coroutine;

coroutine add(int a, int b, int * ret)
{
timespec start;
clock_gettime(CLOCK_REALTIME, &start);

return [=]() mutable -> bool
{
timespec now;
while(1) {
clock_gettime(CLOCK_REALTIME, &now);
if (now.tv_sec - start.tv_sec > 1)
break;

return true;
}
* ret = a + b;
cout << "add " << a << " " << b << " equals: " << a + b << endl;
return false;
};
}

coroutine sum(int a, int b, int c, int * ret)
{
void* EP = 0;
coroutine co = 0;
int tmp = 0;

return [=] () mutable -> bool
{
if (EP) goto *EP;

co = add(a, b, &tmp);
while(co())
YIELD();

co = add(tmp, c, ret);
while(co())
YIELD();

return false;
};
}

int main()
{
int ret;
coroutine c = sum(1, 2, 4, &ret);
while (c())
{
sleep(1);
cout << "wakeup" << endl;
}

cout << "final: " << ret << endl;

return 0;
}

最佳答案

这是一个带有任务和销毁任务的对象:

template<class F, class D>
struct coroutine {
F f;
D d;
template<class...Args>
std::result_of_t<F&(Args...)>
operator()(Args&&...args){
return f(std::forward<Args>(args)...);
}
~coroutine() {
d();
}
};

它的工厂功能:
template<class F, class D>
coroutine< std::decay_t<F>, std::decay_t<D> >
make_coroutine( F&& f, D&& d ) {
return {std::forward<F>(f), std::forward<D>(d)};
}

一些辅助宏:
#define COROUTINE_STATE ED=(void*)0
#define START_COROUTINE if (ED) goto *ED
#define FINISH_COROUTINE return false

auto add(int a, int b, int * ret) {
timespec start;
clock_gettime(CLOCK_REALTIME, &start);

return make_coroutine([=]() mutable
{
timespec now;
while(true) {
clock_gettime(CLOCK_REALTIME, &now);
if (now.tv_sec - start.tv_sec > 1)
break;

return true;
}
*ret = a + b;
cout << "add " << a << " " << b << " equals: " << a + b << endl;
return false;
},
[]{
cout << "adder destroyed\n";
});
}
auto sum(int a, int b, int c, int * ret)
{
std::function<bool()> co;
int tmp = 0;

return make_coroutine([=,COROUTINE_STATE] () mutable
{
START_COROUTINE;
co = add(a, b, &tmp);
while(co())
YIELD();

co = add(tmp, c, ret);
while(co())
YIELD();

FINISH_COROUTINE;
},
[]{
std::cout << "winter is coming\n";
}
);
}

请注意,在此设计中,析构函数无法访问“主体”中的任何状态更改,例如 ED .

你捕获 COROUTINE_STATE获取 ED指针。那你 START_COROUTINE;做自动分支, YIELD()插入一个跳跃点, FINISH_COROUTINE;结束协程。

这里缺少共享状态是一个严重的问题。 co body 可以访问的完全不同于 co如果驱逐舰执行 =,它将可以访问.

我们可以通过在你的协程中添加一个在 FINISH_COROUTINE; 之后发生的新状态来解决这个问题。或类似的。注入(inject)访问的能力是很棘手的——一种方法是移动 ED从 lambda 捕获本身:
template<class F>
struct coroutine {
void** ED = nullptr;
F f;
template<class...Args>
std::result_of_t< F&(void**,Args...) >
operator()(Args&&...args){
return f(ED, std::forward<Args>(args)...);
}
~coroutine() {
void* end = 0;
f(&end);
}
};
template<class F>
coroutine<std::decay_t<F>>
make_coroutine(F&& f){return {std::forward<F>{f}};}
#define START_COROUTINE [=](void** ED)mutable{\
if (ED){if (*ED)goto *ED;\
else goto Cleanup;}
#define END_COROUTINE_BODY return false; Cleanup:
#define END_COROUTINE_CLEANUP }
#define END_COROUTINE END_COROUTINE_BODY; END_COROUTINE_CLEANUP

auto sum(int a, int b, int c, int * ret)
{
std::function<bool()> co = 0;
int tmp = 0;

return
START_COROUTINE
co = add(a, b, &tmp);
while(co())
YIELD();

co = add(tmp, c, ret);
while(co())
YIELD();
END_COROUTINE_BODY
std::cout << "winter is coming\n";
END_COROUTINE_CLEANUP;
}

或类似的东西。我们通过 ED明确地,如果它指向一个 nullptr,我们认为它的意思是“跳转到清理代码”。这会将清理代码与主体放在同一范围内。

我现在看到你的类型删除到 std::function可能有用。请注意,这种类型删除需要内存分配开销(实际上),这是不幸的,并且每次调用都需要虚拟函数开销。

可悲的是,我重用了你的 coroutine typename 在我弄清楚之前,所以开始使用 std::function<bool()直接地。我很抱歉。

关于c++11 - 是否可以覆盖 C++11 lambda/closure 析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29774559/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com