Search⌘ K
AI Features

Manage Optional Values with std::optional

Explore how to use the std::optional class in C++ to manage values that may or may not be present. Understand its construction, value access, boolean checks, and exception handling to write clearer and safer code when dealing with optional data.

We'll cover the following...

Introduced with C++17, the std::optional class holds an optional value.

Consider the case where we have a function that may or may not return a value. For example, a function that checks if a number is prime but returns the first factor if there is one. This function should return either a value or a bool status. We could create a struct that carries both value and status:

struct factor_t {
bool is_prime;
long factor;
};
factor_t factor(long n) {
factor_t r{};
for(long i = 2; i <= n / 2; ++i) {
if (n % i == 0) {
r.is_prime = false;
r.factor = i;
return r;
}
}
r.is_prime = true;
return r;
}

It's a clumsy solution but it works, and it's not uncommon. It could be made a lot simpler with the optional class:

optional<long> factor(long n) {
for (long i = 2; i <= n / 2; ++i) {
if (n % i == 0) return {i};
}
return {};
}

With optional, we can return a value or a non-value. We can call it, like this:

long a{ 42 };
long b{ 73 };
auto x = factor(a);
auto y = factor(b);
if(x) cout << format("lowest factor of {} is {}\n", a, *x);
else cout << format("{} is prime\n", a);
if(y) cout << format("lowest factor of {} is {}\n", b, *y);
else cout << format("{} is prime\n", b);
...