Эта библиотека предполагает, что деструктор<T
>не выбрасывает исключений. Если это так, то поведение многих операций на<optional<T>
>не определено.
Следующие мутирующие операции никогда не делают исключений:
- <
optional<T>::operator=(none_t
)noexcept
>
- <
optional<T>::reset()noexcept
>
Кроме того, следующие конструкторы и деструктор никогда не выбрасывают исключения:
- <
optional<T>::optional()
noexcept
>
- <
optional<T>::optional(
none_t)
noexcept
>
Что касается следующих функций назначения:
- <
optional<T>::operator=(optional<T>const&)
>
- <
optional<T>::operator=(Tconst&)
>
- <
template<classU>optional<T>::operator=(optional<U>const&)
>
- <
template<classInPlaceFactory>optional<T>::operator=(InPlaceFactory
const&
)
>
- <
template<classTypedInPlaceFactory>optional<T>::operator=(TypedInPlaceFactory
const&
)
>
- <
optional<T>::reset(Tconst&)
>
Они направляют вызовы соответствующим строителям или заданиям<T
>(в зависимости от того, инициализирован ли факультативный объект или нет); поэтому, если конструктор<T
>и назначение обеспечивают сильную гарантию безопасности исключения,<optional<T>
>назначение также обеспечивает сильную гарантию безопасности исключения; в противном случае мы получаем только базовую гарантию. Кроме того, если оба участвуют<T
>конструктор и назначение никогда не бросать,<optional<T>
>назначение также никогда не бросает.
Если только<T
>строитель или назначение бросает, назначения<optional<T>
>не бросать ничего другого самостоятельно. Бросок при назначении никогда не изменяет состояние инициализации любого необязательного объекта:
optional<T> opt1(val1);
optional<T> opt2(val2);
assert(opt1);
assert(opt2);
try
{
opt1 = opt2;
}
catch(...)
{
assert(opt1);
assert(opt2);
}
Это также относится к передвижению заданий/конструкторов. Тем не менее, операции перемещения делаются без броска чаще.
Операция<emplace
>обеспечивает основные гарантии безопасности. Если он бросает, необязательный объект становится неинициализированным независимо от его начального состояния, а его предыдущее содержащееся значение (если таковое имеется) разрушается. Он не вызывает никакого назначения или перемещения / копирования конструктора<T
>.
Если<swap
>на опциональном не настроен, его первичная реализация пересылает вызовы<T
>'s<swap
>или конструктору перемещения (в зависимости от состояния инициализации факультативных объектов). Таким образом, если и<T
><swap
>и движущийся конструктор никогда не бросают,<swap
>на<optional<T>
>никогда не бросает. Точно так же, если и<T
><swap
>, и движущийся конструктор предлагают сильную гарантию,<swap
>на<optional<T>
>также предлагает сильную гарантию.
В случае, если<swap
>опционально настроен, вызов к<T
>конструктору хода заменяется вызовами к<T
>конструктору по умолчанию, за которым следует<swap
>. (Это более полезно для старых компиляторов, которые не поддерживают семантику движения, когда вы хотите получить более сильные гарантии безопасности исключения.) В этом случае исключительные гарантии безопасности для<swap
>зависят от гарантий<T
>'s<swap
>и конструктора по умолчанию.