| 1 | <!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd"> |
|---|
| 2 | |
|---|
| 3 | <HTML> |
|---|
| 4 | |
|---|
| 5 | <HEAD> |
|---|
| 6 | <meta http-equiv="Content-Language" content="en-us"> |
|---|
| 7 | <meta name="GENERATOR" content="Microsoft FrontPage 5.0"> |
|---|
| 8 | <meta name="ProgId" content="FrontPage.Editor.Document"> |
|---|
| 9 | <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"> |
|---|
| 10 | <LINK REL="stylesheet" TYPE="text/css" HREF="../../../boost.css"> |
|---|
| 11 | <TITLE>Header </TITLE> |
|---|
| 12 | </HEAD> |
|---|
| 13 | |
|---|
| 14 | <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080"> |
|---|
| 15 | <H2><IMG SRC="../../../boost.png" WIDTH="276" HEIGHT="86">Header <<A |
|---|
| 16 | HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp</A>> </H2> |
|---|
| 17 | |
|---|
| 18 | <H2>Contents</H2> |
|---|
| 19 | <DL CLASS="page-index"> |
|---|
| 20 | <DT><A HREF="#mot">Motivation</A></DT> |
|---|
| 21 | <DT><A HREF="#dev">Development</A></DT> |
|---|
| 22 | <DT><A HREF="#synopsis">Synopsis</A></DT> |
|---|
| 23 | <DT><A HREF="#semantics">Semantics</A></DT> |
|---|
| 24 | <DT><A HREF="#examples">Examples</A></DT> |
|---|
| 25 | <DT><A HREF="#ref">Optional references</A></DT> |
|---|
| 26 | <DT><A HREF="#refassign">Rebinding semantics for assignment of optional references</A></DT> |
|---|
| 27 | <DT><A HREF="#inplace">In-Place Factories</A></DT> |
|---|
| 28 | <DT><A HREF="#bool">A note about optional<bool></A></DT> |
|---|
| 29 | <DT><A HREF="#exsafety">Exception Safety Guarantees</A></DT> |
|---|
| 30 | <DT><A HREF="#requirements">Type requirements</A></DT> |
|---|
| 31 | <DT><A HREF="#impl">Implementation Notes</A></DT> |
|---|
| 32 | <DT><A HREF="#porta">Dependencies and Portability</A></DT> |
|---|
| 33 | <DT><A HREF="#credits">Acknowledgment</A></DT> |
|---|
| 34 | </DL> |
|---|
| 35 | |
|---|
| 36 | <HR> |
|---|
| 37 | |
|---|
| 38 | <H2><A NAME="mot"></A>Motivation</H2> |
|---|
| 39 | |
|---|
| 40 | <P>Consider these functions which should return a value but which might not have |
|---|
| 41 | a value to return:</P> |
|---|
| 42 | <pre>(A) double sqrt(double n ); |
|---|
| 43 | (B) char get_async_input(); |
|---|
| 44 | (C) point polygon::get_any_point_effectively_inside();</pre> |
|---|
| 45 | <P>There are different approaches to the issue of not having a value to return.</P> |
|---|
| 46 | <P>A typical approach is to consider the existence of a valid return value as |
|---|
| 47 | a postcondition, so that if the function cannot compute the value to return, |
|---|
| 48 | it has either undefined behavior (and can use assert in a debug build) |
|---|
| 49 | or uses a runtime check and throws an exception if the postcondition is violated. |
|---|
| 50 | This is a reasonable choice for example, for function (A), because the |
|---|
| 51 | lack of a proper return value is directly related to an invalid parameter (out |
|---|
| 52 | of domain argument), so it is appropriate to require the callee to supply only |
|---|
| 53 | parameters in a valid domain for execution to continue normally.</P> |
|---|
| 54 | <P>However, function (B), because of its asynchronous nature, does not fail just |
|---|
| 55 | because it can't find a value to return; so it is incorrect to consider |
|---|
| 56 | such a situation an error and assert or throw an exception. This function must |
|---|
| 57 | return, and somehow, must tell the callee that it is not returning a meaningful |
|---|
| 58 | value.</P> |
|---|
| 59 | <P>A similar situation occurs with function (C): it is conceptually an error to |
|---|
| 60 | ask a <i>null-area</i> polygon to return a point inside itself, but in many |
|---|
| 61 | applications, it is just impractical for performance reasons to treat this as |
|---|
| 62 | an error (because detecting that the polygon has no area might be too expensive |
|---|
| 63 | to be required to be tested previously), and either an arbitrary point (typically |
|---|
| 64 | at infinity) is returned, or some efficient way to tell the callee that there |
|---|
| 65 | is no such point is used.</P> |
|---|
| 66 | <P>There are various mechanisms to let functions communicate that the returned |
|---|
| 67 | value is not valid. One such mechanism, which is quite common since it has zero |
|---|
| 68 | or negligible overhead, is to use a special value which is reserved to communicate |
|---|
| 69 | this. Classical examples of such special values are EOF, string::npos, points |
|---|
| 70 | at infinity, etc...</P> |
|---|
| 71 | <P>When those values exist, i.e. the return type can hold all meaningful values |
|---|
| 72 | <i>plus</i> the <i>signal</i> value, this mechanism is quite appropriate and |
|---|
| 73 | well known. Unfortunately, there are cases when such values do not exist. In |
|---|
| 74 | these cases, the usual alternative is either to use a wider type, such as 'int' |
|---|
| 75 | in place of 'char'; or a compound type, such as std::pair<point,bool>. |
|---|
| 76 | </P> |
|---|
| 77 | <P>Returning a std::pair<T,bool>, thus attaching a boolean flag to the result |
|---|
| 78 | which indicates if the result is meaningful, has the advantage that can be turned |
|---|
| 79 | into a consistent idiom since the first element of the pair can be whatever |
|---|
| 80 | the function would conceptually return. For example, the last two functions |
|---|
| 81 | could have the following interface:</P> |
|---|
| 82 | <pre>std::pair<char,bool> get_async_input(); |
|---|
| 83 | std::pair<point,bool> polygon::get_any_point_effectively_inside();</pre> |
|---|
| 84 | <p>These functions use a consistent interface for dealing with possibly inexistent |
|---|
| 85 | results:</p> |
|---|
| 86 | <pre>std::pair<point,bool> p = poly.get_any_point_effectively_inside(); |
|---|
| 87 | if ( p.second ) |
|---|
| 88 | flood_fill(p.first); |
|---|
| 89 | </pre> |
|---|
| 90 | |
|---|
| 91 | <P>However, not only is this quite a burden syntactically, it is also error |
|---|
| 92 | prone since the user can easily use the function result (first element of the |
|---|
| 93 | pair) without ever checking if it has a valid value.</P> |
|---|
| 94 | <P>Clearly, we need a better idiom.</P> |
|---|
| 95 | |
|---|
| 96 | <H2><A NAME="dev"></A>Development</H2> |
|---|
| 97 | |
|---|
| 98 | <h3><u>The models:</u></h3> |
|---|
| 99 | <P>In C++, we can <i>declare</i> an object (a variable) of type T, and we can give this variable |
|---|
| 100 | an <i>initial value</i> (through an <i>initializer</i>. (c.f. 8.5)).<br> |
|---|
| 101 | When a declaration includes a non-empty initializer (an initial value is given), it is said that |
|---|
| 102 | the object has been <i><b>initialized</b></i>.<br> |
|---|
| 103 | If the declaration uses an empty initializer (no initial value is given), |
|---|
| 104 | and neither default nor value initialization applies, it is said that the object is |
|---|
| 105 | <i><b>uninitialized</b></i>. Its actual value exist but has an |
|---|
| 106 | <i>indeterminate initial value</i> (c.f. 8.5.9).<br> |
|---|
| 107 | <code>optional<T></code> intends to formalize the notion of initialization |
|---|
| 108 | (or lack of it) |
|---|
| 109 | allowing a program to test whether an object has been initialized and stating that access to |
|---|
| 110 | the value of an uninitialized object is undefined behavior. That is, |
|---|
| 111 | when a variable is declared as optional<T> and no initial value is given, |
|---|
| 112 | the variable is <i>formally</i> uninitialized. A formally uninitialized optional object has conceptually |
|---|
| 113 | no value at all and this situation can be tested at runtime. It is formally <i> |
|---|
| 114 | undefined behavior</i> |
|---|
| 115 | to try to access the value of an uninitialized optional. An uninitialized optional can be <i>assigned</i> a value, in which case its initialization state changes to initialized. Furthermore, given the formal |
|---|
| 116 | treatment of initialization states in optional objects, it is even possible to reset an optional to <i>uninitialized</i>.</P> |
|---|
| 117 | <P>In C++ there is no formal notion of uninitialized objects, which |
|---|
| 118 | means that objects always have an initial value even if indeterminate.<br> |
|---|
| 119 | As discussed on the previous section, this has a drawback because you need additional |
|---|
| 120 | information to tell if an object has been effectively initialized.<br> |
|---|
| 121 | One of the typical ways in which this has been historically |
|---|
| 122 | dealt with is via a special value: EOF,npos,-1, etc... This is equivalent to adding |
|---|
| 123 | the special value to the set of possible values of a given type. This super set of |
|---|
| 124 | T plus some <i>nil_t</i>—were nil_t is some stateless POD-can be modeled in modern |
|---|
| 125 | languages as a <b>discriminated union</b> of <code>T</code> and <code>nil_t</code>. |
|---|
| 126 | Discriminated unions are often called <i>variants</i>. A variant has a <i>current type</i>, |
|---|
| 127 | which in our case is either <code>T</code> or <code>nil_t</code>.<br> |
|---|
| 128 | Using the <a href="../../../doc/html/variant.html">Boost.Variant</a> library, this model can be implemented |
|---|
| 129 | in terms of <code>boost::variant<T,nil_t></code>.<br> |
|---|
| 130 | There is precedence for a discriminated union as a model for an optional value: the |
|---|
| 131 | <a href="http://www.haskell.org/"><u>Haskell</u></a> <b>Maybe</b> built-in type constructor. |
|---|
| 132 | Thus, a discriminated union <code>T+nil_t</code> serves as a conceptual foundation.</p> |
|---|
| 133 | <p>A <code>variant<T,nil_t></code> follows naturally from the traditional idiom of extending |
|---|
| 134 | the range of possible values adding an additional sentinel value with the special meaning of <i>Nothing. </i> |
|---|
| 135 | However, this additional <i>Nothing</i> value is largely irrelevant for our purpose |
|---|
| 136 | since our goal is to formalize the notion of uninitialized objects and, while a special extended value <i>can</i> be used to convey that meaning, it is not strictly |
|---|
| 137 | necessary in order to do so.</p> |
|---|
| 138 | <p>The observation made in the last paragraph about the irrelevant nature of the additional <code>nil_t</code> with respect to |
|---|
| 139 | <u>purpose</u> of optional<T> suggests |
|---|
| 140 | an alternative model: a <i>container</i> that either has a value of T or nothing. |
|---|
| 141 | </p> |
|---|
| 142 | <p>As of this writing I don't know of any precedence for a variable-size fixed-capacity (of 1) |
|---|
| 143 | stack-based container model for optional values, yet I believe this is the consequence of |
|---|
| 144 | the lack of practical implementations of such a container rather than an inherent shortcoming |
|---|
| 145 | of the container model.</p> |
|---|
| 146 | <p>In any event, both the discriminated-union or the single-element container models serve as a conceptual |
|---|
| 147 | ground for a class representing optional—i.e. possibly uninitialized—objects.<br> |
|---|
| 148 | For instance, these models show the <i>exact</i> semantics required for a wrapper of optional values:</p> |
|---|
| 149 | <p>Discriminated-union:</p> |
|---|
| 150 | <blockquote> |
|---|
| 151 | <li><b>deep-copy</b> semantics: copies of the variant implies copies of the value.</li> |
|---|
| 152 | <li><b>deep-relational</b> semantics: comparisons between variants matches both current types and values</li> |
|---|
| 153 | <li>If the variant's current type is T, it is modeling an <i>initialized</i> optional.</li> |
|---|
| 154 | <li>If the variant's current type is not T, it is modeling an <i>uninitialized</i> optional.</li> |
|---|
| 155 | <li>Testing if the variant's current type is T models testing if the optional is initialized</li> |
|---|
| 156 | <li>Trying to extract a T from a variant when its current type is not T, models the undefined |
|---|
| 157 | behavior |
|---|
| 158 | of trying to access the value of an uninitialized optional</li> |
|---|
| 159 | </blockquote> |
|---|
| 160 | <p>Single-element container:</p> |
|---|
| 161 | <blockquote> |
|---|
| 162 | <li><b>deep-copy</b> semantics: copies of the container implies copies of the value.</li> |
|---|
| 163 | <li><b>deep-relational</b> semantics: comparisons between containers compare container size and if match, contained value</li> |
|---|
| 164 | <li>If the container is not empty (contains an object of type T), it is modeling an <i>initialized</i> optional.</li> |
|---|
| 165 | <li>If the container is empty, it is modeling an <i>uninitialized</i> optional.</li> |
|---|
| 166 | <li>Testing if the container is empty models testing if the optional is initialized</li> |
|---|
| 167 | <li>Trying to extract a T from an empty container models the undefined behavior |
|---|
| 168 | of trying to access the value of an uninitialized optional</li> |
|---|
| 169 | </blockquote> |
|---|
| 170 | |
|---|
| 171 | <h3><u>The semantics:</u></h3> |
|---|
| 172 | <p>Objects of type <code>optional<T></code> are intended to be used in places where objects of type T would |
|---|
| 173 | but which might be uninitialized. Hence, <code>optional<T></code>'s purpose is to formalize the |
|---|
| 174 | additional possibly uninitialized state.<br> |
|---|
| 175 | From the perspective of this role, <code>optional<T></code> can have the same operational semantics of T |
|---|
| 176 | plus the additional semantics corresponding to this special state.<br> |
|---|
| 177 | As such, <code>optional<T></code> could be thought of as a <i>supertype</i> of T. Of course, |
|---|
| 178 | we can't do that in C++, so we need to compose the desired semantics using a different mechanism.<br> |
|---|
| 179 | Doing it the other way around, that is, making <code>optional<T></code> a <i>subtype</i> of T is not only |
|---|
| 180 | conceptually wrong but also impractical: it is not allowed to derive from a non-class type, such as a |
|---|
| 181 | built-in type.</p> |
|---|
| 182 | |
|---|
| 183 | <p>We can draw from the purpose of optional<T> the required basic semantics:</p> |
|---|
| 184 | |
|---|
| 185 | <blockquote> |
|---|
| 186 | <p><b>Default Construction:</b> To introduce a formally uninitialized wrapped |
|---|
| 187 | object.</p> |
|---|
| 188 | |
|---|
| 189 | <p><b>Direct Value Construction via copy:</b> To introduce a formally |
|---|
| 190 | initialized wrapped object whose value is obtained as a copy of some object.</p> |
|---|
| 191 | |
|---|
| 192 | <p><b>Deep Copy Construction:</b> To obtain a new yet equivalent wrapped |
|---|
| 193 | object.</p> |
|---|
| 194 | |
|---|
| 195 | <p><b>Direct Value Assignment (upon initialized):</b> To assign a value to the wrapped object.</p> |
|---|
| 196 | |
|---|
| 197 | <p><b>Direct Value Assignment (upon uninitialized):</b> To initialize the wrapped object |
|---|
| 198 | with a value obtained |
|---|
| 199 | as a copy of some object.</p> |
|---|
| 200 | |
|---|
| 201 | <p><b>Assignment (upon initialized):</b> To assign to the wrapped object the value |
|---|
| 202 | of another wrapped object.</p> |
|---|
| 203 | |
|---|
| 204 | <p><b>Assignment (upon uninitialized):</b> To initialize the wrapped object |
|---|
| 205 | with value of another wrapped object.</p> |
|---|
| 206 | |
|---|
| 207 | <p><b>Deep Relational Operations (when supported by the type T):</b> To compare |
|---|
| 208 | wrapped object values taking into account the presence of uninitialized |
|---|
| 209 | states.</p> |
|---|
| 210 | |
|---|
| 211 | <p><b>Value access:</b> To unwrap the wrapped object.</p> |
|---|
| 212 | |
|---|
| 213 | <p><b>Initialization state query:</b> To determine if the object is formally |
|---|
| 214 | initialized or not.</p> |
|---|
| 215 | |
|---|
| 216 | <p><b>Swap:</b> To exchange wrapped objects. (with whatever exception safety |
|---|
| 217 | guarantees are provided by T's swap).</p> |
|---|
| 218 | |
|---|
| 219 | <p><b>De-initialization:</b> To release the wrapped object (if any) and leave |
|---|
| 220 | the wrapper in the uninitialized state.</p> |
|---|
| 221 | |
|---|
| 222 | </blockquote> |
|---|
| 223 | |
|---|
| 224 | <p>Additional operations are useful, such as converting constructors and |
|---|
| 225 | converting assignments, in-place construction and assignment, and safe value |
|---|
| 226 | access via a pointer to the wrapped object or null.</p> |
|---|
| 227 | <h3><u>The Interface:</u></h3> |
|---|
| 228 | <p>Since the purpose of optional is to allow us to use objects with a formal |
|---|
| 229 | uninitialized additional state, the interface could try to follow the interface |
|---|
| 230 | of the underlying T type as much as possible. In order to choose the proper |
|---|
| 231 | degree of adoption of the native T interface, the following must be noted: <br> |
|---|
| 232 | Even if all the operations supported by an instance of type T are defined for |
|---|
| 233 | the entire range of values for such a type, an optional<T> extends such a set of |
|---|
| 234 | values with a new value for which most (otherwise valid) operations are not |
|---|
| 235 | defined in terms of T.<br> |
|---|
| 236 | Furthermore, since optional<T> itself is merely a T wrapper (modeling a T |
|---|
| 237 | supertype), any attempt to define such operations upon uninitialized optionals |
|---|
| 238 | will be totally artificial w.r.t. T.<br> |
|---|
| 239 | This library chooses an interface which follows from T's interface only for |
|---|
| 240 | those operations which are well defined (w.r.t the type T) even if any of the |
|---|
| 241 | operands are uninitialized. These operations include: construction, |
|---|
| 242 | copy-construction, assignment, swap and relational operations.<br> |
|---|
| 243 | For the value access operations, which are undefined (w.r.t the type T) when the |
|---|
| 244 | operand is uninitialized, a different interface is chosen (which will be |
|---|
| 245 | explained next).<br> |
|---|
| 246 | Also, the presence of the possibly uninitialized state requires additional |
|---|
| 247 | operations not provided by T itself which are supported by a special interface.</p> |
|---|
| 248 | <h3>Lexically-hinted Value Access in the presence of possibly untitialized |
|---|
| 249 | optional objects: The operators * and -></h3> |
|---|
| 250 | <p>A relevant feature of a pointer is that it can have a <b>null |
|---|
| 251 | pointer value</b>. This is a <i>special</i> value which is used to indicate that the |
|---|
| 252 | pointer is not referring to any object at all. In other words, null pointer |
|---|
| 253 | values convey the notion of inexistent objects.</P> |
|---|
| 254 | <P>This meaning of the null pointer value allowed pointers to became a <i>de facto</i> standard |
|---|
| 255 | for handling optional objects because all you have to do to refer to a value which you |
|---|
| 256 | don't really have is to use a null pointer value of the appropriate type. |
|---|
| 257 | Pointers have been used for decades—from the days of C APIs to modern C++ libraries—to |
|---|
| 258 | <i>refer</i> to optional (that is, possibly inexistent) objects; particularly |
|---|
| 259 | as optional arguments to a function, but also quite often as optional data members.</P> |
|---|
| 260 | <P>The possible presence of a null pointer value makes the operations that access the |
|---|
| 261 | pointee's value possibly undefined, therefore, expressions which use dereference |
|---|
| 262 | and access operators, such as: <code>( *p = 2 )</code> and <code>( p->foo())</code>, |
|---|
| 263 | implicitly convey the notion of optionality, and this information is tied to |
|---|
| 264 | the <i>syntax</i> of the expressions. That is, the presence of operators * and -> tell by |
|---|
| 265 | themselves—without any additional context—that the expression will be undefined unless |
|---|
| 266 | the implied pointee actually exist.</P> |
|---|
| 267 | <P>Such a <i>de facto</i> idiom for referring to optional objects can be formalized in the form of a |
|---|
| 268 | concept: the <a href="../../utility/OptionalPointee.html">OptionalPointee</a> concept.<br> |
|---|
| 269 | This concept captures the syntactic usage of operators *, -> and conversion to bool to convey |
|---|
| 270 | the notion of optionality.</P> |
|---|
| 271 | <P>However, pointers are good to <u>refer</u> to optional objects, but not particularly good |
|---|
| 272 | to handle the optional objects in all other respects, such as initializing or moving/copying |
|---|
| 273 | them. The problem resides in the shallow-copy of pointer semantics: if you need to |
|---|
| 274 | effectively move or copy the object, pointers alone are not enough. The problem |
|---|
| 275 | is that copies of pointers do not imply copies of pointees. For example, as |
|---|
| 276 | was discussed in the motivation, pointers alone cannot be used to return optional |
|---|
| 277 | objects from a function because the object must move outside from the function and |
|---|
| 278 | into the caller's context.<br> |
|---|
| 279 | A solution to the shallow-copy problem that is often used is to resort to dynamic |
|---|
| 280 | allocation and use a smart pointer to automatically handle the details of this. |
|---|
| 281 | For example, if a function is to optionally return an object X, it can use shared_ptr<X> |
|---|
| 282 | as the return value. However, this requires dynamic allocation of X. If X is |
|---|
| 283 | a built-in or small POD, this technique is very poor in terms of required resources. |
|---|
| 284 | Optional objects are essentially values so it is very convenient to be able to use automatic |
|---|
| 285 | storage and deep-copy semantics to manipulate optional values just as we do with ordinary |
|---|
| 286 | values. Pointers do not have this semantics, so are inappropriate for the initialization and |
|---|
| 287 | transport of optional values, yet are quite convenient for handling the access to the |
|---|
| 288 | possible undefined value because of the idiomatic aid present in the OptionalPointee |
|---|
| 289 | concept incarnated by pointers. |
|---|
| 290 | </p> |
|---|
| 291 | <h4>Optional<T> as a model of OptionalPointee</h4> |
|---|
| 292 | <P>For value access operations optional<> uses operators * and -> to lexically |
|---|
| 293 | warn about the possibly uninitialized state appealing to the familiar pointer |
|---|
| 294 | semantics w.r.t. to null pointers.<br> |
|---|
| 295 | <u><b>However, it is particularly important to note that optional<> objects are not pointers. optional<> |
|---|
| 296 | is not, and does not model, a pointer</b></u><b>.</b> |
|---|
| 297 | <P>For instance, optional<> does not have shallow-copy so does not alias: two different optionals |
|---|
| 298 | never refer to the <i>same</i> value unless T itself is a reference (but may have <i>equivalent</i> values).<br> |
|---|
| 299 | The difference between an optional<T> and a pointer must be kept in mind, particularly |
|---|
| 300 | because the semantics of relational operators are different: since optional<T> |
|---|
| 301 | is a value-wrapper, relational operators are deep: they compare optional values; |
|---|
| 302 | but relational operators for pointers are shallow: they do not compare pointee values.<br> |
|---|
| 303 | As a result, you might be able to replace optional<T> by T* on some situations but |
|---|
| 304 | not always. Specifically, on generic code written for both, you cannot use relational |
|---|
| 305 | operators directly, and must use the template functions |
|---|
| 306 | <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> and |
|---|
| 307 | <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead. |
|---|
| 308 | <HR> |
|---|
| 309 | |
|---|
| 310 | <H2><A NAME="synopsis">Synopsis</A></H2> |
|---|
| 311 | |
|---|
| 312 | <PRE>namespace boost { |
|---|
| 313 | |
|---|
| 314 | template<class T> |
|---|
| 315 | class optional |
|---|
| 316 | { |
|---|
| 317 | public : |
|---|
| 318 | |
|---|
| 319 | <i><u>(If T is of reference type, the parameters and results by reference are by value)</u></i> |
|---|
| 320 | |
|---|
| 321 | optional () ; |
|---|
| 322 | |
|---|
| 323 | optional ( none_t ) ; |
|---|
| 324 | |
|---|
| 325 | optional ( T const& v ) ; |
|---|
| 326 | |
|---|
| 327 | optional ( optional const& rhs ) ; |
|---|
| 328 | |
|---|
| 329 | template<class U> explicit optional ( optional<U> const& rhs ) ; |
|---|
| 330 | |
|---|
| 331 | template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; |
|---|
| 332 | |
|---|
| 333 | template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; |
|---|
| 334 | |
|---|
| 335 | optional& operator = ( none_t ) ; |
|---|
| 336 | |
|---|
| 337 | optional& operator = ( T const& v ) ; |
|---|
| 338 | |
|---|
| 339 | optional& operator = ( optional const& rhs ) ; |
|---|
| 340 | |
|---|
| 341 | template<class U> optional& operator = ( optional<U> const& rhs ) ; |
|---|
| 342 | |
|---|
| 343 | template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; |
|---|
| 344 | |
|---|
| 345 | template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; |
|---|
| 346 | |
|---|
| 347 | T const& get() const ; |
|---|
| 348 | T& get() ; |
|---|
| 349 | |
|---|
| 350 | T const* operator ->() const ; |
|---|
| 351 | T* operator ->() ; |
|---|
| 352 | |
|---|
| 353 | T const& operator *() const ; |
|---|
| 354 | T& operator *() ; |
|---|
| 355 | |
|---|
| 356 | T const* get_ptr() const ; |
|---|
| 357 | T* get_ptr() ; |
|---|
| 358 | |
|---|
| 359 | operator <i>unspecified-bool-type</i>() const ; |
|---|
| 360 | |
|---|
| 361 | bool operator!() const ; |
|---|
| 362 | |
|---|
| 363 | <i><u>deprecated methods</u></i> |
|---|
| 364 | |
|---|
| 365 | void reset() ; (deprecated) |
|---|
| 366 | void reset ( T const& ) ; (deprecated) |
|---|
| 367 | bool is_initialized() const ; (deprecated) |
|---|
| 368 | |
|---|
| 369 | } ; |
|---|
| 370 | |
|---|
| 371 | template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; |
|---|
| 372 | |
|---|
| 373 | template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; |
|---|
| 374 | |
|---|
| 375 | template<class T> inline bool operator < ( optional<T> const& x, optional<T> const& y ) ; |
|---|
| 376 | |
|---|
| 377 | template<class T> inline bool operator > ( optional<T> const& x, optional<T> const& y ) ; |
|---|
| 378 | |
|---|
| 379 | template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; |
|---|
| 380 | |
|---|
| 381 | template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; |
|---|
| 382 | |
|---|
| 383 | template<class T> inline T const& get ( optional<T> const& opt ) ; |
|---|
| 384 | |
|---|
| 385 | template<class T> inline T& get ( optional<T> & opt ) ; |
|---|
| 386 | |
|---|
| 387 | template<class T> inline T const* get ( optional<T> const* opt ) ; |
|---|
| 388 | |
|---|
| 389 | template<class T> inline T* get ( optional<T>* opt ) ; |
|---|
| 390 | |
|---|
| 391 | template<class T> inline T const* get_pointer ( optional<T> const& opt ) ; |
|---|
| 392 | |
|---|
| 393 | template<class T> inline T* get_pointer ( optional<T> & opt ) ; |
|---|
| 394 | |
|---|
| 395 | template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; |
|---|
| 396 | |
|---|
| 397 | } // namespace boost |
|---|
| 398 | </PRE> |
|---|
| 399 | |
|---|
| 400 | <HR> |
|---|
| 401 | |
|---|
| 402 | <h2><A NAME="semantics">Detailed Semantics</a></h2> |
|---|
| 403 | |
|---|
| 404 | <p><b><u>NOTES: </u></b></p> |
|---|
| 405 | |
|---|
| 406 | <p><b>Because T might be of reference type, in the sequel, those entries whose |
|---|
| 407 | semantic depends on T being of reference type or not will be distinguished using |
|---|
| 408 | the following convention:<br> |
|---|
| 409 | If the entry reads: optional<T (not a ref)>, the description corresponds only to |
|---|
| 410 | the case where T is not of reference type.<br> |
|---|
| 411 | If the entry reads: optional<T&>, the description corresponds only to the case |
|---|
| 412 | where T is of reference type. <br> |
|---|
| 413 | If the entry reads: optional<T>, the description is the same for both cases.</b></p> |
|---|
| 414 | |
|---|
| 415 | <p><i>The following section contains various assert() which are used only to |
|---|
| 416 | show the postconditions as sample code. It is not implied that the type T must |
|---|
| 417 | support each particular expression but that if the expression is supported, the |
|---|
| 418 | implied condition holds.</i></p> |
|---|
| 419 | |
|---|
| 420 | <hr> |
|---|
| 421 | |
|---|
| 422 | <pre>optional<T>::optional();</pre> |
|---|
| 423 | <blockquote> |
|---|
| 424 | <p><b>Effect:</b> Default-Constructs an <b>optional</b>.</p> |
|---|
| 425 | <p><b>Postconditions:</b> <b>*this</b> is <u>uninitialized</u>.</p> |
|---|
| 426 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 427 | <p><b>Notes:</b> T's default constructor <u><i>is not</i></u> called.</p> |
|---|
| 428 | <p><b>Example:</b></p> |
|---|
| 429 | <blockquote> |
|---|
| 430 | <pre>optional<T> def ; |
|---|
| 431 | assert ( !def ) ;</pre> |
|---|
| 432 | </blockquote> |
|---|
| 433 | </blockquote> |
|---|
| 434 | |
|---|
| 435 | <HR> |
|---|
| 436 | |
|---|
| 437 | <pre>optional<T>::optional( none_t );</pre> |
|---|
| 438 | <blockquote> |
|---|
| 439 | <p><b>Effect:</b> Constructs an <b>optional </b>uninitialized.</p> |
|---|
| 440 | <p><b>Postconditions:</b> <b>*this</b> is <u>uninitialized</u>.</p> |
|---|
| 441 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 442 | <p><b>Notes:</b></p> |
|---|
| 443 | <blockquote> |
|---|
| 444 | <p>T's default constructor <u><i>is not</i></u> called.<br> |
|---|
| 445 | The |
|---|
| 446 | expression <code>boost::none</code> denotes an instance of <code>boost::none_t</code> that can be |
|---|
| 447 | used as the parameter.</p> |
|---|
| 448 | </blockquote> |
|---|
| 449 | <p><b>Example:</b></p> |
|---|
| 450 | <blockquote> |
|---|
| 451 | <pre>#include <boost/none.hpp></pre> |
|---|
| 452 | <pre>optional<T> n(none) ; |
|---|
| 453 | assert ( !n ) ;</pre> |
|---|
| 454 | </blockquote> |
|---|
| 455 | </blockquote> |
|---|
| 456 | |
|---|
| 457 | <HR> |
|---|
| 458 | |
|---|
| 459 | <pre>optional<T <i>(not a ref)</i>>::optional( T const& v )</pre> |
|---|
| 460 | <blockquote> |
|---|
| 461 | <p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p> |
|---|
| 462 | <!-- TemplateName: general/sy_footer_inc.isml --> |
|---|
| 463 | <p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is a <i>copy</i> of 'v'.</p> |
|---|
| 464 | <p><b>Throws:</b> Whatever T::T( T const& ) throws.</p> |
|---|
| 465 | <p><b>Notes: </b> T::T( T const& ) is called.</p> |
|---|
| 466 | <p><b>Exception Safety:</b> Exceptions can only be thrown during T::T( T const& ); |
|---|
| 467 | in that case, this constructor has no effect. |
|---|
| 468 | </p> |
|---|
| 469 | <p><b>Example:</b></p> |
|---|
| 470 | <blockquote> |
|---|
| 471 | <pre>T v; |
|---|
| 472 | optional<T> opt(v); |
|---|
| 473 | assert ( *opt == v ) ;</pre> |
|---|
| 474 | </blockquote> |
|---|
| 475 | </blockquote> |
|---|
| 476 | |
|---|
| 477 | <HR> |
|---|
| 478 | |
|---|
| 479 | <pre>optional<T&>::optional( T& ref )</pre> |
|---|
| 480 | <blockquote> |
|---|
| 481 | <p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p> |
|---|
| 482 | <p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is an |
|---|
| 483 | instance of an internal type wrapping the reference 'ref'.</p> |
|---|
| 484 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 485 | <p><b>Example:</b></p> |
|---|
| 486 | <blockquote> |
|---|
| 487 | <pre>T v; |
|---|
| 488 | T& vref = v ; |
|---|
| 489 | optional<T&> opt(vref); |
|---|
| 490 | assert ( *opt == v ) ; |
|---|
| 491 | ++ v ; // mutate referee |
|---|
| 492 | assert (*opt == v); </pre> |
|---|
| 493 | </blockquote> |
|---|
| 494 | </blockquote> |
|---|
| 495 | |
|---|
| 496 | <HR> |
|---|
| 497 | |
|---|
| 498 | <pre>optional<T <i>(not a ref)</i>>::optional( optional const& rhs );</pre> |
|---|
| 499 | <blockquote> |
|---|
| 500 | <p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p> |
|---|
| 501 | <p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized |
|---|
| 502 | and its value is a <i>copy</i> of the value of <b>rhs</b>; else <b>*this</b> |
|---|
| 503 | is uninitialized.</p> |
|---|
| 504 | <p><b>Throws:</b> Whatever T::T( T const& ) throws.</p> |
|---|
| 505 | <p><b>Notes:</b> If <b>rhs</b> is initialized, T::T(T const& ) is called.</p> |
|---|
| 506 | <p><b>Exception Safety:</b> Exceptions can only be thrown during T::T( T const& ); |
|---|
| 507 | in that case, this constructor has no effect. |
|---|
| 508 | </p> |
|---|
| 509 | <p><b>Example:</b></p> |
|---|
| 510 | <blockquote> |
|---|
| 511 | <pre>optional<T> uninit ; |
|---|
| 512 | assert (!uninit); |
|---|
| 513 | |
|---|
| 514 | optional<T> uinit2 ( uninit ) ; |
|---|
| 515 | assert ( uninit2 == uninit ); |
|---|
| 516 | |
|---|
| 517 | optional<T> init( T(2) ); |
|---|
| 518 | assert ( *init == T(2) ) ; |
|---|
| 519 | |
|---|
| 520 | optional<T> init2 ( init ) ; |
|---|
| 521 | assert ( init2 == init ) ; |
|---|
| 522 | </pre> |
|---|
| 523 | |
|---|
| 524 | </blockquote> |
|---|
| 525 | </blockquote> |
|---|
| 526 | |
|---|
| 527 | <HR> |
|---|
| 528 | |
|---|
| 529 | <pre>optional<T&>::optional( optional const& rhs );</pre> |
|---|
| 530 | <blockquote> |
|---|
| 531 | <p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p> |
|---|
| 532 | <p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized |
|---|
| 533 | and its value is another reference to the same object referenced by <b>*rhs</b>; else <b>*this</b> |
|---|
| 534 | is uninitialized.</p> |
|---|
| 535 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 536 | <p><b>Notes:</b> If <b>rhs</b> is initialized, both <b>*this</b> and <b>*rhs</b> will |
|---|
| 537 | reefer to the same object<b> </b>(they alias).</p> |
|---|
| 538 | <p><b>Example:</b></p> |
|---|
| 539 | <blockquote> |
|---|
| 540 | <pre>optional<T&> uninit ; |
|---|
| 541 | assert (!uninit); |
|---|
| 542 | |
|---|
| 543 | optional<T&> uinit2 ( uninit ) ; |
|---|
| 544 | assert ( uninit2 == uninit ); |
|---|
| 545 | |
|---|
| 546 | T v = 2 ; T& ref = v ; |
|---|
| 547 | optional<T> init(ref); |
|---|
| 548 | assert ( *init == v ) ; |
|---|
| 549 | |
|---|
| 550 | optional<T> init2 ( init ) ; |
|---|
| 551 | assert ( *init2 == v ) ; |
|---|
| 552 | |
|---|
| 553 | v = 3 ; |
|---|
| 554 | |
|---|
| 555 | assert ( *init == 3 ) ; |
|---|
| 556 | assert ( *init2 == 3 ) ; |
|---|
| 557 | |
|---|
| 558 | |
|---|
| 559 | </pre> |
|---|
| 560 | |
|---|
| 561 | </blockquote> |
|---|
| 562 | </blockquote> |
|---|
| 563 | |
|---|
| 564 | <HR> |
|---|
| 565 | |
|---|
| 566 | <pre>template<U> explicit optional<T <i>(not a ref)</i>>::optional( optional<U> const& rhs );</pre> |
|---|
| 567 | <blockquote> |
|---|
| 568 | <p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p> |
|---|
| 569 | <p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized |
|---|
| 570 | and its value is a <i>copy</i> of the value of <b>rhs</b> <i>converted</i> |
|---|
| 571 | to type T; else <b>*this</b> is uninitialized. |
|---|
| 572 | </p> |
|---|
| 573 | <p><b>Throws:</b> Whatever T::T( U const& ) throws.</p> |
|---|
| 574 | <p><b>Notes:</b> T::T( U const& ) is called if <b>rhs</b> is initialized, which requires |
|---|
| 575 | a valid conversion from U to T. |
|---|
| 576 | </p> |
|---|
| 577 | <p><b>Exception Safety:</b> Exceptions can only be thrown during T::T( U const& ); |
|---|
| 578 | in that case, this constructor has no effect. |
|---|
| 579 | </p> |
|---|
| 580 | <p><b>Example:</b></p> |
|---|
| 581 | <blockquote> |
|---|
| 582 | |
|---|
| 583 | <pre>optional<double> x(123.4); |
|---|
| 584 | assert ( *x == 123.4 ) ; |
|---|
| 585 | |
|---|
| 586 | optional<int> y(x) ; |
|---|
| 587 | assert( *y == 123 ) ; |
|---|
| 588 | </pre> |
|---|
| 589 | </blockquote> |
|---|
| 590 | </blockquote> |
|---|
| 591 | |
|---|
| 592 | <HR> |
|---|
| 593 | |
|---|
| 594 | <pre>template<<i>InPlaceFactory</i>> explicit optional<T <i>(not a ref)</i>>::optional( <i>InPlaceFactory</i> const& f );</pre> |
|---|
| 595 | |
|---|
| 596 | <pre>template<<i>TypedInPlaceFactory</i>> explicit optional<T <i>(not a ref)</i>>::optional( <i>TypedInPlaceFactory</i> const& f );</pre> |
|---|
| 597 | <blockquote> |
|---|
| 598 | <p><b>Effect:</b> Constructs an <b>optional</b> with a value of T obtained from |
|---|
| 599 | the factory.</p> |
|---|
| 600 | <p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is |
|---|
| 601 | <i>directly given</i> from the factory 'f' (i.e., the value<u> is not copied</u>).</p> |
|---|
| 602 | <p><b>Throws:</b> Whatever the T constructor called by the factory throws.</p> |
|---|
| 603 | <p><b>Notes:</b> See <A HREF="#inplace">In-Place Factories</A></p> |
|---|
| 604 | <p><b>Exception Safety:</b> Exceptions can only be thrown during the call to the |
|---|
| 605 | T constructor used by the factory; |
|---|
| 606 | in that case, this constructor has no effect. |
|---|
| 607 | </p> |
|---|
| 608 | <p><b>Example:</b></p> |
|---|
| 609 | <blockquote> |
|---|
| 610 | |
|---|
| 611 | <pre>class C { C ( char, double, std::string ) ; } ; |
|---|
| 612 | |
|---|
| 613 | C v('A',123.4,"hello"); |
|---|
| 614 | |
|---|
| 615 | optional<C> x( in_place ('A', 123.4, "hello") ); // InPlaceFactory used |
|---|
| 616 | optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used |
|---|
| 617 | |
|---|
| 618 | assert ( *x == v ) ; |
|---|
| 619 | assert ( *y == v ) ; |
|---|
| 620 | |
|---|
| 621 | </pre> |
|---|
| 622 | </blockquote> |
|---|
| 623 | </blockquote> |
|---|
| 624 | |
|---|
| 625 | <HR> |
|---|
| 626 | |
|---|
| 627 | <pre>optional& optional<T <i>(not a ref)</i>>::operator= ( T const& rhs ) ;</pre> |
|---|
| 628 | <blockquote> |
|---|
| 629 | <p><b>Effect:</b> Assigns the value 'rhs' to an <b>optional</b>.</p> |
|---|
| 630 | <p><b>Postconditions:</b> <b>*this</b> is initialized |
|---|
| 631 | and its value is a <i>copy</i> of <b>rhs.</b></p> |
|---|
| 632 | <p><b>Throws:</b> Whatever T::operator=( T const& ) or T::T(T const&) throws.</p> |
|---|
| 633 | <p><b>Notes:</b> If <b>*this</b> was initialized, T's assignment operator is |
|---|
| 634 | used, otherwise, its copy-constructor is used.</p> |
|---|
| 635 | <p><b>Exception Safety:</b> In the event of an exception, the initialization |
|---|
| 636 | state of <b>*this</b> is unchanged and its value unspecified as far as optional |
|---|
| 637 | is concerned (it is up to T's operator=()) [If <b>*this</b> is initially |
|---|
| 638 | uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left |
|---|
| 639 | properly uninitialized]</p> |
|---|
| 640 | <p><b>Example:</b></p> |
|---|
| 641 | <blockquote> |
|---|
| 642 | <pre>T x; |
|---|
| 643 | optional<T> def ; |
|---|
| 644 | optional<T> opt(x) ; |
|---|
| 645 | |
|---|
| 646 | T y; |
|---|
| 647 | def = y ; |
|---|
| 648 | assert ( *def == y ) ; |
|---|
| 649 | opt = y ; |
|---|
| 650 | assert ( *opt == y ) ;</pre> |
|---|
| 651 | </blockquote> |
|---|
| 652 | </blockquote> |
|---|
| 653 | |
|---|
| 654 | <HR> |
|---|
| 655 | |
|---|
| 656 | <pre>optional<T&>& optional<T&>::operator= ( T& const& rhs ) ;</pre> |
|---|
| 657 | <blockquote> |
|---|
| 658 | <p><b>Effect:</b> (Re)binds thee wrapped reference.</p> |
|---|
| 659 | <p><b>Postconditions:</b> <b>*this</b> is initialized |
|---|
| 660 | and it references the same object referenced by <b>rhs.</b></p> |
|---|
| 661 | <p><b>Notes:</b> If <b>*this</b> was initialized, is is <i>rebound</i> to the |
|---|
| 662 | new object. See <A HREF="#refassign">here</a> for details on this behavior.</p> |
|---|
| 663 | <p><b>Example:</b></p> |
|---|
| 664 | <blockquote> |
|---|
| 665 | <pre>int a = 1 ; |
|---|
| 666 | int b = 2 ; |
|---|
| 667 | T& ra = a ; |
|---|
| 668 | T& rb = b ; |
|---|
| 669 | optional<int&> def ; |
|---|
| 670 | optional<int&> opt(ra) ; |
|---|
| 671 | |
|---|
| 672 | def = rb ; // binds 'def' to 'b' through 'rb' |
|---|
| 673 | assert ( *def == b ) ; |
|---|
| 674 | *def = a ; // changes the value of 'b' to a copy of the value of 'a' |
|---|
| 675 | assert ( b == a ) ; |
|---|
| 676 | int c = 3; |
|---|
| 677 | int& rc = c ; |
|---|
| 678 | opt = rc ; // REBINDS to 'c' through 'rc' |
|---|
| 679 | c = 4 ; |
|---|
| 680 | assert ( *opt == 4 ) ; |
|---|
| 681 | </pre> |
|---|
| 682 | </blockquote> |
|---|
| 683 | </blockquote> |
|---|
| 684 | |
|---|
| 685 | <HR> |
|---|
| 686 | |
|---|
| 687 | <pre>optional& optional<T <i>(not a ref)</i>>::operator= ( optional const& rhs ) ;</pre> |
|---|
| 688 | <blockquote> |
|---|
| 689 | <p><b>Effect:</b> Assigns another <b>optional</b> to an <b>optional</b>.</p> |
|---|
| 690 | <p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized |
|---|
| 691 | and its value is a <i>copy</i> of the value of <b>rhs</b>; else <b>*this</b> |
|---|
| 692 | is uninitialized. |
|---|
| 693 | </p> |
|---|
| 694 | <p><b>Throws:</b> Whatever T::operator( T const&) or T::T( T const& ) throws.</p> |
|---|
| 695 | <p><b>Notes:</b> If both<b> *this</b> and <b>rhs</b> are initially initialized, |
|---|
| 696 | T's <i>assignment</i> <i>operator</i> is used. If <b>*this</b> is initially initialized but <b> |
|---|
| 697 | rhs</b> is uninitialized, T's <i>destructor</i> is called. If <b>*this</b> is initially |
|---|
| 698 | uninitialized but rhs is initialized, T's <i>copy constructor</i> is called. |
|---|
| 699 | </p> |
|---|
| 700 | <p><b>Exception Safety:</b> In the event of an exception, the initialization |
|---|
| 701 | state of <b>*this</b> is unchanged and its value unspecified as far as optional |
|---|
| 702 | is concerned (it is up to T's operator=()) [If <b>*this</b> is initially |
|---|
| 703 | uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left |
|---|
| 704 | properly uninitialized]</p> |
|---|
| 705 | <p><b>Example:</b></p> |
|---|
| 706 | <blockquote> |
|---|
| 707 | <pre>T v; |
|---|
| 708 | optional<T> opt(v); |
|---|
| 709 | optional<T> def ; |
|---|
| 710 | |
|---|
| 711 | opt = def ; |
|---|
| 712 | assert ( !def ) ; |
|---|
| 713 | // previous value (copy of 'v') destroyed from within 'opt'. |
|---|
| 714 | |
|---|
| 715 | </pre> |
|---|
| 716 | </blockquote> |
|---|
| 717 | </blockquote> |
|---|
| 718 | |
|---|
| 719 | <HR> |
|---|
| 720 | |
|---|
| 721 | <pre>optional<T&> & optional<T&>::operator= ( optional<T&> const& rhs ) ;</pre> |
|---|
| 722 | <blockquote> |
|---|
| 723 | <p><b>Effect:</b> (Re)binds thee wrapped reference.</p> |
|---|
| 724 | <p><b>Postconditions:</b> If <b>*rhs</b> is initialized, *<b>this</b> is initialized |
|---|
| 725 | and it references the same object referenced by <b>*rhs</b>; otherwise, <b>*this</b> |
|---|
| 726 | is uninitialized (and references no object).</p> |
|---|
| 727 | <p><b>Notes:</b> If <b>*this</b> was initialized and so is <b>*rhs</b>, <b>this</b> |
|---|
| 728 | is is <i>rebound</i> to the new object. See <A HREF="#refassign">here</a> for details on this |
|---|
| 729 | behavior.</p> |
|---|
| 730 | <p><b>Example:</b></p> |
|---|
| 731 | <blockquote> |
|---|
| 732 | <pre>int a = 1 ; |
|---|
| 733 | int b = 2 ; |
|---|
| 734 | T& ra = a ; |
|---|
| 735 | T& rb = b ; |
|---|
| 736 | optional<int&> def ; |
|---|
| 737 | optional<int&> ora(ra) ; |
|---|
| 738 | optional<int&> orb(rb) ; |
|---|
| 739 | |
|---|
| 740 | def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb' |
|---|
| 741 | assert ( *def == b ) ; |
|---|
| 742 | *def = ora ; // changes the value of 'b' to a copy of the value of 'a' |
|---|
| 743 | assert ( b == a ) ; |
|---|
| 744 | int c = 3; |
|---|
| 745 | int& rc = c ; |
|---|
| 746 | optional<int&> orc(rc) ; |
|---|
| 747 | ora = orc ; // REBINDS ora to 'c' through 'rc' |
|---|
| 748 | c = 4 ; |
|---|
| 749 | assert ( *ora == 4 ) ; |
|---|
| 750 | </pre> |
|---|
| 751 | </blockquote> |
|---|
| 752 | </blockquote> |
|---|
| 753 | |
|---|
| 754 | <HR> |
|---|
| 755 | |
|---|
| 756 | <pre>template<U> optional& optional<T <i>(not a ref)</i>>::operator= ( optional<U> const& rhs ) ;</pre> |
|---|
| 757 | <blockquote> |
|---|
| 758 | <p><b>Effect:</b> Assigns another <i>convertible</i> <b>optional</b> to an <b>optional</b>.</p> |
|---|
| 759 | <p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized |
|---|
| 760 | and its value is a <i>copy</i> of the value of <b>rhs</b> <i>converted</i> |
|---|
| 761 | to type T; else <b>*this</b> is uninitialized. |
|---|
| 762 | </p> |
|---|
| 763 | <p><b>Throws:</b> Whatever T::operator=( U const& ) or T::T( U const& ) throws.</p> |
|---|
| 764 | <p><b>Notes:</b> If both<b> *this</b> and <b>rhs</b> are initially initialized, |
|---|
| 765 | T's <i>assignment</i> <i>operator</i> (from U) is used. If <b>*this</b> is initially initialized but <b> |
|---|
| 766 | rhs</b> is uninitialized, T's <i>destructor</i> is called. If <b>*this</b> is initially |
|---|
| 767 | uninitialized but rhs is initialized, T's <i>converting constructor</i> (from U) is called. |
|---|
| 768 | </p> |
|---|
| 769 | <p><b>Exception Safety:</b> In the event of an exception, the initialization |
|---|
| 770 | state of <b>*this</b> is unchanged and its value unspecified as far as optional |
|---|
| 771 | is concerned (it is up to T's operator=()) [If <b>*this</b> is initially |
|---|
| 772 | uninitialized and T's <i>converting constructor</i> fails, <b>*this</b> is left |
|---|
| 773 | properly uninitialized]</p> |
|---|
| 774 | <p><b>Example:</b></p> |
|---|
| 775 | <blockquote> |
|---|
| 776 | <pre>T v; |
|---|
| 777 | optional<T> opt0(v); |
|---|
| 778 | optional<U> opt1; |
|---|
| 779 | |
|---|
| 780 | opt1 = opt0 ; |
|---|
| 781 | assert ( *opt1 == static_cast<U>(v) ) ; |
|---|
| 782 | </pre> |
|---|
| 783 | </blockquote> |
|---|
| 784 | </blockquote> |
|---|
| 785 | |
|---|
| 786 | <HR> |
|---|
| 787 | <pre>void optional<T <i>(not a ref)</i>>::reset( T const& v ) ;</pre> |
|---|
| 788 | <blockquote> |
|---|
| 789 | <p><b>Deprecated:</b> same as operator= ( T const& v) ;</p> |
|---|
| 790 | </blockquote> |
|---|
| 791 | |
|---|
| 792 | <HR> |
|---|
| 793 | <pre>void optional<T>::reset() ;</pre> |
|---|
| 794 | <blockquote> |
|---|
| 795 | <p><b>Deprecated: </b>Same as operator=( detail::none_t );</p> |
|---|
| 796 | </blockquote> |
|---|
| 797 | |
|---|
| 798 | <HR> |
|---|
| 799 | |
|---|
| 800 | |
|---|
| 801 | <pre>T const& optional<T <i>(not a ref)</i>>::operator*() const ; |
|---|
| 802 | T& optional<T<i> (not a ref)</i>>::operator*();</pre> |
|---|
| 803 | |
|---|
| 804 | <pre>T const& optional<T <i>(not a ref)</i>>::get() const ; |
|---|
| 805 | T& optional<T <i>(not a ref)</i>>::get() ; |
|---|
| 806 | |
|---|
| 807 | inline T const& get ( optional<T<i> (not a ref)</i>> const& ) ; |
|---|
| 808 | inline T& get ( optional<T <i>(not a ref)</i>> &) ; |
|---|
| 809 | </pre> |
|---|
| 810 | <blockquote> |
|---|
| 811 | <p><b>Requirements: *this</b> is initialized</p> |
|---|
| 812 | <p><b>Returns:</b> A reference to the contained value</p> |
|---|
| 813 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 814 | <p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p> |
|---|
| 815 | <p><b>Example:</b></p> |
|---|
| 816 | <blockquote> |
|---|
| 817 | <pre>T v ; |
|---|
| 818 | optional<T> opt ( v ); |
|---|
| 819 | T const& u = *opt; |
|---|
| 820 | assert ( u == v ) ; |
|---|
| 821 | T w ; |
|---|
| 822 | *opt = w ; |
|---|
| 823 | assert ( *opt == w ) ; |
|---|
| 824 | </pre> |
|---|
| 825 | </blockquote> |
|---|
| 826 | <pre></pre> |
|---|
| 827 | </blockquote> |
|---|
| 828 | |
|---|
| 829 | <HR> |
|---|
| 830 | |
|---|
| 831 | |
|---|
| 832 | <pre>T const& optional<T&>::operator*() const ; |
|---|
| 833 | T & optional<T<i>&</i>>::operator*();</pre> |
|---|
| 834 | |
|---|
| 835 | <pre>T const& optional<T&>::get() const ; |
|---|
| 836 | T& optional<T&>::get() ; |
|---|
| 837 | |
|---|
| 838 | inline T const& get ( optional<T<i>&</i>> const& ) ; |
|---|
| 839 | inline T& get ( optional<T&> &) ; |
|---|
| 840 | </pre> |
|---|
| 841 | <blockquote> |
|---|
| 842 | <p><b>Requirements: *this</b> is initialized</p> |
|---|
| 843 | <p><b>Returns:</b> <u>The</u> reference contained.</p> |
|---|
| 844 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 845 | <p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p> |
|---|
| 846 | <p><b>Example:</b></p> |
|---|
| 847 | <blockquote> |
|---|
| 848 | <pre>T v ; |
|---|
| 849 | T& vref = v ; |
|---|
| 850 | optional<T&> opt ( vref ); |
|---|
| 851 | T const& vref2 = *opt; |
|---|
| 852 | assert ( vref2 == v ) ; |
|---|
| 853 | ++ v ; |
|---|
| 854 | assert ( *opt == v ) ;</pre> |
|---|
| 855 | </blockquote> |
|---|
| 856 | </blockquote> |
|---|
| 857 | |
|---|
| 858 | <HR> |
|---|
| 859 | |
|---|
| 860 | <pre>T const* optional<T <i>(not a ref)</i>>::get_ptr() const ; |
|---|
| 861 | T* optional<T <i>(not a ref)</i>>::get_ptr() ; |
|---|
| 862 | |
|---|
| 863 | inline T const* get_pointer ( optional<T <i>(not a ref)</i>> const& ) ; |
|---|
| 864 | inline T* get_pointer ( optional<T <i>(not a ref)</i>> &) ; |
|---|
| 865 | </pre> |
|---|
| 866 | <blockquote> |
|---|
| 867 | <p><b>Returns:</b> If <b>*this</b> is initialized, a pointer to the contained |
|---|
| 868 | value; else 0 (<i>null</i>). |
|---|
| 869 | </p> |
|---|
| 870 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 871 | <p><b>Notes:</b> The contained value is permanently stored within *this, so |
|---|
| 872 | you should not hold nor delete this pointer |
|---|
| 873 | </p> |
|---|
| 874 | <p><b>Example:</b></p> |
|---|
| 875 | <blockquote> |
|---|
| 876 | <pre>T v; |
|---|
| 877 | optional<T> opt(v); |
|---|
| 878 | optional<T> const copt(v); |
|---|
| 879 | T* p = opt.get_ptr() ; |
|---|
| 880 | T const* cp = copt.get_ptr(); |
|---|
| 881 | assert ( p == get_pointer(opt) ); |
|---|
| 882 | assert ( cp == get_pointer(copt) ) ; |
|---|
| 883 | </pre> |
|---|
| 884 | </blockquote> |
|---|
| 885 | </blockquote> |
|---|
| 886 | |
|---|
| 887 | |
|---|
| 888 | <HR> |
|---|
| 889 | |
|---|
| 890 | |
|---|
| 891 | <pre>T const* optional<T <i>(not a ref)</i>>::operator ->() const ; |
|---|
| 892 | T* optional<T <i>(not a ref)</i>>::operator ->() ; |
|---|
| 893 | </pre> |
|---|
| 894 | <blockquote> |
|---|
| 895 | <p><b>Requirements: *this</b> is initialized.</p> |
|---|
| 896 | <p><b>Returns:</b> A pointer to the contained value.</p> |
|---|
| 897 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 898 | <p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p> |
|---|
| 899 | <p><b>Example:</b></p> |
|---|
| 900 | <blockquote> |
|---|
| 901 | <pre>struct X { int mdata ; } ; |
|---|
| 902 | X x ; |
|---|
| 903 | optional<X> opt (x); |
|---|
| 904 | opt->mdata = 2 ; |
|---|
| 905 | </pre> |
|---|
| 906 | </blockquote> |
|---|
| 907 | </blockquote> |
|---|
| 908 | |
|---|
| 909 | |
|---|
| 910 | <HR> |
|---|
| 911 | |
|---|
| 912 | |
|---|
| 913 | <pre>optional<T>::operator <i>unspecified-bool-type</i>() const ;</pre> |
|---|
| 914 | <blockquote> |
|---|
| 915 | <p><b>Returns:</b> An unspecified value which if used on a boolean context is equivalent to (get() != 0)</p> |
|---|
| 916 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 917 | <blockquote> |
|---|
| 918 | <pre>optional<T> def ; |
|---|
| 919 | assert ( def == 0 ); |
|---|
| 920 | optional<T> opt ( v ) ; |
|---|
| 921 | assert ( opt ); |
|---|
| 922 | assert ( opt != 0 ); |
|---|
| 923 | </pre> |
|---|
| 924 | </blockquote> |
|---|
| 925 | </blockquote> |
|---|
| 926 | |
|---|
| 927 | <HR> |
|---|
| 928 | |
|---|
| 929 | |
|---|
| 930 | <pre> bool optional<T>::operator!() ;</pre> |
|---|
| 931 | <blockquote> |
|---|
| 932 | <p><b>Returns:</b> If <b>*this</b> is uninitialized, <code>true</code>; else <code>false.</code></p> |
|---|
| 933 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 934 | <p><b>Notes:</b> This operator is provided for those compilers which can't use |
|---|
| 935 | the <i>unspecified-bool-type</i> operator in certain boolean contexts. |
|---|
| 936 | </p> |
|---|
| 937 | <p><b>Example:</b></p> |
|---|
| 938 | <blockquote> |
|---|
| 939 | <pre>optional<T> opt ; |
|---|
| 940 | assert ( !opt ); |
|---|
| 941 | *opt = some_T ; |
|---|
| 942 | |
|---|
| 943 | // Notice the "double-bang" idiom here. |
|---|
| 944 | assert ( !!opt ) ; |
|---|
| 945 | </pre> |
|---|
| 946 | </blockquote> |
|---|
| 947 | </blockquote> |
|---|
| 948 | |
|---|
| 949 | |
|---|
| 950 | <HR> |
|---|
| 951 | |
|---|
| 952 | |
|---|
| 953 | <pre>bool optional<T>::is_initialized() const ;</pre> |
|---|
| 954 | <blockquote> |
|---|
| 955 | <p><b>Returns:</b> <i>true</i> is the <b>optional</b> is initialized, <i>false</i> |
|---|
| 956 | otherwise.</p> |
|---|
| 957 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 958 | <blockquote> |
|---|
| 959 | <pre>optional<T> def ; |
|---|
| 960 | assert ( !def.is_initialized() ); |
|---|
| 961 | optional<T> opt ( v ) ; |
|---|
| 962 | assert ( opt.is_initialized() );</pre> |
|---|
| 963 | </blockquote> |
|---|
| 964 | </blockquote> |
|---|
| 965 | |
|---|
| 966 | <HR> |
|---|
| 967 | |
|---|
| 968 | |
|---|
| 969 | <pre>bool operator == ( optional<T> const& x, optional<T> const& y );</pre> |
|---|
| 970 | <blockquote> |
|---|
| 971 | <p><b>Returns:</b> If both <b>x</b> and <b>y</b> are initialied, <code>(*x == *y)</code>. |
|---|
| 972 | If only x or y is initialized, <code>false</code>. If both are uninitialized, <code>true</code>. |
|---|
| 973 | </p> |
|---|
| 974 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 975 | <p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has |
|---|
| 976 | deep relational operators. Do not use operator == directly in generic code |
|---|
| 977 | which expect to be given either an optional<T> or a pointer; |
|---|
| 978 | use <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead |
|---|
| 979 | </p> |
|---|
| 980 | <p><b>Example:</b></p> |
|---|
| 981 | <blockquote> |
|---|
| 982 | <pre>T x(12); |
|---|
| 983 | T y(12); |
|---|
| 984 | T z(21); |
|---|
| 985 | optional<T> def0 ; |
|---|
| 986 | optional<T> def1 ; |
|---|
| 987 | optional<T> optX(x); |
|---|
| 988 | optional<T> optY(y); |
|---|
| 989 | optional<T> optZ(z); |
|---|
| 990 | |
|---|
| 991 | // Identity always hold |
|---|
| 992 | assert ( def0 == def0 ); |
|---|
| 993 | assert ( optX == optX ); |
|---|
| 994 | |
|---|
| 995 | // Both uninitialized compare equal |
|---|
| 996 | assert ( def0 == def1 ); |
|---|
| 997 | |
|---|
| 998 | // Only one initialized compare unequal. |
|---|
| 999 | assert ( def0 != optX ); |
|---|
| 1000 | |
|---|
| 1001 | // Both initialized compare as (*lhs == *rhs) |
|---|
| 1002 | assert ( optX == optY ) ; |
|---|
| 1003 | assert ( optX != optZ ) ; |
|---|
| 1004 | </pre> |
|---|
| 1005 | </blockquote> |
|---|
| 1006 | </blockquote> |
|---|
| 1007 | |
|---|
| 1008 | <HR> |
|---|
| 1009 | |
|---|
| 1010 | |
|---|
| 1011 | <pre>bool operator < ( optional<T> const& x, optional<T> const& y );</pre> |
|---|
| 1012 | <blockquote> |
|---|
| 1013 | <p><b>Returns:</b> If <b>y</b> is not initialized, <code>false</code>. |
|---|
| 1014 | If <b>y</b> is initialized and <b>x</b> is not initialized, <code>true</code>. |
|---|
| 1015 | If both <b>x</b> and <b>y</b> are initialized, <code>(*x < *y)</code>. |
|---|
| 1016 | </p> |
|---|
| 1017 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 1018 | <p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has |
|---|
| 1019 | deep relational operators. Do not use operator < directly in generic code |
|---|
| 1020 | which expect to be given either an optional<T> or a pointer; |
|---|
| 1021 | use <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead |
|---|
| 1022 | </p> |
|---|
| 1023 | <p><b>Example:</b></p> |
|---|
| 1024 | <blockquote> |
|---|
| 1025 | <pre>T x(12); |
|---|
| 1026 | T y(34); |
|---|
| 1027 | optional<T> def ; |
|---|
| 1028 | optional<T> optX(x); |
|---|
| 1029 | optional<T> optY(y); |
|---|
| 1030 | |
|---|
| 1031 | // Identity always hold |
|---|
| 1032 | assert ( !(def < def) ); |
|---|
| 1033 | assert ( optX == optX ); |
|---|
| 1034 | |
|---|
| 1035 | // Both uninitialized compare equal |
|---|
| 1036 | assert ( def0 == def1 ); |
|---|
| 1037 | |
|---|
| 1038 | // Only one initialized compare unequal. |
|---|
| 1039 | assert ( def0 != optX ); |
|---|
| 1040 | |
|---|
| 1041 | // Both initialized compare as (*lhs == *rhs) |
|---|
| 1042 | assert ( optX == optY ) ; |
|---|
| 1043 | assert ( optX != optZ ) ; |
|---|
| 1044 | </pre> |
|---|
| 1045 | </blockquote> |
|---|
| 1046 | </blockquote> |
|---|
| 1047 | |
|---|
| 1048 | <HR> |
|---|
| 1049 | <pre>bool operator != ( optional<T> const& x, optional<T> const& y ); |
|---|
| 1050 | </pre> |
|---|
| 1051 | <blockquote> |
|---|
| 1052 | <p><b>Returns:</b> !( x == y );</p> |
|---|
| 1053 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 1054 | </blockquote> |
|---|
| 1055 | |
|---|
| 1056 | <HR> |
|---|
| 1057 | <pre>bool operator > ( optional<T> const& x, optional<T> const& y ); |
|---|
| 1058 | </pre> |
|---|
| 1059 | <blockquote> |
|---|
| 1060 | <p><b>Returns:</b> ( y < x );</p> |
|---|
| 1061 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 1062 | </blockquote> |
|---|
| 1063 | |
|---|
| 1064 | <HR> |
|---|
| 1065 | <pre>bool operator <= ( optional<T> const& x, optional<T> const& y ); |
|---|
| 1066 | </pre> |
|---|
| 1067 | <blockquote> |
|---|
| 1068 | <p><b>Returns:</b> !( y<x );</p> |
|---|
| 1069 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 1070 | </blockquote> |
|---|
| 1071 | |
|---|
| 1072 | <HR> |
|---|
| 1073 | <pre>bool operator >= ( optional<T> const& x, optional<T> const& y ); |
|---|
| 1074 | </pre> |
|---|
| 1075 | <blockquote> |
|---|
| 1076 | <p><b>Returns:</b> !( x<y );</p> |
|---|
| 1077 | <p><b>Throws:</b> Nothing.</p> |
|---|
| 1078 | </blockquote> |
|---|
| 1079 | |
|---|
| 1080 | <HR> |
|---|
| 1081 | |
|---|
| 1082 | <pre>void swap ( optional<T>& x, optional<T>& y );</pre> |
|---|
| 1083 | |
|---|
| 1084 | <blockquote> |
|---|
| 1085 | <p><b>Effect:</b> If both <b>x</b> and <b>y</b> are initialized, calls <code>swap(*x,*y)</code> |
|---|
| 1086 | using std::swap.<br> |
|---|
| 1087 | If only one is initialized, say x, calls: <code>y.reset(*x); x.reset();</code><br> |
|---|
| 1088 | If none is initialized, does nothing. |
|---|
| 1089 | </p> |
|---|
| 1090 | <p><b>Postconditions:</b> The states of x and y interchanged.</p> |
|---|
| 1091 | <p><b>Throws:</b> If both are initialized, whatever swap(T&,T&) throws. |
|---|
| 1092 | If only one is initialized, whatever T::T ( T const& ) throws. |
|---|
| 1093 | </p> |
|---|
| 1094 | <p><b>Notes:</b> If both are initialized, swap(T&,T&) is used <i>unqualified</i> |
|---|
| 1095 | but with std::swap introduced in scope.<br> |
|---|
| 1096 | If only one is initialized, T::~T() and T::T( T const& ) is called. |
|---|
| 1097 | </p> |
|---|
| 1098 | <p><b>Exception Safety:</b> If both are initialized, this operation has the exception |
|---|
| 1099 | safety guarantees of swap(T&,T&).<br> |
|---|
| 1100 | If only one is initialized, it has the same <b>basic</b> guarantee as optional<T>::reset( T const& ). |
|---|
| 1101 | </p> |
|---|
| 1102 | <p><b>Example:</b></p> |
|---|
| 1103 | <blockquote> |
|---|
| 1104 | <pre>T x(12); |
|---|
| 1105 | T y(21); |
|---|
| 1106 | optional<T> def0 ; |
|---|
| 1107 | optional<T> def1 ; |
|---|
| 1108 | optional<T> optX(x); |
|---|
| 1109 | optional<T> optY(y); |
|---|
| 1110 | |
|---|
| 1111 | boost::swap(def0,def1); // no-op |
|---|
| 1112 | |
|---|
| 1113 | boost::swap(def0,optX); |
|---|
| 1114 | assert ( *def0 == x ); |
|---|
| 1115 | assert ( !optX ); |
|---|
| 1116 | |
|---|
| 1117 | boost::swap(def0,optX); // Get back to original values |
|---|
| 1118 | |
|---|
| 1119 | boost::swap(optX,optY); |
|---|
| 1120 | assert ( *optX == y ); |
|---|
| 1121 | assert ( *optY == x ); |
|---|
| 1122 | |
|---|
| 1123 | </pre> |
|---|
| 1124 | </blockquote> |
|---|
| 1125 | </blockquote> |
|---|
| 1126 | <HR> |
|---|
| 1127 | |
|---|
| 1128 | <H2><A NAME="examples">Examples</A></H2> |
|---|
| 1129 | |
|---|
| 1130 | <h3>Optional return values</h3> |
|---|
| 1131 | <PRE>optional<char> get_async_input() |
|---|
| 1132 | { |
|---|
| 1133 | if ( !queue.empty() ) |
|---|
| 1134 | return optional<char>(queue.top()); |
|---|
| 1135 | else return optional<char>(); // uninitialized |
|---|
| 1136 | } |
|---|
| 1137 | |
|---|
| 1138 | void receive_async_message() |
|---|
| 1139 | { |
|---|
| 1140 | optional<char> rcv ; |
|---|
| 1141 | // The safe boolean conversion from 'rcv' is used here. |
|---|
| 1142 | while ( (rcv = get_async_input()) && !timeout() ) |
|---|
| 1143 | output(*rcv); |
|---|
| 1144 | } |
|---|
| 1145 | </pre> |
|---|
| 1146 | |
|---|
| 1147 | <h3>Optional local variables</h3> |
|---|
| 1148 | <pre>optional<string> name ; |
|---|
| 1149 | if ( database.open() ) |
|---|
| 1150 | { |
|---|
| 1151 | name.reset ( database.lookup(employer_name) ) ; |
|---|
| 1152 | } |
|---|
| 1153 | else |
|---|
| 1154 | { |
|---|
| 1155 | if ( can_ask_user ) |
|---|
| 1156 | name.reset ( user.ask(employer_name) ) ; |
|---|
| 1157 | } |
|---|
| 1158 | |
|---|
| 1159 | if ( name ) |
|---|
| 1160 | print(*name); |
|---|
| 1161 | else print("employer's name not found!"); |
|---|
| 1162 | </pre> |
|---|
| 1163 | |
|---|
| 1164 | <h3>Optional data members</h3> |
|---|
| 1165 | <pre>class figure |
|---|
| 1166 | { |
|---|
| 1167 | public: |
|---|
| 1168 | |
|---|
| 1169 | figure() |
|---|
| 1170 | { |
|---|
| 1171 | // data member 'm_clipping_rect' is uninitialized at this point. |
|---|
| 1172 | } |
|---|
| 1173 | |
|---|
| 1174 | void clip_in_rect ( rect const& rect ) |
|---|
| 1175 | { |
|---|
| 1176 | .... |
|---|
| 1177 | m_clipping_rect.reset ( rect ) ; // initialized here. |
|---|
| 1178 | } |
|---|
| 1179 | |
|---|
| 1180 | void draw ( canvas& cvs ) |
|---|
| 1181 | { |
|---|
| 1182 | if ( m_clipping_rect ) |
|---|
| 1183 | do_clipping(*m_clipping_rect); |
|---|
| 1184 | |
|---|
| 1185 | cvs.drawXXX(..); |
|---|
| 1186 | } |
|---|
| 1187 | |
|---|
| 1188 | // this can return NULL. |
|---|
| 1189 | rect const* get_clipping_rect() { return get_pointer(m_clipping_rect); } |
|---|
| 1190 | |
|---|
| 1191 | private : |
|---|
| 1192 | |
|---|
| 1193 | optional<rect> m_clipping_rect ; |
|---|
| 1194 | |
|---|
| 1195 | }; |
|---|
| 1196 | </pre> |
|---|
| 1197 | <h3>Bypassing expensive unnecessary default construction</h3> |
|---|
| 1198 | <pre>class ExpensiveCtor { ... } ; |
|---|
| 1199 | class Fred |
|---|
| 1200 | { |
|---|
| 1201 | Fred() : mLargeVector(10000) {} |
|---|
| 1202 | |
|---|
| 1203 | std::vector< optional<ExpensiveCtor> > mLargeVector ; |
|---|
| 1204 | } ; |
|---|
| 1205 | </pre> |
|---|
| 1206 | |
|---|
| 1207 | <HR> |
|---|
| 1208 | |
|---|
| 1209 | <H2><A NAME="ref">Optional references</A></H2> |
|---|
| 1210 | <p>This library allows the template parameter T to be of reference type: T&, and |
|---|
| 1211 | to some extent, T const&.</p> |
|---|
| 1212 | |
|---|
| 1213 | <p>However, since references are not real objects some restrictions apply and |
|---|
| 1214 | some operations are not available in this case:</p> |
|---|
| 1215 | |
|---|
| 1216 | <ul> |
|---|
| 1217 | <li>Converting constructors</li> |
|---|
| 1218 | <li>Converting assignment</li> |
|---|
| 1219 | <li>InPlace construction</li> |
|---|
| 1220 | <li>InPlace assignment</li> |
|---|
| 1221 | <li>Value-access via pointer</li> |
|---|
| 1222 | </ul> |
|---|
| 1223 | <p>Also, even though optional<T&> treats it wrapped pseudo-object much as a real |
|---|
| 1224 | value, a true real reference is stored so aliasing will ocurr: </p> |
|---|
| 1225 | |
|---|
| 1226 | <ul> |
|---|
| 1227 | <li>Copies of optional<T&> will copy the references but all these references |
|---|
| 1228 | will nonetheless reefer to the same object.</li> |
|---|
| 1229 | <li>Value-access will actually provide access to the referenced object rather |
|---|
| 1230 | than the reference itself.</li> |
|---|
| 1231 | </ul> |
|---|
| 1232 | |
|---|
| 1233 | <HR> |
|---|
| 1234 | <h2><A NAME="refassign">Rebinding semantics for assignment of optional |
|---|
| 1235 | references</a></h2> |
|---|
| 1236 | <p>If you assign to an <i>uninitialized</i> optional<T&> the effect is to bind (for the first time) to the object. |
|---|
| 1237 | Clearly, there is no other choice.</p> |
|---|
| 1238 | <pre>int x = 1 ; |
|---|
| 1239 | int& rx = x ; |
|---|
| 1240 | optional<int&> ora ; |
|---|
| 1241 | optional<int&> orb(x) ; |
|---|
| 1242 | ora = orb ; // now 'ora' is bound to 'x' through 'rx' |
|---|
| 1243 | *ora = 2 ; // Changes value of 'x' through 'ora' |
|---|
| 1244 | assert(x==2); |
|---|
| 1245 | </pre> |
|---|
| 1246 | <p>If you assign to a bare C++ reference, the assignment is forwarded to the |
|---|
| 1247 | referenced object; it's value changes but the reference is never rebound.</p> |
|---|
| 1248 | <pre>int a = 1 ; |
|---|
| 1249 | int& ra = a ; |
|---|
| 1250 | int b = 2 ; |
|---|
| 1251 | int& rb = b ; |
|---|
| 1252 | ra = rb ; // Changes the value of 'a' to 'b' |
|---|
| 1253 | assert(a==b); |
|---|
| 1254 | b = 3 ; |
|---|
| 1255 | assert(ra!=b); // 'ra' is not rebound to 'b' |
|---|
| 1256 | </pre> |
|---|
| 1257 | <p>Now, if you assign to an <i>initialized</i> optional<T&>, the effect is to <b> |
|---|
| 1258 | rebind</b> to the new object instead of assigning the referee. This is unlike |
|---|
| 1259 | bare C++ references.</p> |
|---|
| 1260 | <pre>int a = 1 ; |
|---|
| 1261 | int b = 2 ; |
|---|
| 1262 | int& ra = a ; |
|---|
| 1263 | int& rb = b ; |
|---|
| 1264 | optional<int&> ora(ra) ; |
|---|
| 1265 | optional<int&> orb(rb) ; |
|---|
| 1266 | ora = orb ; // 'ora' is <b>rebound</b> to 'b' |
|---|
| 1267 | *ora = 3 ; // Changes value of 'b' (not 'a') |
|---|
| 1268 | assert(a==1); |
|---|
| 1269 | assert(b==3); |
|---|
| 1270 | </pre> |
|---|
| 1271 | <h3>Rationale:</h3> |
|---|
| 1272 | <p>Rebinding semantics for the assignment of <i>initialized</i> optional |
|---|
| 1273 | references has been chosen to provide<b><i> </i>consistency among initialization |
|---|
| 1274 | states<i> </i></b>even at the expense of lack of consistency with the semantics of bare |
|---|
| 1275 | C++ references.<br> |
|---|
| 1276 | It is true that optional<U> strives to behave as much as possible as U does |
|---|
| 1277 | whenever it is initialized; but in the case when U is T&, doing so would result |
|---|
| 1278 | in inconsistent behavior w.r.t to the lvalue initialization state.</p> |
|---|
| 1279 | <p>Imagine optional<T&> forwarding assignment to the referenced object (thus |
|---|
| 1280 | changing the referenced object value but not rebinding), and consider the |
|---|
| 1281 | following code :</p> |
|---|
| 1282 | <pre> optional<int&> a = get(); |
|---|
| 1283 | int x = 1 ; |
|---|
| 1284 | int& rx = x ; |
|---|
| 1285 | optional<int&> b(rx); |
|---|
| 1286 | a = b ; |
|---|
| 1287 | </pre> |
|---|
| 1288 | <p>What does the assignment do?<br> |
|---|
| 1289 | If 'a' is <i>uninitialized</i>, the answer is clear: it binds to 'x' (we now have |
|---|
| 1290 | another reference to 'x').<br> |
|---|
| 1291 | But what if 'a' is already <i>initialized? </i>it would change the value of the |
|---|
| 1292 | referenced object (whatever that is); which is inconsistent with the other |
|---|
| 1293 | possible case.</p> |
|---|
| 1294 | <p>If optional<T&> would assign just like T& does, you would never be able to |
|---|
| 1295 | use Optional's assignment without explicitly handling the previous |
|---|
| 1296 | initialization state unless your code is capable of functioning whether after |
|---|
| 1297 | the assignment, 'a' |
|---|
| 1298 | aliases the same object as 'b' or not.</p> |
|---|
| 1299 | <p>That is, you would have to discriminate in order to be consistency.<br> |
|---|
| 1300 | <br> |
|---|
| 1301 | If in your code rebinding to another object is not an option, then is very |
|---|
| 1302 | likely that binding for the fist time isn't either. In such case, assignment to |
|---|
| 1303 | an <i>uninitialized</i> optional<T&> shall be prohibited. It is quite |
|---|
| 1304 | possible that in such scenario the precondition that the lvalue must be already |
|---|
| 1305 | initialized exist. If it doesn't, then binding for the first time is OK while |
|---|
| 1306 | rebinding is not which is IMO |
|---|
| 1307 | very unlikely.<br> |
|---|
| 1308 | In such scenario, you can assign the value itself directly, as in:</p> |
|---|
| 1309 | <pre>assert(!!opt); |
|---|
| 1310 | *opt=value; </pre> |
|---|
| 1311 | |
|---|
| 1312 | <HR> |
|---|
| 1313 | |
|---|
| 1314 | <H2><A NAME="inplace">In-Place Factories</A></H2> |
|---|
| 1315 | <p> |
|---|
| 1316 | One of the typical problems with wrappers and containers is that their |
|---|
| 1317 | interfaces usually provide an operation to initialize or assign the contained |
|---|
| 1318 | object as a copy of some other object. This not only requires the underlying |
|---|
| 1319 | type to be <a href="../../utility/CopyConstructible.html">Copy Constructible</a>, but also requires the existence of a fully |
|---|
| 1320 | constructed object, often temporary, just to follow the copy from:</p> |
|---|
| 1321 | <pre>struct X |
|---|
| 1322 | { |
|---|
| 1323 | X ( int, std:::string ) ; |
|---|
| 1324 | } ;</pre> |
|---|
| 1325 | <pre>class W |
|---|
| 1326 | { |
|---|
| 1327 | X wrapped_ ; |
|---|
| 1328 | |
|---|
| 1329 | public: |
|---|
| 1330 | |
|---|
| 1331 | W ( X const& x ) : wrapped_(x) {} |
|---|
| 1332 | } ;</pre> |
|---|
| 1333 | <pre>void foo() |
|---|
| 1334 | { |
|---|
| 1335 | // Temporary object created. |
|---|
| 1336 | W ( X(123,"hello") ) ; |
|---|
| 1337 | } |
|---|
| 1338 | </pre> |
|---|
| 1339 | <p>A solution to this problem is to support direct construction of the contained |
|---|
| 1340 | object right in the container's storage.<br> |
|---|
| 1341 | In this scheme, the user only needs to supply the arguments to the constructor |
|---|
| 1342 | to use in the wrapped object construction.</p> |
|---|
| 1343 | <pre>class W |
|---|
| 1344 | { |
|---|
| 1345 | X wrapped_ ; |
|---|
| 1346 | |
|---|
| 1347 | public: |
|---|
| 1348 | |
|---|
| 1349 | W ( X const& x ) : wrapped_(x) {} |
|---|
| 1350 | W ( int a0, std::string a1) : wrapped_(a0,a1) {} |
|---|
| 1351 | } ;</pre> |
|---|
| 1352 | <pre>void foo() |
|---|
| 1353 | { |
|---|
| 1354 | // Wrapped object constructed in-place |
|---|
| 1355 | // No temporary created. |
|---|
| 1356 | W (123,"hello") ; |
|---|
| 1357 | } |
|---|
| 1358 | </pre> |
|---|
| 1359 | <p>A limitation of this method is that it doesn't scale well to wrapped objects with multiple |
|---|
| 1360 | constructors nor to generic code were the constructor overloads are unknown.</p> |
|---|
| 1361 | <p>The solution presented in this library is the family of <b>InPlaceFactories</b> and |
|---|
| 1362 | <b>TypedInPlaceFactories</b>.<br> |
|---|
| 1363 | These factories are a family of classes which encapsulate an increasing number of arbitrary |
|---|
| 1364 | constructor parameters and supply a method to construct an object of a given type using those |
|---|
| 1365 | parameters at an address specified by the user via placement new.</p> |
|---|
| 1366 | <p> For example, one member of this family looks like:</p> |
|---|
| 1367 | <pre>template<class T,class A0, class A1> |
|---|
| 1368 | class TypedInPlaceFactory2 |
|---|
| 1369 | { |
|---|
| 1370 | A0 m_a0 ; A1 m_a1 ; |
|---|
| 1371 | |
|---|
| 1372 | public: |
|---|
| 1373 | |
|---|
| 1374 | TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {} |
|---|
| 1375 | |
|---|
| 1376 | void construct ( void* p ) { new (p) T(m_a0,m_a1) ; } |
|---|
| 1377 | } ; |
|---|
| 1378 | </pre> |
|---|
| 1379 | <p>A wrapper class aware of this can use it as:</p> |
|---|
| 1380 | <pre>class W |
|---|
| 1381 | { |
|---|
| 1382 | X wrapped_ ; |
|---|
| 1383 | |
|---|
| 1384 | public: |
|---|
| 1385 | |
|---|
| 1386 | W ( X const& x ) : wrapped_(x) {} |
|---|
| 1387 | W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; } |
|---|
| 1388 | } ;</pre> |
|---|
| 1389 | <pre>void foo() |
|---|
| 1390 | { |
|---|
| 1391 | // Wrapped object constructed in-place via a TypedInPlaceFactory. |
|---|
| 1392 | // No temporary created. |
|---|
| 1393 | W ( TypedInPlaceFactory2<X,int,std::string&rt;(123,"hello")) ; |
|---|
| 1394 | } |
|---|
| 1395 | </pre> |
|---|
| 1396 | <p>The factories are divided in two groups:<ul> |
|---|
| 1397 | <li><u>TypedInPlaceFactories</u>: those which take the target type as a primary template parameter.</li> |
|---|
| 1398 | <li><u>InPlaceFactories</u>: those with a template <code>construct(void*)</code> member function taking the target type.</li> |
|---|
| 1399 | </ul> |
|---|
| 1400 | <p>Within each group, all the family members differ only in the number of parameters allowed.</p> |
|---|
| 1401 | <p></p> |
|---|
| 1402 | <p>This library provides an overloaded set of helper template functions to construct these factories |
|---|
| 1403 | without requiring unnecessary template parameters:</p> |
|---|
| 1404 | <pre>template<class A0,...,class AN> |
|---|
| 1405 | InPlaceFactory<i>N </i><A0,...,AN> <b>in_place</b> ( A0 const& a0, ..., AN const& aN) ; |
|---|
| 1406 | |
|---|
| 1407 | template<class T,class A0,...,class AN> |
|---|
| 1408 | TypedInPlaceFactory<i>N </i><T,A0,...,AN> <b>in_place</b> ( T const& a0, A0 const& a0, ..., AN const& aN) ;</pre> |
|---|
| 1409 | |
|---|
| 1410 | <p>In-place factories can be used generically by the wrapper and user as follows:</p> |
|---|
| 1411 | <pre>class W |
|---|
| 1412 | { |
|---|
| 1413 | X wrapped_ ; |
|---|
| 1414 | |
|---|
| 1415 | public: |
|---|
| 1416 | |
|---|
| 1417 | W ( X const& x ) : wrapped_(x) {} |
|---|
| 1418 | |
|---|
| 1419 | template<class InPlaceFactory></class> |
|---|
| 1420 | W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; } |
|---|
| 1421 | |
|---|
| 1422 | } ;</pre> |
|---|
| 1423 | <pre>void foo() |
|---|
| 1424 | { |
|---|
| 1425 | // Wrapped object constructed in-place via a InPlaceFactory. |
|---|
| 1426 | // No temporary created. |
|---|
| 1427 | W ( in_place(123,"hello") ) ; |
|---|
| 1428 | } |
|---|
| 1429 | </pre> |
|---|
| 1430 | <p>The factories are implemented in the headers: |
|---|
| 1431 | <a href="../../../boost/utility/in_place_factory.hpp">in_place_factory.hpp</a> and |
|---|
| 1432 | <a href="../../../boost/utility/typed_in_place_factory.hpp">typed_in_place_factory.hpp</a> |
|---|
| 1433 | </p> |
|---|
| 1434 | |
|---|
| 1435 | <HR> |
|---|
| 1436 | |
|---|
| 1437 | <H2><A NAME="bool">A note about optional<bool></A></H2> |
|---|
| 1438 | <p><code>optional<bool></code> should be used with special caution and consideration.</p> |
|---|
| 1439 | <p>First, it is functionally similar to a tristate boolean (false,maybe,true) —such as <a href="http://www.boost.org/doc/html/tribool.html">boost::tribool</a>—except that in a tristate boolean, |
|---|
| 1440 | the <i>maybe</i> state <u>represents a valid value</u>, unlike the corresponding state |
|---|
| 1441 | of an uninitialized optional<bool>.<br> |
|---|
| 1442 | It should be carefully considered if an optional<bool> instead of a tribool is really needed</p> |
|---|
| 1443 | <p>Second, optional<> provides an implicit conversion to bool. This conversion |
|---|
| 1444 | refers to the initialization state and not to the contained value.<br> |
|---|
| 1445 | Using optional<bool> can lead to subtle errors due to the implicit bool conversion:</p> |
|---|
| 1446 | <pre>void foo ( bool v ) ; |
|---|
| 1447 | void bar() |
|---|
| 1448 | { |
|---|
| 1449 | optional<bool> v = try(); |
|---|
| 1450 | |
|---|
| 1451 | // The following intended to pass the <b>value</b> of 'v' to foo(): |
|---|
| 1452 | foo(v); |
|---|
| 1453 | // But instead, the <i>initialization state</i> is passed |
|---|
| 1454 | // due to a typo: it should have been foo(<b>*</b>v). |
|---|
| 1455 | } |
|---|
| 1456 | </pre> |
|---|
| 1457 | <p>The only implicit conversion is to bool, and it is <i>safe</i> in the sense that typical |
|---|
| 1458 | integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile). <HR> |
|---|
| 1459 | |
|---|
| 1460 | <H2><A NAME="exsafety">Exception Safety Guarantees</A></H2> |
|---|
| 1461 | <H3><u>Assignment and Reset:</u></H3> |
|---|
| 1462 | <p>Because of the current implementation (see <A HREF="#impl">Implementation Notes</A>), all |
|---|
| 1463 | of the assignment methods:</p> |
|---|
| 1464 | <ul> |
|---|
| 1465 | <li> <code>optional<T>::operator= ( optional<T> const& ) </code> |
|---|
| 1466 | </li> |
|---|
| 1467 | <li> <code>optional<T>::operator= ( T const& ) </code></li> |
|---|
| 1468 | <li> <code>template<class U> optional<T>::operator= ( optional<U> const& ) </code> |
|---|
| 1469 | </li> |
|---|
| 1470 | <li> <code>template<class InPlaceFactory> optional<T>::operator= ( |
|---|
| 1471 | InPlaceFactory const& ) </code></li> |
|---|
| 1472 | <li> <code>template<class TypedInPlaceFactory> optional<T>::operator= ( |
|---|
| 1473 | TypedInPlaceFactory const& ) </code></li> |
|---|
| 1474 | <li> <code>optional<T>:::reset ( T const&)</code></li> |
|---|
| 1475 | </ul> |
|---|
| 1476 | <p>Can only <i>guarantee</i> the <u>basic exception safety</u>: The lvalue optional is left <u>uninitialized</u> |
|---|
| 1477 | if an exception is thrown (any previous value is <i>first</i> destroyed using T::~T())</p> |
|---|
| 1478 | <p>On the other hand, the <i>uninitializing</i> methods:</p> |
|---|
| 1479 | <ul> |
|---|
| 1480 | <li><code>optional<T>::operator= ( detail::none_t ) </code></li> |
|---|
| 1481 | <li><code>optional<T>::reset()</code></li> |
|---|
| 1482 | </ul> |
|---|
| 1483 | <p>Provide the no-throw guarantee (assuming a no-throw T::~T())</p> |
|---|
| 1484 | <p>However, since <code>optional<></code> itself doesn't throw any exceptions, |
|---|
| 1485 | the only source for exceptions here are T's constructor, so if you know the exception guarantees |
|---|
| 1486 | for T::T ( T const& ), you know that optional's assignment and reset has the same guarantees.</p> |
|---|
| 1487 | <pre>// |
|---|
| 1488 | // Case 1: Exception thrown during assignment. |
|---|
| 1489 | // |
|---|
| 1490 | T v0(123); |
|---|
| 1491 | optional<T> opt0(v0); |
|---|
| 1492 | try |
|---|
| 1493 | { |
|---|
| 1494 | T v1(456); |
|---|
| 1495 | optional<T> opt1(v1); |
|---|
| 1496 | opt0 = opt1 ; |
|---|
| 1497 | |
|---|
| 1498 | // If no exception was thrown, assignment succeeded. |
|---|
| 1499 | assert( *opt0 == v1 ) ; |
|---|
| 1500 | } |
|---|
| 1501 | catch(...) |
|---|
| 1502 | { |
|---|
| 1503 | // If any exception was thrown, 'opt0' is reset to uninitialized. |
|---|
| 1504 | assert( !opt0 ) ; |
|---|
| 1505 | } |
|---|
| 1506 | |
|---|
| 1507 | // |
|---|
| 1508 | // Case 2: Exception thrown during reset(v) |
|---|
| 1509 | // |
|---|
| 1510 | T v0(123); |
|---|
| 1511 | optional<T> opt(v0); |
|---|
| 1512 | try |
|---|
| 1513 | { |
|---|
| 1514 | T v1(456); |
|---|
| 1515 | opt.reset ( v1 ) ; |
|---|
| 1516 | |
|---|
| 1517 | // If no exception was thrown, reset succeeded. |
|---|
| 1518 | assert( *opt == v1 ) ; |
|---|
| 1519 | } |
|---|
| 1520 | catch(...) |
|---|
| 1521 | { |
|---|
| 1522 | // If any exception was thrown, 'opt' is reset to uninitialized. |
|---|
| 1523 | assert( !opt ) ; |
|---|
| 1524 | } |
|---|
| 1525 | </pre> |
|---|
| 1526 | <H3><u>Swap:</u></H3> |
|---|
| 1527 | <p><code>void swap( optional<T>&, optional<T>& )</code> has the same exception guarantee as <code>swap(T&,T&)</code> when both optionals are initialized.<br> |
|---|
| 1528 | If only one of the optionals is initialized, it gives the same <i>basic</i> exception guarantee as <code>optional<T>::reset( T const& )</code> (since <code>optional<T>::reset()</code> doesn't throw).<br> |
|---|
| 1529 | If none of the optionals is initialized, it has no-throw guarantee since it is a no-op. </p> |
|---|
| 1530 | |
|---|
| 1531 | <HR> |
|---|
| 1532 | |
|---|
| 1533 | <H2><A NAME="requirements">Type requirements</A></H2> |
|---|
| 1534 | <p>In general, T must be <a href="../../utility/CopyConstructible.html">Copy Constructible</a> and have a no-throw destructor. The copy-constructible requirement is not needed |
|---|
| 1535 | if InPlaceFactories are used.<br> |
|---|
| 1536 | T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</a> </p> |
|---|
| 1537 | |
|---|
| 1538 | <HR> |
|---|
| 1539 | |
|---|
| 1540 | <H2><A NAME="impl">Implementation Notes</A></H2> |
|---|
| 1541 | <p>optional<T> is currently implemented |
|---|
| 1542 | using a custom aligned storage facility built from <code>alignment_of</code> and <code>type_with_alignment</code> (both from Type Traits). |
|---|
| 1543 | It uses a separate boolean flag to indicate the initialization state.<br> |
|---|
| 1544 | Placement new with T's copy constructor and T's destructor |
|---|
| 1545 | are explicitly used to initialize,copy and destroy optional values.<br> |
|---|
| 1546 | As a result, T's default constructor is effectively by-passed, but the exception |
|---|
| 1547 | guarantees are basic.<br> |
|---|
| 1548 | It is planned to replace the current implementation with another with |
|---|
| 1549 | stronger exception safety, such as a future boost::variant<T,nil_t>. </p> |
|---|
| 1550 | |
|---|
| 1551 | <HR> |
|---|
| 1552 | |
|---|
| 1553 | <H2><A NAME="porta">Dependencies and Portability</A></H2> |
|---|
| 1554 | |
|---|
| 1555 | <p>The implementation uses <code>type_traits/alignment_of.hpp</code> and <code>type_traits/type_with_alignment.hpp</code></p> |
|---|
| 1556 | |
|---|
| 1557 | <HR> |
|---|
| 1558 | |
|---|
| 1559 | <H2><A NAME="credits">Acknowledgments</A></H2> |
|---|
| 1560 | <p>Pre-formal review:</p> |
|---|
| 1561 | <blockquote> |
|---|
| 1562 | <p>Peter Dimov suggested the name 'optional', and was the first to point out the |
|---|
| 1563 | need for aligned storage<br> |
|---|
| 1564 | Douglas Gregor developed 'type_with_alignment', and later Eric Friedman coded |
|---|
| 1565 | 'aligned_storage', which are the core of the optional class implementation.<br> |
|---|
| 1566 | Andrei Alexandrescu and Brian Parker also worked with aligned storage techniques |
|---|
| 1567 | and their work influenced the current implementation.<br> |
|---|
| 1568 | Gennadiy Rozental made extensive and important comments which shaped the design.<br> |
|---|
| 1569 | Vesa Karvonen and Douglas Gregor made quite useful comparisons between optional, |
|---|
| 1570 | variant and any; and made other relevant comments. Douglas Gregor and Peter |
|---|
| 1571 | Dimov commented on comparisons and evaluation in boolean contexts.<br> |
|---|
| 1572 | Eric Friedman helped understand the issues involved with aligned storage, move/copy |
|---|
| 1573 | operations and exception safety.<br> |
|---|
| 1574 | Many others have participated with useful comments: Aleksey Gurotov, Kevlin |
|---|
| 1575 | Henney, David Abrahams, and others I can't recall. </p> |
|---|
| 1576 | </blockquote> |
|---|
| 1577 | <p>Post-formal review:</p> |
|---|
| 1578 | <blockquote> |
|---|
| 1579 | <p>William Kempf carefully considered the originally proposed interface and |
|---|
| 1580 | suggested the new interface which is currently used. He also started and fueled |
|---|
| 1581 | the discussion about the analogy optional<>/smart pointer and about |
|---|
| 1582 | relational operators.<br> |
|---|
| 1583 | Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson focused |
|---|
| 1584 | on the relational semantics of optional (originally undefined); concluding |
|---|
| 1585 | with the fact that the pointer-like interface doesn't make it a pointer so |
|---|
| 1586 | it shall have deep relational operators.<br> |
|---|
| 1587 | Augustus Saunders also explored the different relational semantics between |
|---|
| 1588 | optional<> and a pointer and developed the OptionalPointee concept as |
|---|
| 1589 | an aid against potential conflicts on generic code.<br> |
|---|
| 1590 | Joel de Guzman noticed that optional<> can be seen as an API on top |
|---|
| 1591 | of variant<T,nil_t>.<br> |
|---|
| 1592 | Dave Gomboc explained the meaning and usage of the Haskell analog to optional<>: |
|---|
| 1593 | the Maybe type constructor (analogy originally pointed out by David Sankel).<br> |
|---|
| 1594 | Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, Rob |
|---|
| 1595 | Stewart, and others.<br> |
|---|
| 1596 | Joel de Guzman made the case for the support of references and helped with |
|---|
| 1597 | the proper semantics.<br> |
|---|
| 1598 | Mat Marcus shown the virtues of a value-oriented interface, influencing the |
|---|
| 1599 | current design, and contributed the idea of "none".</p> |
|---|
| 1600 | </blockquote> |
|---|
| 1601 | <HR> |
|---|
| 1602 | |
|---|
| 1603 | <P>Revised April 21, 2005</P> |
|---|
| 1604 | <p>© Copyright Fernando Luis Cacciola Carballal, 2003,2004,2005</p> |
|---|
| 1605 | <p> Use, modification, and distribution are subject to the Boost Software |
|---|
| 1606 | License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt"> |
|---|
| 1607 | LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> |
|---|
| 1608 | www.boost.org/LICENSE_1_0.txt</a>)</p> |
|---|
| 1609 | <P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>, |
|---|
| 1610 | the latest version of this file can be found at <A |
|---|
| 1611 | HREF="http://www.boost.org">www.boost.org</A>, and the boost |
|---|
| 1612 | <A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P> |
|---|
| 1613 | </BODY> |
|---|
| 1614 | </HTML> |
|---|