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

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

// 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* вызовет неопределенное поведение (за нарушение требует пункт в [Optional.observe] § 5).

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

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

3

Решение

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

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

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

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

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

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

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

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]