Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::optional::value_or() - lazy argument evaluation

Is it possible to evaluate std::optional::value_or(expr) argument in a lazy way, so the expr were calculated only in the case of having no value?

If not, what would be a proper replacement?

like image 996
vtrz Avatar asked Aug 05 '18 15:08

vtrz


2 Answers

#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

like image 85
Piotr Skotnicki Avatar answered Oct 21 '22 21:10

Piotr Skotnicki


You may write your helper function:

template<typename T, typename F>
T lazy_value_or(const std::optional<T> &opt, F fn) {
    if(opt) return opt.value();
    return fn();
}

which can then be used as:

T t = lazy_value_or(opt, [] { return expensive_computation();});

If that's significantly less typing than doing it explicitly that's up to you to judge; still, you can make it shorter with a macro:

#define LAZY_VALUE_OR(opt, expr) \
    lazy_value_or((opt), [&] { return (expr);})

to be used as

T t = LAZY_VALUE_OR(opt, expensive_calculation());

This is closest to what I think you want, but may be frowned upon as it hides a bit too much stuff.

like image 11
Matteo Italia Avatar answered Oct 21 '22 20:10

Matteo Italia