Exception Safety Guarantees

| Home | Libraries | People | FAQ | More

## Exception Safety Guarantees

Because of the current implementation (see Implementation Notes), all of the assignment methods:

- `optional<T>::operator= ( optional<T> const& )`
- `optional<T>::operator= ( T const& )`
- `template<class U> optional<T>::operator= ( optional<U> const& )`
- `template<class InPlaceFactory> optional<T>::operator= ( InPlaceFactory const& )`
- `template<class TypedInPlaceFactory> optional<T>::operator= ( TypedInPlaceFactory const& )`
- `optional<T>:::reset ( T const&)`

Can only guarantee the basic exception safety: The lvalue optional is left uninitialized if an exception is thrown (any previous value is first destroyed using `T::~T()`)

On the other hand, the uninitializing methods:

- `optional<T>::operator= ( detail::none_t )`
- `optional<T>::reset()`

Provide the no-throw guarantee (assuming a no-throw `T::~T()`)

However, since `optional<>` itself doesn't throw any exceptions, the only source for exceptions here are `T`'s constructor, so if you know the exception guarantees for `T::T ( T const& )`, you know that `optional`'s assignment and reset has the same guarantees.

    //
    // Case 1: Exception thrown during assignment.
    //
    T v0(123);
    optional<T> opt0(v0);
    try
    {
        T v1(456);
        optional<T> opt1(v1);
        opt0 = opt1 ;

        // If no exception was thrown, assignment succeeded.
        assert( *opt0 == v1 ) ;
    }
    catch(...)
    {
        // If any exception was thrown, 'opt0' is reset to uninitialized.
        assert( !opt0 ) ;
    }

    //
    // Case 2: Exception thrown during reset(v)
    //
    T v0(123);
    optional<T> opt(v0);
    try
    {
        T v1(456);
        opt.reset ( v1 ) ;

        // If no exception was thrown, reset succeeded.
        assert( *opt == v1 ) ;
    }
    catch(...)
    {
        // If any exception was thrown, 'opt' is reset to uninitialized.
        assert( !opt ) ;
    }

#### Swap

`void swap( optional<T>&, optional<T>& )` has the same exception guarantee as `swap(T&,T&)` when both optionals are initialized. If only one of the optionals is initialized, it gives the same basic exception guarantee as `optional<T>::reset( T const& )` (since `optional<T>::reset()` doesn't throw). If none of the optionals is initialized, it has no-throw guarantee since it is a no-op.