...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
optional<T> make_optional( T const& v )
optional<T>(v)
for the deduced
type T
of v
.
template<class T> void foo ( optional<T> const& opt ) ; foo ( make_optional(1+1) ) ; // Creates an optional<int>
optional<std::decay_t<T>> make_optional( T && v )
optional<std::decay_t<T>>(std::move(v))
for the deduced
type T
of v
.
optional<T> make_optional( bool condition, T const& v )
optional<T>(condition, v)
for the deduced
type T
of v
.
optional<double> calculate_foo() { double val = compute_foo(); return make_optional(is_not_nan_and_finite(val),val); } optional<double> v = calculate_foo(); if ( !v ) error("foo wasn't computed");
optional<std::decay_t<T>> make_optional( bool condition, T && v )
optional<std::decay_t<T>>(condition, std::move(v))
for the deduced
type T
of v
.
bool operator == ( optional<T> const& x, optional<T> const& y );
T
shall meet requirements of EqualityComparable
.
x
and y
are initialized,
(*x
== *y)
.
If only x
or y
is initialized, false
.
If both are uninitialized, true
.
optional<T>
not containing a value is compared unequal to any optional<T>
containing any value, and equal
to any other optional<T>
not containing a value. 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
optional<T> oN, oN_; optional<T> o1(T(1)), o1_(T(1)); optional<T> o2(T(2)); assert ( oN == oN ); // Identity implies equality assert ( o1 == o1 ); // assert ( oN == oN_ ); // Both uninitialized compare equal assert ( oN != o1 ); // Initialized unequal to initialized. assert ( o1 == o1_ ); // Both initialized compare as (*lhs == *rhs) assert ( o1 != o2 ); //
bool operator < ( optional<T> const& x, optional<T> const& y );
*x < *y
shall be well-formed and its result
shall be convertible to bool
.
(!y) ? false : (!x) ? true : *x <
*y
.
optional<T>
not containing a value is ordered as less than any optional<T>
containing any value, and equivalent
to any other optional<T>
not containing a value. 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. T
need not
be LessThanComparable
. Only
single operator<
is required. Other relational operations are defined in terms of this
one. If T
's operator<
satisfies the axioms of LessThanComparable
(transitivity,
antisymmetry and irreflexivity), optinal<T>
is LessThanComparable
.
optional<T> oN, oN_; optional<T> o0(T(0)); optional<T> o1(T(1)); assert ( !(oN < oN) ); // Identity implies equivalence assert ( !(o1 < o1) ); assert ( !(oN < oN_) ); // Two uninitialized are equivalent assert ( !(oN_ < oN) ); assert ( oN < o0 ); // Uninitialized is less than initialized assert ( !(o0 < oN) ); assert ( o1 < o2 ) ; // Two initialized compare as (*lhs < *rhs) assert ( !(o2 < o1) ) ; assert ( !(o2 < o2) ) ;
bool operator != ( optional<T> const& x, optional<T> const& y );
!(
x ==
y );
bool operator > ( optional<T> const& x, optional<T> const& y );
(
y <
x );
bool operator <= ( optional<T> const& x, optional<T> const& y );
!(
y <
x );
bool operator >= ( optional<T> const& x, optional<T> const& y );
!(
x <
y );
bool operator == ( optional<T> const& x, none_t ) noexcept;
bool operator == ( none_t, optional<T> const& x ) noexcept;
!x
.
T
need not meet requirements of EqualityComparable
.
bool operator != ( optional<T> const& x, none_t ) noexcept;
bool operator != ( none_t, optional<T> const& x ) noexcept;
bool(x);
auto get_pointer ( optional<T>& o ) -> typename optional<T>::pointer_type ;
auto get_pointer ( optional<T> const& o ) -> typename optional<T>::pointer_const_type ;
o.get_ptr()
.
auto get_optional_value_or ( optional<T>& o, typename optional<T>::reference_type def ) -> typename optional<T>::reference_type ;
auto get_optional_value_or ( optional<T> const& o, typename optional<T>::reference_const_type def ) -> typename optional<T>::reference_const_type ;
o.get_value_or(def)
.
void swap ( optional<T>& x, optional<T>& y ) ;
T
shall be swappable and T
shall be MoveConstructible
.
Effects:
|
|
|
|
calls |
initializes the contained value of |
|
initializes the contained value of |
no effect |
x
and y
interchanged.
swap(T&,T&)
throws. If only one is initialized, whatever T::T ( T&& )
throws.
T x(12); T y(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 );
void swap ( optional<T&>& x, optional<T&>& y ) noexcept ;
x
refers to what y
refererred
to before the swap (if anything). y
refers to whatever x
referred to before the swap.
T x(12); T y(21); optional<T&> opt0; optional<T&> optX (x); optional<T&> optY (y); boost::swap(optX, optY); assert (addressof(*optX) == addressof(y)); assert (addressof(*optY) == addressof(x)); boost::swap(opt0, optX); assert ( opt0 ); assert ( !optX ); assert (addressof(*opt0) == addressof(y));