The class template std::optional manages an optional contained value: an object that is either engaged and stores a T, or disengaged and stores no value.
std::optional is primarily used to model “maybe a value” without falling back to sentinel values, out-parameters, or heap allocation. A successful result is stored directly inside the optional object, so the type behaves like an object wrapper rather than a smart pointer.
#
Declarations
template< class T >
class optional;
(since C++17)
#
Semantic model
- An engaged
optional<T> contains a T nested inside the optional object itself. - A disengaged
optional<T> contains no T; operator bool() and has_value() report that state. reset() destroys the contained object and returns the optional to the empty state.- Checked access goes through value() and throws bad_optional_access if no value is present.
- Unchecked access goes through operator-> and operator*; these require that a value is already present.
- Since C++26,
optional also models a zero-or-one-element view with begin() and end().
#
Template parameters
| Parameter | Description |
|---|
T | The stored value type. T must be destructible. Reference types, array types, function types, void, std::nullopt_t, and std::in_place_t are not valid optional element types. |
#
Member types
| Member type | Definition |
|---|
value_type | T |
iterator | C++26 iterator type for the zero-or-one-element range view returned by begin() |
const_iterator | C++26 const iterator type for the range view |
The iterator aliases exist to make optional participate in range-based code as a tiny view, not to turn it into a general-purpose container.
#
Member functions
#
Special members
#
Iterators
| Member | Purpose |
|---|
| begin | Returns an iterator to the contained element when engaged, otherwise the past-the-end iterator |
| end | Returns the end iterator for the zero-or-one-element range |
#
Observers
#
Monadic operations
| Member | Purpose |
|---|
| and_then | Chains another optional-producing operation when a value is present |
| transform | Applies a transformation to the contained value and wraps the result |
| or_else | Produces an alternative optional when the current one is empty |
These C++23 operations let optional pipelines stay explicit about success and absence without repeated if (opt) scaffolding.
#
Modifiers
| Member | Purpose |
|---|
| swap | Exchanges the states and contained values of two optionals |
| reset | Destroys any contained value and leaves the optional disengaged |
| emplace | Constructs the contained value directly inside the optional |
#
Non-member functions
#
Helper classes and objects
#
Helper specializations
ranges::enable_view<std::optional<T>> = true makes optional model a view in C++26.format_kind<std::optional<T>> = range_format::disabled disables generic range formatting for optional in C++26.
#
Deduction guides
The class has deduction guides so direct construction such as std::optional o(std::string{"x"}); can infer the stored type without spelling T explicitly.
#
Notes
| Feature-test macro | Value | Standard | Meaning |
|---|
__cpp_lib_optional | 201606L | C++17 | std::optional |
__cpp_lib_optional | 202106L | C++23 (DR20) | fully constexpr optional |
__cpp_lib_optional | 202110L | C++23 | monadic operations |
__cpp_lib_optional_range_support | 202406L | C++26 | range support for std::optional |
optional expresses absence, but not the reason for absence. If the caller needs structured error information rather than a simple engaged/disengaged state, std::expected is usually a better fit.
#
Example
#include <iostream>
#include <optional>
#include <string>
// optional can be used as the return type of a factory that may fail
std::optional<std::string> create(bool b)
{
if (b)
return "Godzilla";
return {};
}
// std::nullopt can be used to create any (empty) std::optional
auto create2(bool b)
{
return b ? std::optional<std::string>{"Godzilla"} : std::nullopt;
}
int main()
{
std::cout << "create(false) returned "
<< create(false).value_or("empty") << '\n';
// optional-returning factory functions are usable as conditions of while and if
if (auto str = create2(true))
std::cout << "create2(true) returned " << *str << '\n';
}
#
See also