I can't get an optional with (cond) ? value : nullopt ... what should I write instead?

Suppose I'm implementing the function returning an std::optional<T>
. In that function, I compute some condition, and then want to return either a value, or a nullopt
. I can do it like so:
std::optional<T> foo()
{
auto cond = compute_condition();
if (cond) return compute_value();
return std::nullopt;
}
and this works fine. But - I want a one-liner. I would have liked to be able to write:
std::optional<T> foo()
{
return (compute_condition()) ? compute_value() : std::nullopt;
}
but this fails to compile (GodBolt.org):
error: operands to '?:' have different types 'T' and 'const std::nullopt_t'
is there something in the standard I can use?
Note: This question is related, but less general.
Answer
I don't think there's anything in the standard catering to your use-case. Here is a flawed, less efficient, but mostly decent-looking, and non-idiomatic, solution:
Use following utility function template:
template <typename T>
std::optional<T> value_if(bool cond, T&& value)
{
if (cond) return value;
return std::nullopt;
}
and then write:
std::optional<T> foo()
{
return value_if<int>(compute_condition(), compute_value());
}
... but - this has the drawback of always computing the value, even if the condition does not hold.
Q: Why are you specifying T
in the invocation of value_if()
?
A: That's because the result of compute_value()
may need to undergo implicit conversion to fit the optional's type. If I just let T
be deduced, I might get the wrong optional.
Enjoyed this question?
Check out more content on our blog or follow us on social media.
Browse more questions