What is the use case for not having lazy evaluation of value_or()?
Asked Answered
J

2

6

I was having trouble when using foo.value_or(bar()) in my code, because I wasn't expecting the function bar() to be called when the optional variable foo had a value. I've since found this question that explains that value_or() doesn't use lazy evaluation.

Now I'm left wondering why that is, when lazy evaluation has always been a standard aspect of conditionals in C and C++. I find this very counter-intuitive, and I assume I wasn't the first and won't be the last to be tripped up by it. With the risk of asking to look into the minds of the people who devised std::optional, is there a use case that explains why lazy evaluation would not be a good idea here?

Jelly answered 17/6, 2022 at 4:1 Comment(1)
foo.value_or(/*...*/) is a function call. The argument expression will always be evaluated first, no matter what function is being called. You can see this directly in the syntax, whether it is value_or or any other function doesn't matter. The core language doesn't have any lazily evaluated function arguments, so the library couldn't use them in such a way. The question you linked does explain though how to get a lazy evaluation with the help of a wrapped lambda.Shipboard
K
8

It's not possible to design a function that does lazy evaluation. Function arguments are always evaluated if the function call itself is evaluated. The ONLY things that can short-circuit or evaluate in a lazy way are the built-in && and || and ?: operators.

Other related comments:

A few Standard library functions or features do things that would not be possible to implement in portable code, so they require some compiler "magic". But they try to keep those sorts of things limited.

Even an overloaded operator function operator&& or operator|| still must evaluate its operands, so that's a caution about overloading those: they'll never act just like the built-in versions.

Although the value_or function itself can't put off evaluating its argument, there are some tricks you could use to pass in a lazy placeholder that only does a computation if it's actually needed.

Krasnoyarsk answered 17/6, 2022 at 4:12 Comment(0)
P
1

If you're looking for lazy evaluation, c++23 brings monadic operations - https://en.cppreference.com/w/cpp/utility/optional/or_else

In your case, *foo.or_else(bar)

Potboiler answered 10/5, 2023 at 12:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.