Let's say we have a class which represents a human head. The head can have a hat of some sort, or no hat at all. By using std::optional to represent the hat member variable the implementation is as expressive as can be.
struct Hat {...}class Head {public: Head() { assert(!hat_); } // hat_ is empty by default auto set_hat(const Hat& h){ hat_ = h; } auto has_hat() const { return hat_.has_value(); } auto& get_hat() const { assert(hat_.has_value()); return *hat_; } auto remove_hat() { hat_ = {}; } // Hat is cleared by assigning to {}private: std::optional<Hat> hat_;};
Without std::optional, representing an optional member variable would rely on, for example, a pointer or an extra bool member variable. Both having disadvantages ...