...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Note | |
---|---|
The following section contains various |
optional<T>::optional() noexcept;
optional
.
*this
is uninitialized.
optional<T> def ; assert ( !def ) ;
optional<T>::optional( none_t ) noexcept;
optional
uninitialized.
*this
is uninitialized.
T
's
default constructor is not called.
The expression boost::none
denotes an instance of boost::none_t
that can be used as the parameter.
#include <boost/none.hpp> optional<T> n(none) ; assert ( !n ) ;
optional<T>::optional( T const& v )
is_copy_constructible<T>::value
is true
.
optional
.
*this
is initialized
and its value is a copy of v
.
T::T( T const&
)
throws.
T::T( T const&
)
is called.
T::T( T const&
);
in that case, this constructor
has no effect.
T v; optional<T> opt(v); assert ( *opt == v ) ;
optional<T>::optional( T&& v )
is_move_constructible<T>::value
is true
.
optional
.
*this
is initialized
and its value is move-constructed from v
.
T::T( T&& )
throws.
T::T( T&& )
is called.
T::T( T&& );
in that case, the state of v
is determined by exception safety guarantees for T::T(T&&)
.
T v1, v2; optional<T> opt(std::move(v1)); assert ( *opt == v2 ) ;
optional<T>::optional( bool condition, T const& v ) ;
optional<T>::optional( T const& v )
optional<T>::optional()
optional<T>::optional( optional const& rhs );
is_copy_constructible<T>::value
is true
.
optional
.
*this
is initialized and its value is a copy of the
value of rhs
; else
*this
is uninitialized.
T::T( T const&
)
throws.
T::T(T const& )
is called.
T::T( T const&
);
in that case, this constructor
has no effect.
optional<T> uninit ; assert (!uninit); optional<T> uinit2 ( uninit ) ; assert ( uninit2 == uninit ); optional<T> init( T(2) ); assert ( *init == T(2) ) ; optional<T> init2 ( init ) ; assert ( init2 == init ) ;
optional<T>::optional( optional&& rhs ) noexcept(
see below);
is_move_constructible<T>::value
is true
.
optional
.
rhs
is initialized, *this
is initialized and its value is move constructed from rhs
; else *this
is uninitialized.
T::T( T&& )
throws.
noexcept
is equivalent to is_nothrow_move_constructible<T>::value
.
rhs
is initialized, T::T( T &&
)
is called.
T::T( T&& );
in that case, rhs
remains
initialized and the value of *rhs
is determined by exception safety
of T::T(T&&)
.
optional<std::unique_ptr<T>> uninit ; assert (!uninit); optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ; assert ( uninit2 == uninit ); optional<std::unique_ptr<T>> init( std::unique_ptr<T>(new T(2)) ); assert ( **init == T(2) ) ; optional<std::unique_ptr<T>> init2 ( std::move(init) ) ; assert ( init ); assert ( *init == nullptr ); assert ( init2 ); assert ( **init2 == T(2) ) ;
template<U> explicit optional<T>::optional( optional<U> const& rhs );
optional
.
rhs
is initialized, *this
is initialized and its value is a copy of the
value of rhs converted to type T
;
else *this
is uninitialized.
T::T( U const&
)
throws.
T::T( U const&
)
is called if rhs
is initialized, which requires
a valid conversion from U
to T
.
T::T( U const&
);
in that case, this constructor
has no effect.
optional<double> x(123.4); assert ( *x == 123.4 ) ; optional<int> y(x) ; assert( *y == 123 ) ;
template<U> explicit optional<T>::optional( optional<U>&& rhs );
optional
.
rhs
is initialized, *this
is initialized and its value is move-constructed from *rhs
;
else *this
is uninitialized.
T::T( U&& )
throws.
T::T( U&& )
is called if rhs
is
initialized, which requires a valid conversion from U
to T
.
T::T( U&& );
in that case, rhs
remains
initialized and the value of *rhs
is determined by exception safety
guarantee of T::T( U&&
)
.
optional<double> x(123.4); assert ( *x == 123.4 ) ; optional<int> y(std::move(x)) ; assert( *y == 123 ) ;
template<class... Args> explicit optional<T>::optional( in_place_init_t, Args&&... ars );
is_constructible_v<T, Args&&...>
is true
.
T
with the arguments std::forward<Args>(args)...
.
*this
is initialized.
T
.
T
need not be MoveConstructible
.
On compilers that do not support variadic templates or rvalue references,
this constuctor is available in limited functionality. For details
see here.
// creates an std::mutex using its default constructor optional<std::mutex> om {in_place_init}; assert (om); // creates a unique_lock by calling unique_lock(*om, std::defer_lock) optional<std::unique_lock<std::mutex>> ol {in_place_init, *om, std::defer_lock}; assert (ol); assert (!ol->owns_lock());
template<class... Args> explicit optional<T>::optional( in_place_init_if_t, bool condition, Args&&... ars );
is_constructible_v<T, Args&&...>
is true
.
condition
is true
, initializes the
contained value as if direct-non-list-initializing an object of type
T
with the arguments
std::forward<Args>(args)...
.
bool(*this) == condition
.
T
.
T
need not be MoveConstructible
.
On compilers that do not support variadic templates or rvalue references,
this constuctor is available in limited functionality. For details
see here.
optional<std::vector<std::string>> ov1 {in_place_init_if, false, 3, "A"}; assert (!ov1); optional<std::vector<std::string>> ov2 {in_place_init_if, true, 3, "A"}; assert (ov2); assert (ov2->size() == 3);
template<InPlaceFactory> explicit optional<T>::optional( InPlaceFactory const& f );
template<TypedInPlaceFactory> explicit optional<T>::optional( TypedInPlaceFactory const& f );
optional
with a value of T
obtained from the factory.
*this
is initialized
and its value is directly given from the factory
f
(i.e., the value
is not copied).
T
constructor called by the factory
throws.
T
constructor used by the factory; in that case, this constructor has
no effect.
class C { C ( char, double, std::string ) ; } ; C v('A',123.4,"hello"); optional<C> x( in_place ('A', 123.4, "hello") ); // InPlaceFactory used optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used assert ( *x == v ) ; assert ( *y == v ) ;
optional& optional<T>::operator= ( none_t ) noexcept;
*this
is initialized destroys its contained
value.
*this
is uninitialized.
optional& optional<T>::operator= ( T const& rhs ) ;
rhs
to an optional
.
*this
is initialized and its value is
a copy of rhs
.
T::operator=( T const&
)
or T::T(T const&)
throws.
*this
was initialized, T
's assignment operator is used,
otherwise, its copy-constructor is used.
*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.
T x; optional<T> def ; optional<T> opt(x) ; T y; def = y ; assert ( *def == y ) ; opt = y ; assert ( *opt == y ) ;
optional& optional<T>::operator= ( T&& rhs ) ;
rhs
to an optional
.
*this
is initialized and its value is
moved from rhs
.
T::operator=( T&& )
or T::T(T &&)
throws.
*this
was initialized, T
's move-assignment operator is used,
otherwise, its move-constructor is used.
*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
move constructor fails, *this
is left properly uninitialized.
T x; optional<T> def ; optional<T> opt(x) ; T y1, y2, yR; def = std::move(y1) ; assert ( *def == yR ) ; opt = std::move(y2) ; assert ( *opt == yR ) ;
optional& optional<T>::operator= ( optional const& rhs ) ;
T
is CopyConstructible
and CopyAssignable
.
Effects:
|
|
|
|
assigns |
initializes the contained value as if direct-initializing
an object of type |
|
destroys the contained value by calling |
no effect |
*this
;
bool(rhs) == bool(*this)
.
*this
and rhs
remains unchanged. If an exception is thrown during the call to T
's copy constructor, no effect.
If an exception is thrown during the call to T
's
copy assignment, the state of its contained value is as defined by
the exception safety guarantee of T
's
copy assignment.
T v; optional<T> opt(v); optional<T> def ; opt = def ; assert ( !def ) ; // previous value (copy of 'v') destroyed from within 'opt'.
optional& optional<T>::operator= ( optional&& rhs ) noexcept(
see below);
T
is MoveConstructible
and MoveAssignable
.
Effects:
|
|
|
|
assigns |
initializes the contained value as if direct-initializing
an object of type |
|
destroys the contained value by calling |
no effect |
*this
;
bool(rhs) == bool(*this)
.
noexcept
is equivalent to is_nothrow_move_constructible<T>::value &&
is_nothrow_move_assignable<T>::value
.
*this
and rhs
remains unchanged. If an exception is thrown during the call to T
's move constructor, the state of
*rhs
is determined by the exception safety guarantee of T
's
move constructor. If an exception is thrown during the call to T's
move-assignment, the state of **this
and *rhs
is determined by the exception
safety guarantee of T's move assignment.
optional<T> opt(T(2)) ; optional<T> def ; opt = def ; assert ( def ) ; assert ( opt ) ; assert ( *opt == T(2) ) ;
template<U> optional& optional<T>::operator= ( optional<U> const& rhs ) ;
Effect:
|
|
|
|
assigns |
initializes the contained value as if direct-initializing
an object of type |
|
destroys the contained value by calling |
no effect |
*this
.
bool(rhs) == bool(*this)
.
bool(*this)
remains unchanged. If an exception
is thrown during the call to T
's
constructor, no effect. If an exception is thrown during the call to
T
's assignment, the
state of its contained value is as defined by the exception safety
guarantee of T
's copy
assignment.
T v; optional<T> opt0(v); optional<U> opt1; opt1 = opt0 ; assert ( *opt1 == static_cast<U>(v) ) ;
template<U> optional& optional<T>::operator= ( optional<U>&& rhs ) ;
Effect:
|
|
|
|
assigns |
initializes the contained value as if direct-initializing
an object of type |
|
destroys the contained value by calling |
no effect |
*this
.
bool(rhs) == bool(*this)
.
bool(*this)
remains unchanged. If an exception
is thrown during the call to T
's
constructor, no effect. If an exception is thrown during the call to
T
's assignment, the
state of its contained value is as defined by the exception safety
guarantee of T
's copy
assignment.
T v; optional<T> opt0(v); optional<U> opt1; opt1 = std::move(opt0) ; assert ( opt0 ); assert ( opt1 ) assert ( *opt1 == static_cast<U>(v) ) ;
template<class... Args> void optional<T>::emplace( Args&&... args );
*this
is initialized calls *this = none
.
Then initializes in-place the contained value as if direct-initializing
an object of type T
with std::forward<Args>(args)...
.
*this
is initialized.
T
's constructor throws.
T
,
*this
is uninitialized.
T
need not be MoveConstructible
or MoveAssignable
.
On compilers that do not support variadic templates or rvalue references,
this function is available in limited functionality. For details see here.
T v; optional<const T> opt; opt.emplace(0); // create in-place using ctor T(int) opt.emplace(); // destroy previous and default-construct another T opt.emplace(v); // destroy and copy-construct in-place (no assignment called)
template<InPlaceFactory> optional<T>& optional<T>::operator=( InPlaceFactory const& f );
template<TypedInPlaceFactory> optional<T>& optional<T>::operator=( TypedInPlaceFactory const& f );
optional
with a value of T
obtained
from the factory.
*this
is initialized
and its value is directly given from the factory
f
(i.e., the value
is not copied).
T
constructor called by the factory
throws.
T
constructor used by the factory; in that case, the optional
object will be reset to be uninitialized.
void optional<T>::reset( T const& v ) ;
operator=
( T
const&
v)
;
void optional<T>::reset() noexcept ;
operator=( none_t
);
T const& optional<T>::get() const ;
T& optional<T>::get() ;
inline T const& get ( optional<T> const& ) ;
inline T& get ( optional<T> &) ;
*this
is initialized
BOOST_ASSERT()
.
T const& optional<T>::operator*() const& ;
T& optional<T>::operator*() &;
*this
is initialized
BOOST_ASSERT()
.
On compilers that do not support ref-qualifiers on member functions
these two overloads are replaced with the classical two: a const
and non-const
member functions.
T v ; optional<T> opt ( v ); T const& u = *opt; assert ( u == v ) ; T w ; *opt = w ; assert ( *opt == w ) ;
T&& optional<T>::operator*() &&;
*this
contains a value.
return std::move(*val);
.
BOOST_ASSERT()
.
On compilers that do not support ref-qualifiers on member functions
this overload is not present.
T const& optional<T>::value() const& ;
T& optional<T>::value() & ;
return bool(*this) ? *val : throw bad_optional_access();
.
const
and non-const
member functions.
T v ; optional<T> o0, o1 ( v ); assert ( o1.value() == v ); try { o0.value(); // throws assert ( false ); } catch(bad_optional_access&) { assert ( true ); }
T&& optional<T>::value() && ;
return bool(*this) ? std::move(*val) : throw bad_optional_access();
.
template<class U> T optional<T>::value_or(U && v) const& ;
if (*this) return **this; else return
std::forward<U>(v);
.
T
is not CopyConstructible
or U &&
is not convertible to T
,
the program is ill-formed.
const
-qualified member
function. On compilers without rvalue reference support the type of
v
becomes U const&
.
template<class U> T optional<T>::value_or(U && v) && ;
if (*this) return std::move(**this); else return std::forward<U>(v);
.
T
is not MoveConstructible
or U &&
is not convertible to T
,
the program is ill-formed.
template<class F> T optional<T>::value_or_eval(F f) const& ;
T
is CopyConstructible
and F
models a Generator
whose result type
is convertible to T
.
if
(*this) return **this; else return f();
.
const
-qualified member
function.
int complain_and_0() { clog << "no value returned, using default" << endl; return 0; } optional<int> o1 = 1; optional<int> oN = none; int i = o1.value_or_eval(complain_and_0); // fun not called assert (i == 1); int j = oN.value_or_eval(complain_and_0); // fun called assert (i == 0);
template<class F> T optional<T>::value_or_eval(F f) && ;
T
is MoveConstructible
and F
models a Generator
whose result type
is convertible to T
.
if
(*this) return std::move(**this); else return
f();
.
template<class F> auto optional<T>::map(F f) const& ->
see below;
template<class F> auto optional<T>::map(F f) & ->
see below;
if
(*this) return f(**this); else return
none;
optional<decltype(f(**this))>
.
On compilers that do not support ref-qualifiers on member functions,
these two (as well as the next one) overloads are replaced with good
old const and non-const overloads.
auto length = [](const string& s){ return s.size(); }; optional<string> o1 {}, o2 {"cat"}; optional<size_t> os1 = o1.map(length), os2 = o2.map(length); assert ( !os1 ) ; assert ( os2 ) ; assert ( *os2 == 3 ) ;
template<class F> auto optional<T>::map(F f) && ->
see below;
if
(*this) return f(std::move(**this)); else return
none;
optional<decltype(f(istd::move(**this)))>
.
template<class F> auto optional<T>::flat_map(F f) const& ->
see below;
template<class F> auto optional<T>::flat_map(F f) & ->
see below;
f(**this)
is optional<U>
for some object or reference type U
.
if
(*this) return f(**this); else return
none;
optional<U>
.
On compilers that do not support ref-qualifiers on member functions,
these two (as well as the next one) overloads are replaced with good
old const and non-const overloads.
optional<char> first_char(const string& s) { return s.empty() ? none : optional<char>(s[0]); }; optional<string> o1 {}, o2 {"cat"}; optional<char> os1 = o1.flat_map(first_char), os2 = o2.flat_map(first_char); assert ( !os1 ) ; assert ( os2 ) ; assert ( *os2 == 'c' ) ;
template<class F> auto optional<T>::flat_map(F f) && ->
see below;
f(std::move(**this))
is optional<U>
for some object or reference type U
.
if
(*this) return f(std::move(**this)); else return
none;
optional<U>
.
T const& optional<T>::get_value_or( T const& default) const ;
T& optional<T>::get_value_or( T& default ) ;
value_or()
instead.
default
.
T v, z ; optional<T> def; T const& y = def.get_value_or(z); assert ( y == z ) ; optional<T> opt ( v ); T const& u = opt.get_value_or(z); assert ( u == v ) ; assert ( u != z ) ;
T const* optional<T>::get_ptr() const ;
T* optional<T>::get_ptr() ;
*this
is initialized, a pointer to the
contained value; else 0
(null).
*this
,
so you should not hold nor delete this pointer
T v; optional<T> opt(v); optional<T> const copt(v); T* p = opt.get_ptr() ; T const* cp = copt.get_ptr(); assert ( p == get_pointer(opt) ); assert ( cp == get_pointer(copt) ) ;
T const* optional<T>::operator ->() const ;
T* optional<T>::operator ->() ;
*this
is initialized.
BOOST_ASSERT()
.
struct X { int mdata ; } ; X x ; optional<X> opt (x); opt->mdata = 2 ;
explicit optional<T>::operator bool() const noexcept ;
bool optional<T>::has_value() const noexcept ;
get_ptr() != 0
.
optional<T> def ; assert ( def == 0 ); optional<T> opt ( v ) ; assert ( opt ); assert ( opt != 0 );
bool optional<T>::operator!() noexcept ;
*this
is uninitialized, true
; else false
.
optional<T> opt ; assert ( !opt ); *opt = some_T ; // Notice the "double-bang" idiom here. assert ( !!opt ) ;
bool optional<T>::is_initialized() const ;
explicit operator
bool ()
;