...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
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 ) ; }
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.