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

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

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.

Related Articles