Skip to content
C++ Basics: Represent Missing Results with std::optional

C++ Basics: Represent Missing Results with std::optional

November 2, 2026

A stock count of zero is a valid answer. An unknown product is different: the lookup has no answer. Return std::optional<int> to keep those cases separate.

Prepare a scratch directory

Tested on Linux x86_64 with GCC 14.2.0. Install G++ and its C++ standard-library development files, and make g++ available on PATH. You also need Bash, a text editor, and mktemp, rm, and rmdir. No third-party C++ library is required.

Keep the same terminal open. Stop if setup fails, before saving the source:

start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1

Run the example

Save this as optional-explicit-absence-demo.cpp:

#include <iostream>
#include <optional>
#include <string_view>

std::optional<int> lookup_stock(std::string_view product)
{
    if (product == "pencil") {
        return 0;
    }
    if (product == "notebook") {
        return 12;
    }
    return std::nullopt;
}

int main()
{
    for (const auto product : {"pencil", "notebook", "eraser"}) {
        const auto stock = lookup_stock(product);
        std::cout << product << ": ";
        if (stock) {
            std::cout << *stock << '\n';
        } else {
            std::cout << "unknown\n";
        }
    }
}

Compile and run it. The second command runs only after compilation succeeds:

g++ -std=c++20 -Wall -Wextra -Werror -pedantic optional-explicit-absence-demo.cpp -o optional-explicit-absence-demo &&
./optional-explicit-absence-demo

Observed output:

pencil: 0
notebook: 12
eraser: unknown

Read the result

The pencil result contains zero, so its optional is engaged and the branch prints 0. The eraser result is disengaged, so the program never dereferences it. Checking an optional tests whether a value exists, not whether the contained integer is nonzero.

Apply it carefully

Dereference only after checking engagement. An optional represents absence, but does not explain why a lookup failed. Use a richer result type when callers need distinct failure reasons. value_or supplies a fallback value, which may intentionally erase the difference between missing data and a real value. This example needs only the C++17 optional interface, compiled in C++20 mode.

The C++ working draft specifies the relevant library behavior. The example uses interfaces available in C++20; the current working draft also describes later additions.

Clean up

Remove only the source and executable created here, then return to the starting directory:

rm -- optional-explicit-absence-demo.cpp optional-explicit-absence-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directory

If the directory is not empty, inspect the remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on