Ссылка на значение пустого необязательного

Я видел следующую картину несколько раз:

// T is a type, this is at namespace scope
std::aligned_storage_t<sizeof(T), alignof(T)> storage;
T &t = reinterpret_cast<T &>(storage);

Это, в сочетании с адекватным пространством имен и имен, обеспечивает приятный интерфейс (t) для пользователей переменной, обеспечивая возможность отложенного построения, повторной инициализации и т. д. реального объекта на стороне библиотеки при размещении new и явные вызовы деструкторов. Вы можете видеть это работает здесь.

Сейчас, std::aligned_storage и все, но C++17 дал нам новый инструмент для такого разделения времени хранения объекта хранения, то есть std::optional,

Тем не менее, два способа доступа к значению std::optional (value() а также operator*) оба требуют значения, чтобы действительно быть там; иначе value() будет бросать std::bad_optional_access, в то время как operator* вызовет неопределенное поведение (за нарушение условия require в [option.observe] §5).

std::optional<T> storage;
T &t = *storage; // Looks okay, mines bitcoin when you're not looking

Такое использование std::optional все еще возможно как-то?
Если нет, что было бы причиной для предотвращения этого?

1 ответ

Решение

Это, в сочетании с адекватным пространством имен и именами, обеспечивает приятный интерфейс (t) для пользователей переменной, в то же время обеспечивая отложенное создание, повторную инициализацию и т. Д. Реального объекта на стороне библиотеки.

К сожалению, используя t доступ к объекту, созданному позже по этому адресу, является неопределенным поведением. Это одна из причин, почему std::launder предлагается.

Обратите внимание, что этот случай отличается от случая, описанного в этом вопросе. В этом вопросе ссылка / указатель получается после объекта типа T создается (хотя это также может быть неопределенным после C++17 без std::launder).

Такое использование std::option все еще возможно?

Как вы указали, это неопределенное поведение.

Если нет, что было бы причиной для предотвращения этого?

Оптимизатор может обнаружить, что адрес связан с объектом, который предоставляет хранилище для Tи игнорировать любой доступ к этому адресу через glvalue типа, который вызывает неопределенное поведение. На самом деле, причина в том, что правила строгого наложения выгодны для оптимизатора.

Другие вопросы по тегам