Lazy evaluation¶
Reference¶
-
template<std::invocable Function>
struct lazy¶ Wrapper to lazily evaluate a function (which has no parameters) only when the result is needed, specifically when conversion to the result is requested.
This simple wrapper has surprisingly remarkable benefits:
It simplifies the code that uses the function result only conditionally, for example, when inserting an element into a map only if it doesn’t already exist:
If we require the function to be called only when necessary, the shortest alternative looks like this:auto iter = map.try_emplace(key, ac::lazy{computeValue}).first;
auto iter = map.find(key); if (iter == map.end()) iter = map.emplace(key, computeValue()).first;
Even when the function is always called unconditionally, approach similar to ac::lazy is the only way to avoid an extra move constructor when emplacing a function result into a container. If a move constructor is not defined, copy constructor is called instead.
For example, the first line here results in the extra move constructor of the result, while the second doesn’t:
std::optional optional1{computeValue()}; std::optional optional2{ac::lazy{computeValue}};
For the in-depth explanation, please refer to this article, where the analog is called
with_result_of_t
(I hope you’ll find our naming better): https://quuxplusone.github.io/blog/2018/05/17/super-elider-round-2/Or to the original source of the idea: https://akrzemi1.wordpress.com/2018/05/16/rvalues-redefined/
Note
This is the simplest possible implementation, so it doesn’t perform any result caching for the case where it can be used multiple times.