Я видел следующий шаблон несколько раз:
// 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*
вызовет неопределенное поведение (из-за нарушения предложения requires в [необязательный.observe]§5).
std::optional<T> storage;
T &t = *storage; // Looks okay, mines bitcoin when you're not looking
Возможно ли такое использование std::optional
каким-то образом?
Если нет, то по какой причине его можно предотвратить?
t
в первом примере не требует предварительного запуска множества проверок, связанных с бухгалтерией? - person StoryTeller - Unslander Monica   schedule 26.12.2017main
, и это просто о том, чтобы избежать слишком многого во время статической инициализации/уничтожения, сохраняя при этом глобальную точку доступа. - person Quentin   schedule 26.12.2017T &t = reinterpret_cast<T &>(storage);
демонстрирует неопределенное поведение, или, скорее, последующее использованиеt
будет. Правильный способ сделать этоT& t = *new(&storage) T;
. По сути, это эквивалентно установке значения вstd::optional
. В итоге получается шесть одних, полдюжины других. - person Igor Tandetnik   schedule 26.12.2017optional
, и тогдаoperator*
будет работать. - person Igor Tandetnik   schedule 26.12.2017