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