When a program communicates with the outside world and relies on values it gets from there, then all kinds of failures can happen.
This means that whenever we write a function that ought to return a value, but that can also possibly fail, then this must be reflected in some change of the function interface. We have several possibilities. Let's see how we can design the interface of a function that will return a string, but that could also fail:
- Use a success-indicating return value and output parameters: bool get_string(string&);
- Return a pointer (or a smart pointer) that can be set to nullptr if there is a failure: string* get_string();
- Throw an exception in the case of failure and leave the function signature very simple: string get_string();
All these approaches have different advantages and disadvantages. Since C++17, there is a new type that can be used to solve such a problem in a different way: std::optional. The notion of an optional value comes from purely functional programming languages (where they are sometimes called Maybe types) and can lead to very elegant code.
We can wrap optional around our own types in order to signal empty or erroneous values. In this recipe, we will learn how to do that.