std :: optional :: value_or() - оценка ленивого аргумента

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

Если нет, то что будет подходящей заменой?

Ответ 1

#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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

int b = 4;

int c = opt.value_or([=] { return b * 10 + 2;}) ();