如何管理自引用跨谱lambda? [英] How does one manage a self-referring cross-scope lambda?

查看:59
本文介绍了如何管理自引用跨谱lambda?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个想在计时器结束时调用的功能.我已将该功能放在lambda函数中.此外,在该函数中,我可能希望设置另一个计时器,以便在以后的另一个场合调用相同的lambda.

Assume that I have a functionality which I want to call whenever a timer finishes. I have put that piece of functionality in a lambda function. Furthermore, in that function, I may wish to set another timer to call that same lambda on another, later occasion.

void doSetupThingsInSomeDecoupledCodeOrWhatever() {
    std::function<void(float)> semiRecursiveFunc;
    semiRecursiveFunc = [&semiRecursiveFunc](float deltaT){
        if (whatever()) {
            // Do something...
        }
        else {
            // Do something else, then:
            float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
            // Gives the timer a duration to wait, and a function to run at the end of it.
            getTimerSystem().setNewTimer(durationMS, semiRecursiveFunc);
        }
    };

    float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
    // Gives the timer a duration to wait, and a function to run at the end of it.
    getTimerSystem().setNewTimer(durationMS, fooLambda);
}

现在,显然这是行不通的,因为 semiRecursiveFunc 已绑定到 doSetupThingsInSomeDecoupledCodeOrWhatever 的范围,并且当计时器系统尝试运行该功能时,该功能将不再有效存在,一切都会分解成一个壮观的火焰球.

Now, clearly this won't work, because semiRecursiveFunc is tied to the scope of doSetupThingsInSomeDecoupledCodeOrWhatever, and when the timer system tries to run it the function will no longer exist and everything will disintegrate into a spectacular ball of flame.

管理此问题的最佳方法是什么?我无法将 semiRecursiveFunc 存储在指针中,因为据我所知,不能这样声明lambda.对于这种持久性lambda用例,是否有一些通用工具?什么是最丑陋的方法,而周围的基础结构却最少?是否有最佳实践可循,我错过了一些相关工具?任何建议都将不胜感激.

What's the best way to manage this? I can't store semiRecursiveFunc in a pointer because one can't declare lambdas like that, as far as I can tell. Is there some common tool for this sort of persistent-lambda use-case? What's the least ugly approach, with minimum surrounding infrastructure? Is there a best-practice to follow, some relevant tool I've missed? Any suggestions or recommendations would be much appreciated.

推荐答案

您正在寻找的是一个y-combinator ,有时称为

What you're looking for is a y-combinator, sometimes called a fixed-point combinator.

无论哪种方式,您都不必像这样完全使用 std :: function (这会增加不必要的开销),而是这样编写回调:

Either way, instead of using std::function at all (which adds needless overhead), you would write your callback like this:

auto semiRecursiveCallback = combinator([](auto self, float deltaT){
    if (whatever()) {
        // Do something...
    }
    else {
        // Do something else, then:
        float durationMS = getRNGSystem().getUniformFloat(1000.0f, 5000.0f)
        // Gives the timer a duration to wait, and a function to run at the end of it.
        // NB: we pass 'self' as the argument
        getTimerSystem().setNewTimer(durationMS, self);
    }
});

其中 combinator 是我的链接答案的 y_combinator 实现,或者来自优秀的Boost.HOF库的 boost :: hof :: fix

Where combinator is either the y_combinator implementation of my linked answer or boost::hof::fix from the excellent Boost.HOF library.

组合器确保对象本身可以访问自身,因此您可以执行递归操作.在上面的代码中,您实际上是在传递自己的副本,但这很好:值语义很酷.

The combinator ensures that the object itself has access to itself, so you can do recursive things. In the above code, you're actually getting passed a copy of yourself, but that's fine: value semantics are cool like that.

这篇关于如何管理自引用跨谱lambda?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆