ein*_*ica 13 c++ lambda lazy-evaluation c++11 std-future
我刚读过:
并注意到它有点陈旧,大多数答案都与2011年之前的C++有关.这些天我们有语法lambda,甚至可以推断出返回类型,所以懒惰的评估似乎归结为只是传递它们:而不是
auto x = foo();
Run Code Online (Sandbox Code Playgroud)
你执行
auto unevaluted_x = []() { return foo(); };
Run Code Online (Sandbox Code Playgroud)
然后评估您需要的时间/地点:
auto x = unevaluted_x();
Run Code Online (Sandbox Code Playgroud)
似乎没有更多的东西了.但是,其中一个答案建议使用带异步启动的期货.有人可以用C++或更抽象的方式列出为什么/如果期货对懒惰评估工作有重要意义吗?似乎期货很可能会被热切地评估,但简单地说,在另一个线程上,并且可能没有创建它们的任何优先级; 无论如何,它应该依赖于实现,对吧?
另外,还有其他现代C++构造在懒惰评估的背景下有用吗?
ale*_*in0 13
当你写作
auto unevaluted_x = []() { return foo(); };
...
auto x = unevaluted_x();
Run Code Online (Sandbox Code Playgroud)
每当你想要获得价值时(当你打电话时unevaluated_x)它就会被计算出来,浪费了计算资源.因此,为了摆脱这种过度的工作,跟踪lambda是否已经被调用(可能在其他线程中,或者在代码库中的一个非常不同的位置)是一个好主意.为此,我们需要一些围绕lambda的包装器:
template<typename Callable, typename Return>
class memoized_nullary {
public:
memoized_nullary(Callable f) : function(f) {}
Return operator() () {
if (calculated) {
return result;
}
calculated = true;
return result = function();
}
private:
bool calculated = false;
Return result;
Callable function;
};
Run Code Online (Sandbox Code Playgroud)
请注意,此代码只是一个示例,并非线程安全.
但不是重新发明轮子,你可以使用std::shared_future:
auto x = std::async(std::launch::deferred, []() { return foo(); }).share();
Run Code Online (Sandbox Code Playgroud)
这需要更少的代码来编写并支持其他一些功能(例如,检查值是否已经计算,线程安全等).
标准[futures.async,(3.2)]中有以下文字:
如果
launch::deferred在策略,存储DECAY_COPY(std::forward<F>(f))和DECAY_COPY(std::forward<Args>(args))...共享状态中设置.这些副本f和args构成延迟功能.延迟函数的调用的计算结果INVOKE(std::move(g), std::move(xyz)),其中g是的存储值DECAY_COPY(std::forward<F>(f))和xyz处于所存储的副本DECAY_COPY(std::forward<Args>(args))....的任何返回值被存储作为结果处于共享状态.从执行延迟函数传播的任何异常都作为异常结果存储在共享状态中.在功能完成之前,共享状态尚未就绪.在引用此共享状态的异步返回对象上第一次调用非定时等待函数(30.6.4)将调用调用等待函数的线程中的延迟函数.评估INVOKE(std::move(g),std::move(xyz))开始后,该功能不再被视为延期.[注意:如果此策略与其他策略一起指定,例如在使用策略值时launch::async | launch::deferred,实现应该在不再能够有效利用并发性时推迟调用或选择策略. - 尾注]
因此,您可以保证在需要之前不会调用计算.
这里发生了一些事情。
Applicative order评估意味着在将参数传递给函数之前先对其进行评估。
Normal order评估是指在评估参数之前将参数传递给函数。
正常顺序评估的好处是,某些参数永远不会被评估,而某些参数又会被一遍又一遍地评估。
Lazy评估通常是指normal order + memoization。推迟评估,希望根本不需要评估,但是如果需要评估,请记住结果,这样您只需要执行一次即可。重要的是永远不要评估一个术语,记忆是提供此术语的最简单机制。
该promise/future模型是不同再次。这里的想法是,一旦有足够的可用信息,就可能在另一个线程中开始评估。然后,您将尽可能长时间地查看结果,以提高其已可用的机会。
该promise/future模型与惰性评估具有一些有趣的协同作用。该策略是:
当结果由后台线程产生时,可以整齐地引入备忘录。
尽管两者之间具有协同作用,但它们并不是同一概念。