C/C++ Arena

Step 3 of 7

optional for "maybe"

When the only possible failure is "there's no result", std::optional says it right in the return type: the function returns either a value or nothing. There's no separate out-parameter, and the empty case is part of the type, so callers see it and check it (reading an empty optional with * is still a bug).

#include <iostream>
#include <map>
#include <optional>
#include <string>

std::optional<std::string> phone_of(const std::map<std::string, std::string>& book, const std::string& name) {
    auto it = book.find(name);
    if (it == book.end()) return std::nullopt;
    return it->second;
}

int main() {
    std::map<std::string, std::string> book = {{"ada", "555-0101"}, {"alan", "555-0199"}};
    for (const char* who : {"alan", "grace"}) {
        auto p = phone_of(book, who);
        std::cout << who << ": " << p.value_or("unknown") << "\n";
    }
}
alan: 555-0199
grace: unknown

Compared with a status code

Question status code std::optional
Result delivered out-parameter return value
Caller forgets to check wrong data used silently the missing case is spelled out in the type, so it's hard to forget
Says why it failed no no

Why not return -1?

For an index, -1 is the classic "not found" value, but the return type std::size_t is unsigned, so -1 would become a huge number that looks like a valid index. std::optional<std::size_t> avoids the whole problem.

For your search: loop over the indexes, return i on a match, and return std::nullopt after the loop.

Your turn: write std::optional<std::size_t> find_player(const std::vector<std::string>& team, const std::string& name) returning the index or std::nullopt.

Previous: Status codes Next: A Result type