std :: option :: value_or () — ленивая оценка аргумента

Можно ли оценить std::optional::value_or(expr) аргумент ленивым образом, так что expr были рассчитаны только в случае отсутствия значения?

Если нет, то что будет правильной заменой?

15

Решение

#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;}});
}

DEMO

22

Другие решения

Вы можете написать свою вспомогательную функцию:

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());

Это наиболее близко к тому, что я думаю, что вы хотите, но может быть осуждено, так как скрывает слишком много вещей.

9

Сделайте опциональный тип функции.

Затем можно ввести лямбду, которая при вызове вычислит правильное значение в запрошенный момент.

std::optional<std::function<int()>> opt;

int a = 42;
opt = [=] { return a; }

int b = 4;

int c = opt.value_or([=] { return b * 10 + 2;}) ();
0
По вопросам рекламы [email protected]