From 0fd45d73b100ccd6406edf4c98860084fc24cf1d Mon Sep 17 00:00:00 2001
From: Fernando Cacciola Returns: A reference to the contained value, if any, or Throws: Nothing. Example: Returns: A reference to the contained value (which can be itself a reference), if any, or Throws: Nothing. Example: Returns: The result obtained by replacing the argument 'n' by optional<T>(n). Returns: The result obtained by replacing the argument 'n' by optional<T>().
-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 ) ;
-
-
-
-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 = get_optional_value_or(opt,z);
-assert ( u == v ) ;
-assert ( u != z ) ;
-
-
-
T const& optional<T&>::operator*() const ;
T & optional<T&>::operator*();
@@ -967,6 +965,33 @@ assert ( *opt == v ) ;
+T const& optional<T>::get_value_or( T const& default) const ;
+T& optional<T>::get_value_or( T& default ) ;
+
+inline T const& get_optional_value_or ( optional<T> const& o, T const& default ) ;
+inline T& get_optional_value_or ( optional<T>& o, T& default ) ;
+
+
+
+
+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 = get_optional_value_or(opt,z);
+assert ( u == v ) ;
+assert ( u != z ) ;
+
+
+
T const* optional<T>::get_ptr() const ;
T* optional<T>::get_ptr() ;
@@ -1235,18 +1260,37 @@ assert ( optX != optZ ) ;
-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 );
+bool operator == ( optional<T> const& x, T const& n );
+bool operator != ( optional<T> const& x, T const& n );
+bool operator < ( optional<T> const& x, T const& n );
+bool operator > ( optional<T> const& x, T const& n );
+bool operator <= ( optional<T> const& x, T const& n );
+bool operator >= ( optional<T> const& x, T const& n );
+bool operator == ( T const& n, optional<T> const& y );
+bool operator != ( T const& n, optional<T> const& y );
+bool operator < ( T const& n, optional<T> const& y );
+bool operator > ( T const& n, optional<T> const& y );
+bool operator <= ( T const& n, optional<T> const& y );
+bool operator >= ( T const& n, optional<T> const& y );
+
+
+
+
+
+
+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 );
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:
+value, a true real reference is stored, thus aliasing can ocurr:int x = 1 ; int& rx = x ; optional<int&> ora ; -optional<int&> orb(x) ; +optional<int&> orb(rx) ; ora = orb ; // now 'ora' is bound to 'x' through 'rx' *ora = 2 ; // Changes value of 'x' through 'ora' assert(x==2); @@ -1418,7 +1462,7 @@ referenced object; it's value changes but the reference is never rebound. int& ra = a ; int b = 2 ; int& rb = b ; -ra = rb ; // Changes the value of 'a' to 'b' +ra = rb ; // Changes the VALUE of 'a' to that of 'b' assert(a==b); b = 3 ; assert(ra!=b); // 'ra' is not rebound to 'b' @@ -1444,45 +1488,68 @@ C++ references.
It is true that optional<U> strives to behave as much as possible as U does whenever it is initialized; but in the case when U is T&, doing so would result in inconsistent behavior w.r.t to the lvalue initialization state. -Imagine optional<T&> forwarding assignment to the referenced object (thus -changing the referenced object value but not rebinding), and consider the -following code :
-optional<int&> a = get(); - int x = 1 ; - int& rx = x ; - optional<int&> b(rx); - a = b ; +Consider the following code :
++int x = 1 ; +int& rx = x ; +void foo ( optional<int&> & outer ) +{ + optional<int&> b(rx); + outer = b ; +} ++What should the assignment to 'outer' do?
+
+If 'outer' is uninitialized, the answer is clear: it should bind to 'x' (so we now have +a second reference to 'x').
+But what if 'outer' is already initialized?
+The assignment could change the value of the +referenced object (whatever that is), but doing that would be inconsistent with the uninitialized case +and then you wouldn't be able to reason at compile time about all the references to x since +the appearance of a new reference to it would depend on wheter the lvalue ('outer') +is initialized or not.Arguably, if rebinding the reference to another object is wrong for your code, then is +likely that binding it for the fist time via assignment instead of intialization is also wrong. +In that case, you can always just assign the value to the referenced object directly via +the access operator
+*opt=value
.If rebinding is wrong but first-time binding +isn't (via assignment), you can always work around the rebinding semantics using a discriminator:
++if ( !opt ) + opt = value ; // first-time binding +else *opt = value ; // assign to referee without rebinding-What does the assignment do?
-
-If 'a' is uninitialized, the answer is clear: it binds to 'x' (we now have -another reference to 'x').
-But what if 'a' is already initialized? it would change the value of the -referenced object (whatever that is); which is inconsistent with the other -possible case.If optional<T&> would assign just like T& does, you would never be able to -use Optional's assignment without explicitly handling the previous -initialization state unless your code is capable of functioning whether after -the assignment, 'a' -aliases the same object as 'b' or not.
-That is, you would have to discriminate in order to be consistency.
-
-
-If in your code rebinding to another object is not an option, then is very -likely that binding for the fist time isn't either. In such case, assignment to -an uninitialized optional<T&> shall be prohibited. It is quite -possible that in such scenario the precondition that the lvalue must be already -initialized exist. If it doesn't, then binding for the first time is OK while -rebinding is not which is IMO -very unlikely.
-In such scenario, you can assign the value itself directly, as in:assert(!!opt); -*opt=value;
-none_t
-+
none_t and none
+optional<T> supports uninitialized states with a convenient syntax via a constant of +the implementation-defined type
+boost::none_t
, identified asboost::none
.Starting with Boost version 1.34.0, both
+boost::none_t
andboost::none
are +included inboost/none.hpp
, which is automatically included byboost/optional/optional.hpp
This contant is similar in purpose to NULL, except that is not a null pointer value. You can use it to initialize +an optional<T> instance, which has the same effect of a default constructor, and you can assign it which has the +effect of reseting the optional<T> instance. You can also use it in relational operators to make the predicate expression +more clear.
+Here are some typical examples:
++#include "boost/optional/optional.hpp" // boost/none.hpp is included automatically +boost::optional<int> foo ( int a ) +{ + return some_condition(a) ? boost::make_optional(a) : boost::none ; + + // NOTE: in real code you can just use this: make_optional(some_condition(a), a ) +} + +boost::optional<int> opt = boost::none ; + +if ( opt == boost::none ) + opt = foo(123); + +opt = boost::none ; + +
@@ -1725,7 +1792,7 @@ T is not required to be LICENSE_1_0.txt or copy at www.boost.org/LICENSE_1_0.txt)