diff --git a/doc/optional.html b/doc/optional.html index ac786ea..3d472ea 100644 --- a/doc/optional.html +++ b/doc/optional.html @@ -10,7 +10,7 @@

Header <boost/optional.hpp>

+HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp>

Contents

@@ -33,28 +33,28 @@ HREF="../../../boost/optional.hpp">boost/optional.hpp>

Motivation

-

Consider these functions which should return a value but which might not have +

Consider these functions which should return a value but which might not have a value to return:

(A) double sqrt(double n );
 (B) char get_async_input();
 (C) point polygon::get_any_point_effectively_inside();

There are different approaches to the issue of not having a value to return.

-

A typical approach is to consider the existence of a valid return value as - a postcondition, so that if the function cannot compute the value to return, - it has either undefined behavior (and can use asssert in a debug build) - or uses a runtime check and throws an exception if the postcondition is violated. - This is a reasonable choice for example, for function (A), because the - lack of a proper return value is directly related to an invalid parameter (out - of domain argument), so it is appropriate to require the callee to supply only +

A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use asssert in a debug build) + or uses a runtime check and throws an exception if the postcondition is violated. + This is a reasonable choice for example, for function (A), because the + lack of a proper return value is directly related to an invalid parameter (out + of domain argument), so it is appropriate to require the callee to supply only parameters in a valid domain for execution to continue normally.

-

However, function (B), because of its asynchronous nature, does not fail just +

However, function (B), because of its asynchronous nature, does not fail just because it can't find a value to return; so it is incorrect to consider - such a situation an error and assert or throw an exception. This function must - return, and somehow, must tell the callee that it is not returning a meaningful + such a situation an error and assert or throw an exception. This function must + return, and somehow, must tell the callee that it is not returning a meaningful value.

-

A similar situation occurs with function (C): it is conceptually an error to - ask a null-area polygon to return a point inside itself, but in many - applications, it is just impractical for performance reasons to treat this as +

A similar situation occurs with function (C): it is conceptually an error to + ask a null-area polygon to return a point inside itself, but in many + applications, it is just impractical for performance reasons to treat this as an error (because detecting that the polygon has no area might be too expensive to be required to be tested previously), and either an arbitrary point (typically at infinity) is returned, or some efficient way to tell the callee that there @@ -106,7 +106,7 @@ if ( p.second ) when a variable is declared as optional<T> and no initial value is given, the variable is formally uninitialized. A formally uninitialized optional object has conceptually no value at all and this situation can be tested at runtime. It is formally undefined behaviour - to try to access the value of an uninitialized optional. An uninitialized optional can be assigned a value, in which case its initialization state changes to initialized. Furthermore, given the formal + to try to access the value of an uninitialized optional. An uninitialized optional can be assigned a value, in which case its initialization state changes to initialized. Furthermore, given the formal treatment of initialization states in optional objects, it is even possible to reset an optional to uninitialized.

In C++ there is no formal notion of uninitialized objects, which means that objects always have an initial value even if indeterminate.
@@ -114,7 +114,7 @@ if ( p.second ) information to tell if an object has been effectively initialized.
One of the typical ways in which this has been historically dealt with is via a special value: EOF,npos,-1, etc... This is equivalent to adding - the special value to the set of possible values of a given type. This super set of + the special value to the set of possible values of a given type. This super set of T plus some nil_t—were nil_t is some stateless POD-can be modeled in modern languages as a discriminated union of T and nil_t. Discriminated unions are often called variants. A variant has a current type, @@ -128,13 +128,13 @@ if ( p.second ) the range of possible values adding an additional sentinel value with the special meaning of Nothing. However, this additional Nothing value is largely irrelevant for our purpose since our goal is to formalize the notion of uninitialized objects and, while a special extended value can be used to convey that meaning, it is not strictly neccesary in order to do so.

-

The observation made in the last paragraph about the irrelevant nature of the additional nil_t with respect to +

The observation made in the last paragraph about the irrelevant nature of the additional nil_t with respect to purpose of optional<T> suggests an alternative model: a container that either has a value of T or nothing.

-

As of this writting I don't know of any precedence 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 +

As of this writting I don't know of any precedence 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.

In any event, both the discriminated-union or the single-element container models serve as a conceptual ground for a class representing optional—i.e. possibly uninitialized—objects.
@@ -174,71 +174,71 @@ conceptually wrong but also impractical: it is not allowed to derive from a non-

We can draw from the purpose of optional<T> the required basic semantics:

-

Default Construction: To introduce a formally uninitialized wrapped +

Default Construction: To introduce a formally uninitialized wrapped object.

-

Direct Value Construction via copy: To introduce a formally +

Direct Value Construction via copy: To introduce a formally initialized wrapped object whose value is obtained as a copy of some object.

-

Deep Copy Construction: To obtain a different yet equivalent wrapped +

Deep Copy Construction: To obtain a different yet equivalent wrapped object.

-

Direct Value Assignment (upon initialized): To assign the wrapped object a value obtained +

Direct Value Assignment (upon initialized): To assign the wrapped object a value obtained as a copy of some object.

-

Direct Value Assignment (upon uninitialized): To initialize the wrapped object -with a value obtained +

Direct Value Assignment (upon uninitialized): To initialize the wrapped object +with a value obtained as a copy of some object.

-

Assignnment (upon initialized): To assign the wrapped object a value obtained as a copy +

Assignnment (upon initialized): To assign the wrapped object a value obtained as a copy of another wrapper's object.

-

Assignnment (upon uninitialized): To initialize the wrapped object -with value obtained as a copy +

Assignnment (upon uninitialized): To initialize the wrapped object +with value obtained as a copy of another wrapper's object.

-

Deep Relational Operations (when supported by the type T): To compare -wrapped object values taking into account the presence of uninitialized +

Deep Relational Operations (when supported by the type T): To compare +wrapped object values taking into account the presence of uninitialized operands.

Value access: To unwrap the wrapped object.

-

Initialization state query: To determine if the object is formally +

Initialization state query: To determine if the object is formally initialized or not.

-

Swap: To exchange wrapper's objects. (with whatever exception safety +

Swap: To exchange wrapper's objects. (with whatever exception safety guarantiees are provided by T's swap).

-

De-initialization: To release the wrapped object (if any) and leave +

De-initialization: To release the wrapped object (if any) and leave the wrapper in the uninitialized state.

-

Additional operations are useful, such as converting constructors and -converting assignments, in-place construction and assignment, and safe value +

Additional operations are useful, such as converting constructors and +converting assignments, in-place construction and assignment, and safe value access via a pointer to the wrapped object or null.

The Interface:

-

Since the purpose of optional is to allow us to use objects with a formal -uninitialized additional state, the interface could try to follow the interface -of the underlying T type as much as possible. In order to choose the proper +

Since the purpose of optional is to allow us to use objects with a formal +uninitialized additional state, the interface could try to follow the interface +of the underlying T type as much as possible. In order to choose the proper degree of adoption of the native T interface, the following must be noted:
-Even if all the operations supported by an instance of type T are defined for -the entire range of values for such a type, an optional<T> extends such a set of -values with a new value for which most (otherwise valid) operations are not +Even if all the operations supported by an instance of type T are defined for +the entire range of values for such a type, an optional<T> extends such a set of +values with a new value for which most (otherwise valid) operations are not defined in terms of T.
-Furthermore, since optional<T> itself is merely a T wrapper (modeling a T -supertype), any attempt to define such operations upon uninitialized optionals +Furthermore, since optional<T> itself is merely a T wrapper (modeling a T +supertype), any attempt to define such operations upon uninitialized optionals will be totally artificial w.r.t. T.
-This library chooses an interface which follows from T's interface only for -those operations which are well defined (w.r.t the type T) even if any of the -operands are uninitialized. These operations include: construction, +This library chooses an interface which follows from T's interface only for +those operations which are well defined (w.r.t the type T) even if any of the +operands are uninitialized. These operations include: construction, copy-construction, assignment, swap and relational operations.
-For the value access operations, which are undefined (w.r.t the type T) when the -operand is uninitialized, a different interface is choosen (which will be +For the value access operations, which are undefined (w.r.t the type T) when the +operand is uninitialized, a different interface is choosen (which will be explained next).
-Also, the presence of the possibly uninitialized state requires additional +Also, the presence of the possibly uninitialized state requires additional operations not provided by T itself which are supported by a special interface.

-

Lexically-hinted Value Access in the presence of possibly untitialized +

Lexically-hinted Value Access in the presence of possibly untitialized optional objects: The operators * and ->

A relevant feature of a pointer is that it can have a null pointer value. This is a special value which is used to indicate that the @@ -248,7 +248,7 @@ optional objects: The operators * and -> for handling optional objects because all you have to do to refer to a value which you don't really have is to use a null pointer value of the appropriate type. Pointers have been used for decades—from the days of C APIs to modern C++ libraries—to - refer to optional (that is, possibly inexistent) objects; particularly + refer to optional (that is, possibly inexistent) objects; particularly as optional arguments to a function, but also quite often as optional data members.

The possible presence of a null pointer value makes the operations that access the pointee's value possibly undefined, therefore, expressions which use dereference @@ -282,10 +282,10 @@ them. The problem resides in the shallow-copy of pointer semantics: if you need concept incarnated by pointers.

Optional<T> as a model of OptionalPointee

-

For value access operations optional<> uses operators * and -> to lexically -warn about the possibliy uninitialized state appealing to the familiar pointer +

For value access operations optional<> uses operators * and -> to lexically +warn about the possibliy uninitialized state appealing to the familiar pointer semantics w.r.t. to null pointers.
-However, it is particularly important to note that optional<> objects are not pointers. optional<> +However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a pointer.

For instance, optional<> has not shallow-copy so does not alias: two different optionals never refer to the same value unless T itself is an reference (but my have equivalent values).
@@ -296,7 +296,7 @@ is not, and does not model, a pointer
. As a result, you might be able to replace optional<T> by T* on some situations but not always. Specifically, on generic code written for both, you cannot use relational operators directly, and must use the template functions - equal_pointees() and + equal_pointees() and less_pointees() instead.


@@ -315,30 +315,30 @@ class optional optional ( detail::none_t ) ; - optional ( T const& v ) ; + optional ( T const& v ) ; - optional ( optional const& rhs ) ; + optional ( optional const& rhs ) ; template<class U> explicit optional ( optional<U> const& rhs ) ; - + template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; - + template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; optional& operator = ( detail::none_t ) ; - - optional& operator = ( T const& v ) ; + + optional& operator = ( T const& v ) ; optional& operator = ( optional const& rhs ) ; template<class U> optional& operator = ( optional<U> const& rhs ) ; template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; - + template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; - - T const& get() const ; - T& get() ; + + T const& get() const ; + T& get() ; T const* operator ->() const ; T* operator ->() ; @@ -352,9 +352,9 @@ class optional operator unspecified-bool-type() const ; bool operator!() const ; - + deprecated methods - + void reset() ; (deprecated) void reset ( T const& ) ; (deprecated) bool is_initialized() const ; (deprecated) @@ -396,18 +396,18 @@ template<class T> inline void swap( optional<T>& x, optional<T>

NOTES:

-

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 +

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 +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 +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.

-

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 +

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.


@@ -435,8 +435,8 @@ assert ( !def ) ;

Notes:

T's default constructor is not called.
-The -expression boost::none denotes an instance of boost::detail::none_t that can be +The +expression boost::none denotes an instance of boost::detail::none_t that can be used as the parameter.

Example:

@@ -471,7 +471,7 @@ assert ( *opt == v ) ;
optional<T&>::optional( T ref )

Effect: Directly-Constructs an optional.

-

Postconditions: *this is initialized and its value is an +

Postconditions: *this is initialized and its value is an instance of an internal type wrapping the reference 'ref'.

Throws: Nothing.

Example:

@@ -525,8 +525,8 @@ assert ( init2 == init ) ; and its value is a copy of the internal wrapper holding the references in rhs; else *this is uninitialized.

Throws: Nothing.

-

Notes: If rhs is initialized, the internal wrapper will be -copied and just like true references, both *this and rhs will +

Notes: If rhs is initialized, the internal wrapper will be +copied and just like true references, both *this and rhs will referr to the same object (will alias).

Example:

@@ -581,13 +581,13 @@ assert( *y == 123 ) ;
template<TypedInPlaceFactory> explicit optional<T (not a ref)>::optional( TypedInPlaceFactory const& f );
-

Effect: Constructs an optional with a value of T obtained from +

Effect: Constructs an optional with a value of T obtained from the factory.

-

Postconditions:  *this is initialized and its value is +

Postconditions:  *this is initialized and its value is directly given from the factory 'f' (i.e, the value is not copied).

Throws: Whatever the T constructor called by the factory throws.

Notes: See In-Place Factories

-

Exception Safety: Exceptions can only be thrown during the call to the +

Exception Safety: Exceptions can only be thrown during the call to the T constructor used by the factory; in that case, this constructor has no effect.

@@ -863,7 +863,7 @@ assert ( !!opt ) ;
bool optional<T>::is_initialized() const ;
-

Returns: true is the optional is initialized, false +

Returns: true is the optional is initialized, false otherwise.

Throws: Nothing.

@@ -921,7 +921,7 @@ assert ( optX != optZ ) ;
bool operator < ( optional<T> const& x, optional<T> const& y );
-

Returns: If y is not initialized, false. +

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).

@@ -991,8 +991,8 @@ assert ( optX != optZ ) ;
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();
@@ -1105,7 +1105,7 @@ else print("employer's name not found!"); }; -

Bypassing expensive unnecesary default construction

+

Bypassing expensive unnecesary default construction

class ExpensiveCtor { ... } ;
 class Fred
 {
@@ -1118,10 +1118,10 @@ class Fred
 

Optional references

-

This library allow the template parameter T to be of reference type: T&, and +

This library allow the template parameter T to be of reference type: T&, and to some extent, T const&.

-

However, since references are not real objects some restrictions apply and +

However, since references are not real objects some restrictions apply and some operations are not available in this case:

    @@ -1131,13 +1131,13 @@ some operations are not available in this case:

  • InPlace assignment
  • Value-access via pointer
-

Also, even though optional<T&> treats it wrapped pseudo-object much as a real +

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:

    -
  • Copies of optional<T&> will copy the references but all these references +
  • Copies of optional<T&> will copy the references but all these references will nonetheless refeer to the same object.
  • -
  • Value-access will actually provide access to the referenced object rather +
  • Value-access will actually provide access to the referenced object rather than the reference itself.
@@ -1145,52 +1145,52 @@ value, a true real reference is stored so aliasing will ocurr:

In-Place Factories

-One of the typical problems with wrappers and containers is that their -interfaces usually provide an operation to initialize or assign the contained -object as a copy of some other object. This not only requires the underlying -type to be Copy Constructible, but also requires the existence of a fully +One of the typical problems with wrappers and containers is that their +interfaces usually provide an operation to initialize or assign the contained +object as a copy of some other object. This not only requires the underlying +type to be Copy Constructible, but also requires the existence of a fully constructed object, often temporary, just to follow the copy from:

-
struct X 
+
struct X
 {
-  X ( int, std:::string ) ; 
+  X ( int, std:::string ) ;
 } ;
class W
 {
   X wrapped_ ;
-  
+
 public:
 
-  W ( X const& x ) : wrapped_(x) {}  
+  W ( X const& x ) : wrapped_(x) {}
 } ;
void foo()
 {
   // Temporary object created.
-  W ( X(123,"hello") ) ; 
+  W ( X(123,"hello") ) ;
 }
 
-

A solution to this problem is to support direct construction of the contained +

A solution to this problem is to support direct construction of the contained object right in the container's storage.
-In this shceme, the user only needs to supply the arguments to the constructor +In this shceme, the user only needs to supply the arguments to the constructor to use in the wrapped object construction.

class W
 {
   X wrapped_ ;
-  
+
 public:
 
-  W ( X const& x ) : wrapped_(x) {}  
+  W ( X const& x ) : wrapped_(x) {}
   W ( int a0, std::string a1) : wrapped_(a0,a1) {}
 } ;
void foo()
 {
   // Wrapped object constructed in-place
   // No temporary created.
-  W (123,"hello") ; 
+  W (123,"hello") ;
 }
 

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 familiy of InPlaceFactories and +

The solution presented in this library is the familiy of InPlaceFactories and TypedInPlaceFactories.
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 @@ -1200,29 +1200,29 @@ parameters at an address specified by the user via placement new.

class TypedInPlaceFactory2 { A0 m_a0 ; A1 m_a1 ; - + public: TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {} - void construct ( void* p ) { new (p) T(m_a0,m_a1) ; } + void construct ( void* p ) { new (p) T(m_a0,m_a1) ; } } ;

A wrapper class aware of this can use it as:

class W
 {
   X wrapped_ ;
-  
+
 public:
 
-  W ( X const& x ) : wrapped_(x) {}  
+  W ( X const& x ) : wrapped_(x) {}
   W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
 } ;
void foo()
 {
   // Wrapped object constructed in-place via a TypedInPlaceFactory.
   // No temporary created.
-  W ( TypedInPlaceFactory2<X,int,std::string&rt;(123,"hello")) ; 
+  W ( TypedInPlaceFactory2<X,int,std::string&rt;(123,"hello")) ;
 }
 

The factories are divided in two groups:

    @@ -1233,35 +1233,35 @@ public:

    This library provides an overloaded set of helper template functions to construct these factories without requiring unnecessary template parameters:

    -
    template<class A0,...,class AN> 
    +
    template<class A0,...,class AN>
     InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ;
     
    -template<class T,class A0,...,class AN> 
    +template<class T,class A0,...,class AN>
     TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ;

    In-place factories can be used generically by the wrapper and user as follows:

    class W
     {
       X wrapped_ ;
    -  
    +
     public:
     
    -  W ( X const& x ) : wrapped_(x) {}  
    -  
    +  W ( X const& x ) : wrapped_(x) {}
    +
       template
       W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }
    -  
    +
     } ;
    void foo()
     {
       // Wrapped object constructed in-place via a InPlaceFactory.
       // No temporary created.
    -  W ( in_place(123,"hello") ) ; 
    +  W ( in_place(123,"hello") ) ;
     }
     

    The factories are implemented in the headers: -in_place_factory.hpp and -typed_in_place_factory.hpp +in_place_factory.hpp and +typed_in_place_factory.hpp


    @@ -1272,7 +1272,7 @@ 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 +

    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:

    void foo ( bool v ) ;
    @@ -1291,7 +1291,7 @@ integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't
     
     

    Exception Safety Guarantees

    Assignment and Reset:

    -

    Because of the current implementation (see Implementation Notes), all +

    Because of the current implementation (see Implementation Notes), all of the assignment methods:

    • optional<T>::operator= ( optional<T> const& ) @@ -1299,9 +1299,9 @@ of the assignment methods:

    • optional<T>::operator= ( T const& )
    • template<class U> optional<T>::operator= ( optional<U> const& )
    • -
    • template<class InPlaceFactory> optional<T>::operator= ( +
    • template<class InPlaceFactory> optional<T>::operator= ( InPlaceFactory const& )
    • -
    • template<class TypedInPlaceFactory> optional<T>::operator= ( +
    • template<class TypedInPlaceFactory> optional<T>::operator= ( TypedInPlaceFactory const& )
    • optional<T>:::reset ( T const&)
    @@ -1363,7 +1363,7 @@ If none of the optionals is initialized, it has no-throw guarantee since it is a

    Type requirements

    -

    In general, T must be Copy Constructible and have a no-throw destructor. The copy-constructible requirement is not needed +

    In general, T must be Copy Constructible and have a no-throw destructor. The copy-constructible requirement is not needed if InPlaceFactories are used.
    T is not required to be Default Constructible

    @@ -1407,39 +1407,40 @@ T is not required to be +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 +HREF="http://www.boost.org">www.boost.org, and the boost discussion lists