Is there a less verbose idiom for unpacking an optional in C++?

Viewed 167

In the project I am currently working on I find myself writing a lot of code that looks like the following, where, get_optional_foo is returning an std::optional:

//...
auto maybe_foo = get_optional_foo(quux, ...)
if (!maybe_foo.has_value())
    return {};
auto foo = maybe_foo.value()
//...
// continue on, doing things with foo...

I want to bail out of the function if I get a null option; otherwise, I want to assign a non-optional variable to the value. I've started using the convention of naming the optional with a maybe_ prefix but am wondering if there is some way of doing this such that I don't need to use a temporary for the optional at all? This variable is only ever going to be used to check for a null option and dereference if there is a value.

3 Answers

You don't need an intermediate object. std::optional supports a pointer interface to access it so you can just use it like:

//...
auto foo = get_optional_foo(quux, ...)
if (!foo)
    return {};
//...
foo->some_member;
(*foo).some_member;

Shortest I can think of:

auto maybe_foo = get_optional_foo(quux, ...)
if (!maybe_foo) return {};

auto &foo = *maybe_foo; // alternatively, use `*maybe_foo` below

If you have multiple optionals in the function and it's very unlikely they'll be empty you can wrap the whole thing with a try - catch.

try {
  auto &foo = get_optional_foo(quux, ...).value();
  auto &bar = get_optional_bar(...).value();
  ...
} catch (std::bad_optional_access &e) {
  return {};
}

Slightly different than what you are asking, but consider:

  if (auto foo = get_optional_foo(1)) {
    // ...
    return foo->x;
  } else {
    return {};
  }

This places the main body of the function in an if() block, which may be more readable.

Related