Why is this an issue?
The class std::optional<T>
either stores a value of type T
or is empty.
One way to access the value of a non-empty optional is the operator*
. But using the dereference operator gives the optional appearance
of a pointer when it is not: it models an object. Additionally, attempting to call the operator*
on an empty optional will result in
undefined behavior.
Another way to access the value of a non-empty optional is the function value()
. But assigning a value to the optional object through
this function will throw an exception (std::bad_optional_access
) if the optional has no value, and the assignment will not happen.
For the assignment of an optional to happen correctly, whatever its state, it is better to:
- assign the value directly with the
operator=
: e.g. myOptionalInteger = 3;
- use the
emplace
function (for example, when the move or copy operation is expensive or forbidden).
How to fix it
The rule raises an issue when the operator*
or the value()
function are used to assign a new value to an optional.
Code examples
Noncompliant code example
void g(std::optional<int> &val, bool b) {
if (b) {
*val = 314; // Noncompliant; the behavior is undefined if the optional is empty.
} else {
val.value() = 42; // Noncompliant; it will throw if the optional is empty.
}
}
Compliant solution
void g(std::optional<int> &val, bool b) {
if (b) {
val = 314; // Compliant
} else {
val = 42; // Compliant
}
}
Resources