Можно ли оценить std::optional::value_or(expr)
аргумент ленивым образом, так что expr
были рассчитаны только в случае отсутствия значения?
Если нет, то что будет правильной заменой?
#include <optional>
template <typename F>
struct Lazy
{
F f;
operator decltype(f())() const
{
return f();
}
};
template <typename F>
Lazy(F f) -> Lazy<F>;
int main()
{
std::optional<int> o;
int i = o.value_or(Lazy{[]{return 0;}});
}
Вы можете написать свою вспомогательную функцию:
template<typename T, typename F>
T lazy_value_or(const std::optional<T> &opt, F fn) {
if(opt) return opt.value();
return fn();
}
который затем может быть использован как:
T t = lazy_value_or(opt, [] { return expensive_computation();});
Если это значительно меньше печатать, чем делать это явно, решать вам; тем не менее, вы можете сделать его короче с помощью макроса:
#define LAZY_VALUE_OR(opt, expr) \
lazy_value_or((opt), [&] { return (expr);})
использоваться как
T t = LAZY_VALUE_OR(opt, expensive_calculation());
Это наиболее близко к тому, что я думаю, что вы хотите, но может быть осуждено, так как скрывает слишком много вещей.
Сделайте опциональный тип функции.
Затем можно ввести лямбду, которая при вызове вычислит правильное значение в запрошенный момент.
std::optional<std::function<int()>> opt;
int a = 42;
opt = [=] { return a; }
int b = 4;
int c = opt.value_or([=] { return b * 10 + 2;}) ();