c++ - 如何管理一个自引用的跨范围 lambda?
问题描述
假设我有一个功能,我想在计时器完成时调用它。我已将该功能放入 lambda 函数中。此外,在该函数中,我可能希望设置另一个计时器以在以后的另一个场合调用相同的 lambda。
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
,并且当计时器系统尝试运行它时,该功能将不再存在,并且一切都将分解为壮观的火焰球。
管理此问题的最佳方法是什么?据我所知,我不能存储semiRecursiveFunc
在指针中,因为不能像那样声明 lambda。对于这种持久性 lambda 用例,是否有一些常用工具?什么是最丑陋的方法,周围的基础设施最少?是否有最佳实践可以遵循,我错过了一些相关工具?任何建议或建议将不胜感激。
解决方案
您正在寻找的是y-combinator,有时称为定点组合器。
无论哪种方式,都不要使用std::function
(这会增加不必要的开销),而是像这样编写回调:
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);
}
});
我的链接答案或优秀的 Boost.HOF 库combinator
的实现在哪里。y_combinator
boost::hof::fix
组合器确保对象本身可以访问自己,因此您可以执行递归操作。在上面的代码中,你实际上得到了一个自己的副本,但这很好:值语义就像那样很酷。
推荐阅读
- c# - DBContext 初始化抛出 SocketException
- javascript - 鼠标流触发onbeforeunload不起作用
- ar.js - 如何将自定义图标添加到地名 AR.JS
- g++ - 在 .cpp 文件中声明了一个全局变量,但我不能在另一个 .hpp 文件中使用它
- wpf - 是否可以在 WPF 中使用 ReactiveUI 绑定仅通过 INotifyDataErrorInfo 验证用户输入?
- binding - std::is_same 在使用 C++17 结构化绑定时给出了奇怪的结果
- docker - 码头工人撰写错误:yaml.parser.ParserError:预期'
',但发现' ' - javascript - Typescript 中的不同类型
- javascript - 使用 Javascript 和 React 检测 DIV 中的滚动位置
- r - 如何通过 2 个步骤在闪亮中使用用户选择的变量