Согласно стандарту, если вы сохраняете значение в std::optional
, то это значение должно быть в состоянии получить именно то, что сохранено.Кроме того, если задействован optional<T>
, вы можете сохранить любой T
в значении optional
, не сообщая optional
, что вы это делаете.Например:
optional<T> opt = T{};
auto &&val = *opt;
val = <insert value here>; //opt has no idea it has been set.
Из-за этого единственный действительный способ optional<T>
может быть оптимизирован для использования определенных значений T
, означающих, что optional
не включен, если он невозможно для пользователя создать T
с этими значениями.Реализации IEEE-754 double
могут принимать любой битовый шаблон, и все они являются допустимыми (даже сигнализируя NaN).
Причина, по которой другие необязательные типы могут сделать это, заключается в том, что они имеют неявное соглашение с пользователем, чтоони не будут устанавливать для него определенные значения.std::optional<T>
не имеет такого соглашения;любое значение, которое может принять T
, может быть сохранено и извлечено.
Теперь, если optional<T>::operator*
и optional<T>::value
вернули какой-то прокси-объект, а не прямую ссылку на T
, то это может бытьвозможно, так как прокси может обрабатывать соответствующие преобразования.Но даже тогда стандарт должен был бы конкретно указать, что попытка установить его на одно из этих значений приведет к тому, что значение примет эквивалентное, но другое представление объекта.