Because T might be of reference
type, in the sequel, those entries whose semantic depends on T being of reference type or not will be
distinguished using the following convention:

If the entry reads: optional<T(not
a ref)>, the description
corresponds only to the case where T
is not of reference type.

If the entry reads: optional<T&>,
the description corresponds only to the case where T
is of reference type.

If the entry reads: optional<T>,
the description is the same for both cases.

Note

The following section contains various assert() which are used only to show the postconditions
as sample code. It is not implied that the type T
must support each particular expression but that if the expression is supported,
the implied condition holds.

Notes: If *this was initialized, T's
assignment operator is used, otherwise, its copy-constructor is used.

Exception Safety: In the event of an exception,
the initialization state of *this is unchanged and its value unspecified
as far as optional is concerned
(it is up to T's operator=()).
If *this
is initially uninitialized and T's
copy constructor fails, *this is left properly uninitialized.

Postconditions: *this is initialized and it references the
same object referenced by rhs.

Notes: If *this was initialized, is is rebound
to the new object. See here
for details on this behavior.

Example:

inta=1;intb=2;T&ra=a;T&rb=b;optional<int&>def;optional<int&>opt(ra);def=rb;// binds 'def' to 'b' through 'rb'
assert(*def==b);*def=a;// changes the value of 'b' to a copy of the value of 'a'
assert(b==a);intc=3;int&rc=c;opt=rc;// REBINDS to 'c' through 'rc'
c=4;assert(*opt==4);

optional&optional<T(not a ref)>::operator=(optionalconst&rhs);

Effect: Assigns another optional
to an optional.

Postconditions: If rhs
is initialized, *this
is initialized and its value is a copy of the value
of rhs; else *this is uninitialized.

Throws: Whatever T::operator(Tconst&) or T::T(Tconst&) throws.

Notes: If both *this and rhs
are initially initialized, T's
assignment operator is used. If *this is initially initialized but rhs is uninitialized, T's
[destructor] is called. If *this is initially uninitialized but rhs is initialized, T's
copy constructor is called.

Exception Safety: In the event of an exception,
the initialization state of *this is unchanged and its value unspecified
as far as optional is concerned (it is up to T's
operator=()).
If *this
is initially uninitialized and T's
copy constructor fails, *this is left properly uninitialized.

Example:

Tv;optional<T>opt(v);optional<T>def;opt=def;assert(!def);// previous value (copy of 'v') destroyed from within 'opt'.

optional<T&>&optional<T&>::operator=(optional<T&>const&rhs);

Effect: (Re)binds thee wrapped reference.

Postconditions: If *rhs is initialized, *this is initialized and it references the
same object referenced by *rhs; otherwise, *this is uninitialized (and references no object).

Notes: If *this was initialized and so is *rhs, this
is is rebound to the new object. See here
for details on this behavior.

Example:

inta=1;intb=2;T&ra=a;T&rb=b;optional<int&>def;optional<int&>ora(ra);optional<int&>orb(rb);def=orb;// binds 'def' to 'b' through 'rb' wrapped within 'orb'
assert(*def==b);*def=ora;// changes the value of 'b' to a copy of the value of 'a'
assert(b==a);intc=3;int&rc=c;optional<int&>orc(rc);ora=orc;// REBINDS ora to 'c' through 'rc'
c=4;assert(*ora==4);

template<U>optional&optional<T(not a ref)>::operator=(optional<U>const&rhs);

Effect: Assigns another convertible optional
to an optional.

Postconditions: If rhs
is initialized, *this
is initialized and its value is a copy of the value
of rhsconverted
to type T; else *this is uninitialized.

Throws: Whatever T::operator=(Uconst&) or
T::T(Uconst&) throws.

Notes: If both *this and rhs are initially initialized, T's assignment operator
(from U) is used. If *this is initially
initialized but rhs is uninitialized,
T's destructor
is called. If *this
is initially uninitialized but rhs is initialized, T's
converting constructor (from U)
is called.

Exception Safety: In the event of an exception,
the initialization state of *this is unchanged and its value unspecified
as far as optional is concerned (it is up to T's
operator=()).
If *this
is initially uninitialized and T's
converting constructor fails, *this is left properly uninitialized.

Returns: If both x
and y are initialized, (*x==*y). If only x
or y is initialized, false. If both are uninitialized, true.

Throws: Nothing.

Notes: Pointers have shallow relational
operators while optional
has deep relational operators. Do not use operator== directly in generic code which
expect to be given either an optional<T>
or a pointer; use equal_pointees()
instead

Returns: If y
is not initialized, false. If
y is initialized and x is not initialized, true.
If both x and y are initialized, (*x<*y).

Throws: Nothing.

Notes: Pointers have shallow relational
operators while optional
has deep relational operators. Do not use operator< directly in generic code which
expect to be given either an optional<T>
or a pointer; use less_pointees()
instead.

Effect: If both x
and y are initialized, calls
swap(*x,*y) using std::swap.
If only one is initialized, say x,
calls: y.reset(*x);x.reset(); If none is initialized, does nothing.

Postconditions: The states of x and y
interchanged.

Throws: If both are initialized, whatever
swap(T&,T&)
throws. If only one is initialized, whatever T::T(Tconst&) throws.

Notes: If both are initialized, swap(T&,T&) is used unqualified but with std::swap
introduced in scope. If only one is initialized, T::~T()
and T::T(Tconst&) is called.

Exception Safety: If both are initialized,
this operation has the exception safety guarantees of swap(T&,T&).
If only one is initialized, it has the same basic guarantee as optional<T>::reset(Tconst&).

Example:

Tx(12);Ty(21);optional<T>def0;optional<T>def1;optional<T>optX(x);optional<T>optY(y);boost::swap(def0,def1);// no-op
boost::swap(def0,optX);assert(*def0==x);assert(!optX);boost::swap(def0,optX);// Get back to original values
boost::swap(optX,optY);assert(*optX==y);assert(*optY==x);