Почему преобразование std::optional в std::optional меняет хранимое значение?
#include <iostream>
#include <optional>
int main() {
const auto a = std::optional<int>(0);
const auto b = std::optional<bool>(a);
std::cout << a.value() << b.value() << '\n';
}
Почему программа печатает 01, а не 00?
Ответы (1 шт):
Потому что при таком преобразовании происходит неявное преобразование std::optional<int>(0) в bool. А в документации ясно говорится, что такое преобразование дает true, если в std::optional хранится значение, и false, если его нет. Но ведь в std::optional<int>(0) значение хранится, с этим вы не спорите? Вот и получается, что его приведение к bool дает значение true, все в соответствии со стандартом...
Если хотите получить значение, то делайте уж
const auto b = std::optional<bool>(*a);
только при использовании оператора * обратите внимание на примечание
This operator does not check whether the optional contains a value! You can do so manually by using has_value() or simply operator bool(). Alternatively, if checked access is needed, value() or value_or() may be used.
P.S. Мне показалось правильным внести в ответ из комментариев следующее:
Если в первом заменить тип
intнаbool, то будет ожидаемый вывод. Если поставить в первомint, а во второмdouble, то тоже будет ожидаемый результат, хотя при этом типы разные.
Потому что нет оператора преобразования optional<int> в double, только в bool. Соответственно, рассматриваются варианты, требующие более сложного преобразования.
<bool> -> <bool> - работает точно соответствующий конструктор копирования.
<int> -> <bool> - работает приведение типа к bool, о котором я уже написал.
<int> -> <double> — ничего проще, чем шаблонный конструктор, нет, применяется он.