diff --git a/doc/optional.html b/doc/optional.html index 8143319..c0f62cc 100644 --- a/doc/optional.html +++ b/doc/optional.html @@ -24,6 +24,7 @@ HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp>
As of this writing I don't know of any precedence for a variable-size fixed-capacity (of 1) +
As of this writing I don't know of any precedent for a variable-size fixed-capacity (of 1) stack-based container model for optional values, yet I believe this is the consequence of the lack of practical implementations of such a container rather than an inherent shortcoming of the container model.
@@ -324,6 +325,8 @@ class optional optional ( T const& v ) ; + optional ( bool condition, T const& v ) ; [new in 1.34] + optional ( optional const& rhs ) ; template<class U> explicit optional ( optional<U> const& rhs ) ; @@ -347,6 +350,8 @@ class optional T const& get() const ; T& get() ; + T const& get_value_or( T const& default ) const ; [new in 1.34] + T const* operator ->() const ; T* operator ->() ; @@ -380,6 +385,36 @@ template<class T> inline bool operator <= ( optional<T> const& x, op template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; +template<class T> inline bool operator == ( optional<T> const& x, none_t n ) ; [new in 1.34] + +template<class T> inline bool operator != ( optional<T> const& x, none_t n ) ; [new in 1.34] + +template<class T> inline bool operator < ( optional<T> const& x, none_t n ) ; [new in 1.34] + +template<class T> inline bool operator > ( optional<T> const& x, none_t n ) ; [new in 1.34] + +template<class T> inline bool operator <= ( optional<T> const& x, none_t n ) ; [new in 1.34] + +template<class T> inline bool operator >= ( optional<T> const& x, none_t n ) ; [new in 1.34] + +template<class T> inline bool operator == ( none_t n, optional<T> const& y ) ; [new in 1.34] + +template<class T> inline bool operator != ( none_t n, optional<T> const& y ) ; [new in 1.34] + +template<class T> inline bool operator < ( none_t n, optional<T> const& y ) ; [new in 1.34] + +template<class T> inline bool operator > ( none_t n, optional<T> const& y ) ; [new in 1.34] + +template<class T> inline bool operator <= ( none_t n, optional<T> const& y ) ; [new in 1.34] + +template<class T> inline bool operator >= ( none_t n, optional<T> const& y ) ; [new in 1.34] + +template<class T> inline optional<T> make_optional ( T const& v ) ; [new in 1.34] + +template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; [new in 1.34] + +template<class T> inline T const& get_optional_value_or ( optional<T> const& opt, T const& default ) ; [new in 1.34] + template<class T> inline T const& get ( optional<T> const& opt ) ; template<class T> inline T& get ( optional<T> & opt ) ; @@ -436,7 +471,7 @@ assert ( !def ) ;optional<T>::optional( none_t );
-Effect: Constructs an optional uninitialized.
+Effect: Constructs an optional uninitialized.
Postconditions: *this is uninitialized.
Throws: Nothing.
Notes:
@@ -448,9 +483,11 @@ used as the parameter.
Example:
-@@ -459,7 +496,6 @@ assert ( !n ) ;#include <boost/none.hpp>-optional<T> n(none) ; -assert ( !n ) ;++#include <boost/none.hpp> +optional<int> n(boost::none) ; +assert ( !n ) ; +
optional<T (not a ref)>::optional( T const& v )
@@ -484,17 +522,37 @@ instance of an internal type wrapping the reference 'ref'.Effect: Directly-Constructs an optional.
-Postconditions: *this is initialized and its value is a copy of 'v'.
Throws: Whatever T::T( T const& ) throws.
Notes: T::T( T const& ) is called.
@@ -468,9 +504,11 @@ in that case, this constructor has no effect.Example:
-T v; ++T v; optional<T> opt(v); -assert ( *opt == v ) ;+assert ( *opt == v ) ; +
Throws: Nothing.
Example:
-T v; ++T v; T& vref = v ; optional<T&> opt(vref); assert ( *opt == v ) ; ++ v ; // mutate referee -assert (*opt == v);+assert (*opt == v); +
optional<T (not a ref)>::optional( bool condition, T const& v ) ; +optional<T&> ::optional( bool condition, T& v ) ; ++ +
++ +If condition is
+true
, same as:optional<T (not a ref)>::optional( T const& v ) +optional<T&> ::optional( T& v ) ++otherwise, same as:
++optional<T (not a ref)>::optional() +optional<T&> ::optional() ++
optional<T (not a ref)>::optional( optional const& rhs );
Effect: Copy-Constructs an optional.
@@ -508,7 +566,8 @@ in that case, this constructor has no effect.Example:
-optional<T> uninit ; ++optional<T> uninit ; assert (!uninit); optional<T> uinit2 ( uninit ) ; @@ -537,7 +596,8 @@ is uninitialized. reefer to the same object (they alias).Example:
-optional<T&> uninit ; ++optional<T&> uninit ; assert (!uninit); optional<T&> uinit2 ( uninit ) ; @@ -580,7 +640,8 @@ in that case, this constructor has no effect.Example:
-optional<double> x(123.4); ++optional<double> x(123.4); assert ( *x == 123.4 ) ; optional<int> y(x) ; @@ -608,7 +669,8 @@ in that case, this constructor has no effect.Example:
-class C { C ( char, double, std::string ) ; } ; +-+class C { C ( char, double, std::string ) ; } ; C v('A',123.4,"hello"); @@ -624,6 +686,27 @@ assert ( *y == v ) ;
+optional& optional<T>::operator= ( none_t n ) ;+++ +Effect: Same as opeator=(optional const& rhs), when rhs is default-constructed (uninitialized).
+Postconditions: *this is uninitialized
+Example:
++++#include <boost/none.hpp> + +optional<int> def ; +optional<int> opt(123) ; + +opt = boost::none ; + +assert ( opt == def ) ; ++
+optional& optional<T (not a ref)>::operator= ( T const& rhs ) ;Effect: Assigns the value 'rhs' to an optional.
@@ -639,7 +722,8 @@ uninitialized and T's copy constructor fails, *this is left properly uninitialized]Example:
-@@ -965,18 +1094,47 @@ assert ( opt.is_initialized() );T x; ++T x; optional<T> def ; optional<T> opt(x) ; @@ -662,7 +746,8 @@ and it references the same object referenced by rhs. new object. See here for details on this behavior.Example:
-int a = 1 ; ++int a = 1 ; int b = 2 ; T& ra = a ; T& rb = b ; @@ -792,12 +877,11 @@ assert ( *opt1 == static_cast<U>(v) ) ;
void optional<T>::reset() ;-Deprecated: Same as operator=( detail::none_t );
+Deprecated: Same as operator=( none_t n);
-T const& optional<T (not a ref)>::operator*() const ; T& optional<T (not a ref)>::operator*();@@ -828,6 +912,32 @@ assert ( *opt == w ) ;
+T const& optional<T (not a ref)>::get_value_or( T const& default) const ; +T& optional<T (not a ref)>::get_value_or( T& default ) ; + +inline T const& get_optional_value_or ( optional<T (not a ref)> const& o, T const& default ) ; +inline T& get_optional_value_or ( optional<T (not a ref)>& o, T& default ) ; ++++Returns: A reference to the contained value, if any, or
+default
Throws: Nothing.
+Example:
+++ +T v, z ; +optional<T> def; +T const& y = def.get_value_or(z); +assert ( y == z ) ; + +optional<T> opt ( v ); +T const& u = get_optional_value_or(opt,z); +assert ( u == v ) ; +assert ( u != z ) ; ++
+T const& optional<T&>::operator*() const ; T & optional<T&>::operator*();@@ -857,29 +967,39 @@ assert ( *opt == v ) ;
-T const* optional<T (not a ref)>::get_ptr() const ; -T* optional<T (not a ref)>::get_ptr() ; +T const* optional<T>::get_ptr() const ; +T* optional<T>::get_ptr() ; -inline T const* get_pointer ( optional<T (not a ref)> const& ) ; -inline T* get_pointer ( optional<T (not a ref)> &) ; +inline T const* get_pointer ( optional<T> const& ) ; +inline T* get_pointer ( optional<T> &) ;@@ -888,13 +1008,14 @@ assert ( cp == get_pointer(copt) ) ;Returns: If *this is initialized, a pointer to the contained value; else 0 (null).
Throws: Nothing.
+Notes: If T is a reference type, the pointer is to the referenced object
Notes: The contained value is permanently stored within *this, so -you should not hold nor delete this pointer +you should not hold nor delete this pointer.
Example:
-T v; -optional<T> opt(v); -optional<T> const copt(v); -T* p = opt.get_ptr() ; -T const* cp = copt.get_ptr(); +int v=123; +optional<int> opt(v); +optional<int> const copt(v); +int* p = opt.get_ptr() ; +int const* cp = copt.get_ptr(); assert ( p == get_pointer(opt) ); assert ( cp == get_pointer(copt) ) ; + +int& rv = v ; +optional<int&> optr(rv); + +*(optr.get_ptr()) = 456 ; + +assert ( v == 456 ); + +
-T const* optional<T (not a ref)>::operator ->() const ; -T* optional<T (not a ref)>::operator ->() ; +T const* optional<T>::operator ->() const ; +T* optional<T>::operator ->() ;Requirements: *this is initialized.
Returns: A pointer to the contained value.
Throws: Nothing.
+Notes: If T is a reference type, the pointer is to the referenced object
Notes: The requirement is asserted via BOOST_ASSERT().
Example:
@@ -902,6 +1023,14 @@ T* optional<T (not a ref)>::operator ->() ; X x ; optional<X> opt (x); opt->mdata = 2 ; + +X& rx = x ; + +optional<X&> optr (rx); +optr->mdata = 4 ; + +assert ( x.mdata = 4 ) +
+optional<T (not a ref)> make_optional( T const& v )+++Returns: optional<T>(v) for the deduced type
+T
ofv
.Example:
+++template<class T> void foo ( optional<T> const& opt ) ; + +foo ( make_optional(1+1) ) ; // Creates an optional<int> +
+ +optional<T (not a ref)> make_optional( bool condition, T const& v )+++ +Returns: optional<T>(condition,v) for the deduced type
+T
ofv
.Example:
+++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"); +
+bool operator == ( optional<T> const& x, optional<T> const& y );Returns: If both x and y are initialied,
+If only x or y is initialized,(*x == *y)
. -If only x or y is initialized,false
. If both are uninitialized,true
. -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 -
+use equal_pointees() insteadExample:
T x(12); @@ -1012,14 +1170,12 @@ assert ( optX != optZ ) ;-Returns: If y is not initialized,
+If both x and y are initialized,false
. If y is initialized and x is not initialized,true
. -If both x and y are initialized,(*x < *y)
. -(*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 -
+use less_pointees() insteadExample:
+T x(12); @@ -1077,28 +1233,40 @@ assert ( optX != optZ ) ;Throws: Nothing.
++bool operator == ( optional<T> const& x, none_t n ); +bool operator != ( optional<T> const& x, none_t n ); +bool operator < ( optional<T> const& x, none_t n ); +bool operator > ( optional<T> const& x, none_t n ); +bool operator <= ( optional<T> const& x, none_t n ); +bool operator >= ( optional<T> const& x, none_t n ); +bool operator == ( none_t n, optional<T> const& y ); +bool operator != ( none_t n, optional<T> const& y ); +bool operator < ( none_t n, optional<T> const& y ); +bool operator > ( none_t n, optional<T> const& y ); +bool operator <= ( none_t n, optional<T> const& y ); +bool operator >= ( none_t n, optional<T> const& y ); +++Returns: The result obtained by replacing the argument 'n' by optional<T>().
+
void swap ( optional<T>& x, optional<T>& y );-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. -Effect: If both x and y are initialized, calls
swap(*x,*y)
using std::swap.
+If only one is initialized, say x, calls:y = *x; x = boost:none;
+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 ( T const& ) throws. -
-Notes: If both are initialized, swap(T&,T&) is used unqualified -but with std::swap introduced in scope.
+If only one is initialized, whatever T::T ( T const& ) throws. +
-If only one is initialized, T::~T() and T::T( T const& ) is called. -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( T const& ) 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>::operator=( T const& ).
-If only one is initialized, it has the same basic guarantee as optional<T>::reset( T const& ). -Example:
T x(12); @@ -1148,12 +1316,12 @@ void receive_async_message()optional<string> name ; if ( database.open() ) { - name.reset ( database.lookup(employer_name) ) ; + name = database.lookup(employer_name) ; } else { if ( can_ask_user ) - name.reset ( user.ask(employer_name) ) ; + name = user.ask(employer_name) ; } if ( name ) @@ -1174,7 +1342,7 @@ else print("employer's name not found!"); void clip_in_rect ( rect const& rect ) { .... - m_clipping_rect.reset ( rect ) ; // initialized here. + m_clipping_rect = rect ; // initialized here. } void draw ( canvas& cvs ) @@ -1218,15 +1386,16 @@ some operations are not available in this case:Converting assignment InPlace construction InPlace assignment -Value-access via pointer Also, even though optional<T&> treats it wrapped pseudo-object much as a real value, a true real reference is stored so aliasing will ocurr:
-
@@ -1254,8 +1423,7 @@ assert(a==b); b = 3 ; assert(ra!=b); // 'ra' is not rebound to 'b'- Copies of optional<T&> will copy the references but all these references +
- Copies of optional<T&> copies the reference, but all copied references will nonetheless reefer to the same object.
-- Value-access will actually provide access to the referenced object rather +
- Value-access provides access to the referenced object rather + than the reference itself.
+- Pointer-access provides a pointer to the referenced object rather than the reference itself.
Now, if you assign to an initialized optional<T&>, the effect is to -rebind to the new object instead of assigning the referee. This is unlike +
Now, if you assign to an initialized optional<T&>, the effect is to rebind to the new object instead of assigning the referee. This is unlike bare C++ references.
int a = 1 ; int b = 2 ; @@ -1309,6 +1477,13 @@ In such scenario, you can assign the value itself directly, as in:assert(!!opt); *opt=value;+
+ +none_t
++
+ +
In-Place Factories
@@ -1358,8 +1533,7 @@ public:A limitation of this method is that it doesn't scale well to wrapped objects with multiple constructors nor to generic code were the constructor overloads are unknown.
-The solution presented in this library is the family of InPlaceFactories and -TypedInPlaceFactories.
+The solution presented in this library is the family of InPlaceFactories and TypedInPlaceFactories.
@@ -1427,10 +1601,7 @@ public: W ( in_place(123,"hello") ) ; }
These factories are a family of classes which encapsulate an increasing number of arbitrary constructor parameters and supply a method to construct an object of a given type using those parameters at an address specified by the user via placement new.The factories are implemented in the headers: -in_place_factory.hpp and -typed_in_place_factory.hpp -
+The factories are implemented in the headers: in_place_factory.hpp and typed_in_place_factory.hpp
@@ -1440,9 +1611,8 @@ public: the maybe state represents a valid value, unlike the corresponding state of an uninitialized optional<bool>.
It should be carefully considered if an optional<bool> instead of a tribool is really needed -Second, optional<> provides an implicit conversion to bool. This conversion - refers to the initialization state and not to the contained value.
+
-Using optional<bool> can lead to subtle errors due to the implicit bool conversion:Second, optional<> provides a simple way to test initialization state: an implicit conversion to a type that evaluates as a 'bool' in a boolean context.
+Using optional<bool> can lead to subtle errors due to this implicit conversion:void foo ( bool v ) ; void bar() { @@ -1458,7 +1628,9 @@ void bar() integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile).
Exception Safety Guarantees
-Assignment and Reset:
+ +Assignment:
+IMPORTANT NOTE: This changed in 1.33.1 with respect to previous versions
Because of the current implementation (see Implementation Notes), all of the assignment methods:
@@ -1471,61 +1643,17 @@ of the assignment methods: 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())
+cannot offer any exception safety guarantee beyond that provided by
T::operator=( T const& )
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 ; +Provides the no-throw guarantee (assuming a no-throw T::~T()) becuse it only destroys the stored object.
- // 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 asswap(T&,T&)
when both optionals are initialized.
-If only one of the optionals is initialized, it gives the same basic exception guarantee asoptional<T>::reset( T const& )
(sinceoptional<T>::reset()
doesn't throw).
+If only one of the optionals is initialized, it gives the same exception guarantee asT::operator=( T const& )
(sinceoptional<T>::operator=( none_t )
doesn't throw).
If none of the optionals is initialized, it has no-throw guarantee since it is a no-op.
@@ -1539,14 +1667,11 @@ T is not required to be Implementation Notesoptional<T> is currently implemented - using a custom aligned storage facility built from
+ using a custom aligned storage facility built fromalignment_of
andtype_with_alignment
(both from Type Traits). - It uses a separate boolean flag to indicate the initialization state.
- Placement new with T's copy constructor and T's destructor - are explicitly used to initialize,copy and destroy optional values.
- As a result, T's default constructor is effectively by-passed, but the exception - guarantees are basic.
- It is planned to replace the current implementation with another with - stronger exception safety, such as a future boost::variant. alignment_of
andtype_with_alignment
(both from Type Traits). + It uses a separate boolean flag to indicate the initialization state. +Placement new with T's copy constructor and T's destructor + is explicitly used to initialize and destroy optional values. This allows T's default constructor to be effectively by-passed.
+If assignment is used and the lvalue optional is uninitialized, T's copy constructor is used. However, if it is already initialized, T's assignment operator is used. This prevents optional from offering any exception guarantee stronger than the one offered by the type T itself
@@ -1600,15 +1725,12 @@ T is not required to be -LICENSE_1_0.txt or copy at -www.boost.org/LICENSE_1_0.txt) +License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at www.boost.org/LICENSE_1_0.txt)Developed by Fernando Cacciola, the latest version of this file can be found at www.boost.org, and the boost -discussion lists
-