How to express optional values in C++
5 min read
The problem
Implement a function that accepts a player ID, an activity ID and returns the player’s score for that activity. The returned score depends on the activity ID and it is not guaranteed that the player has a score for the given activity.
The bad solution
One possible solution is to use -1 to represent the absence of a score.
This approach is one of the oldest conventions in programming. You will see it in C legacy code, in UNIX system calls and other places.
However, in modern C++, using -1 is an anti-pattern. It assumes that negative numbers will never be valid data in your domain or it may lead to accidental arithmetical errors.
The signature of the function does not express the fact that the return value may be invalid, which might be confusing to the reader. All of these can lead to subtle bugs that are hard to track down.
The good solution
C++17 introduced the std::optional type, which can be used to express the fact (as the name implies) that a value may be optional.
Notice that the signature of the function now expresses the fact that the return value may be optional.
The reader doesn’t have to search through the function body to understand that the return value may be missing or to understand what the special value -1 means.
Now it is clear that the function may or may not return a value.
The caller can verify if the returned optional value is valid by using the has_value() method.
You can retrieve the value by using value() or value_or(), in which you can specify a default value.
C++23 introduced monadic operations on std::optional that allow you to chain operations safely without writing if-else ladders.
These operations are transform, and_then and or_else.
Complete example
You can try the below example in C++ Shell.