11_development.qbk 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. [/
  2. Boost.Optional
  3. Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. ]
  8. [section Design Overview]
  9. [section The models]
  10. In C++, we can ['declare] an object (a variable) of type `T`, and we can give this
  11. variable an ['initial value] (through an ['initializer]. (cf. 8.5)).
  12. When a declaration includes a non-empty initializer (an initial value is given),
  13. it is said that the object has been initialized.
  14. If the declaration uses an empty initializer (no initial value is given), and
  15. neither default nor value initialization applies, it is said that the object is
  16. [*uninitialized]. Its actual value exist but has an ['indeterminate initial value]
  17. (cf. 8.5/11).
  18. `optional<T>` intends to formalize the notion of initialization (or lack of it)
  19. allowing a program to test whether an object has been initialized and stating
  20. that access to the value of an uninitialized object is undefined behavior. That
  21. is, when a variable is declared as `optional<T>` and no initial value is given,
  22. the variable is ['formally] uninitialized. A formally uninitialized optional object
  23. has conceptually no value at all and this situation can be tested at runtime. It
  24. is formally ['undefined behavior] to try to access the value of an uninitialized
  25. optional. An uninitialized optional can be assigned a value, in which case its initialization state changes to initialized. Furthermore, given the formal
  26. treatment of initialization states in optional objects, it is even possible to
  27. reset an optional to ['uninitialized].
  28. In C++ there is no formal notion of uninitialized objects, which means that
  29. objects always have an initial value even if indeterminate.
  30. As discussed on the previous section, this has a drawback because you need
  31. additional information to tell if an object has been effectively initialized.
  32. One of the typical ways in which this has been historically dealt with is via
  33. a special value: `EOF`, `npos`, -1, etc... This is equivalent to adding the
  34. special value to the set of possible values of a given type. This super set of
  35. `T` plus some ['nil_t]—where `nil_t` is some stateless POD—can be modeled in modern
  36. languages as a [*discriminated union] of T and nil_t. Discriminated unions are
  37. often called ['variants]. A variant has a ['current type], which in our case is either
  38. `T` or `nil_t`.
  39. Using the __BOOST_VARIANT__ library, this model can be implemented in terms of `boost::variant<T,nil_t>`.
  40. There is precedent for a discriminated union as a model for an optional value:
  41. the __HASKELL__ [*Maybe] built-in type constructor. Thus, a discriminated union
  42. `T+nil_t` serves as a conceptual foundation.
  43. A `variant<T,nil_t>` follows naturally from the traditional idiom of extending
  44. the range of possible values adding an additional sentinel value with the
  45. special meaning of ['Nothing]. However, this additional ['Nothing] value is largely
  46. irrelevant for our purpose since our goal is to formalize the notion of
  47. uninitialized objects and, while a special extended value can be used to convey
  48. that meaning, it is not strictly necessary in order to do so.
  49. The observation made in the last paragraph about the irrelevant nature of the
  50. additional `nil_t` with respect to [_purpose] of `optional<T>` suggests an
  51. alternative model: a ['container] that either has a value of `T` or nothing.
  52. As of this writing I don't know of any precedent for a variable-size
  53. fixed-capacity (of 1) stack-based container model for optional values, yet I
  54. believe this is the consequence of the lack of practical implementations of
  55. such a container rather than an inherent shortcoming of the container model.
  56. In any event, both the discriminated-union or the single-element container
  57. models serve as a conceptual ground for a class representing optional—i.e.
  58. possibly uninitialized—objects.
  59. For instance, these models show the ['exact] semantics required for a wrapper
  60. of optional values:
  61. Discriminated-union:
  62. * [*deep-copy] semantics: copies of the variant implies copies of the value.
  63. * [*deep-relational] semantics: comparisons between variants matches both
  64. current types and values
  65. * If the variant's current type is `T`, it is modeling an ['initialized] optional.
  66. * If the variant's current type is not `T`, it is modeling an ['uninitialized]
  67. optional.
  68. * Testing if the variant's current type is `T` models testing if the optional
  69. is initialized
  70. * Trying to extract a `T` from a variant when its current type is not `T`, models
  71. the undefined behavior of trying to access the value of an uninitialized optional
  72. Single-element container:
  73. * [*deep-copy] semantics: copies of the container implies copies of the value.
  74. * [*deep-relational] semantics: comparisons between containers compare container
  75. size and if match, contained value
  76. * If the container is not empty (contains an object of type `T`), it is modeling
  77. an ['initialized] optional.
  78. * If the container is empty, it is modeling an ['uninitialized] optional.
  79. * Testing if the container is empty models testing if the optional is
  80. initialized
  81. * Trying to extract a `T` from an empty container models the undefined behavior
  82. of trying to access the value of an uninitialized optional
  83. [endsect]
  84. [section The semantics]
  85. Objects of type `optional<T>` are intended to be used in places where objects of
  86. type `T` would but which might be uninitialized. Hence, `optional<T>`'s purpose is
  87. to formalize the additional possibly uninitialized state.
  88. From the perspective of this role, `optional<T>` can have the same operational
  89. semantics of `T` plus the additional semantics corresponding to this special
  90. state.
  91. As such, `optional<T>` could be thought of as a ['supertype] of `T`. Of course, we
  92. can't do that in C++, so we need to compose the desired semantics using a
  93. different mechanism.
  94. Doing it the other way around, that is, making `optional<T>` a ['subtype] of `T`
  95. is not only conceptually wrong but also impractical: it is not allowed to
  96. derive from a non-class type, such as a built-in type.
  97. We can draw from the purpose of `optional<T>` the required basic semantics:
  98. * [*Default Construction:] To introduce a formally uninitialized wrapped
  99. object.
  100. * [*Direct Value Construction via copy:] To introduce a formally initialized
  101. wrapped object whose value is obtained as a copy of some object.
  102. * [*Deep Copy Construction:] To obtain a new yet equivalent wrapped object.
  103. * [*Direct Value Assignment (upon initialized):] To assign a value to the
  104. wrapped object.
  105. * [*Direct Value Assignment (upon uninitialized):] To initialize the wrapped
  106. object with a value obtained as a copy of some object.
  107. * [*Assignment (upon initialized):] To assign to the wrapped object the value
  108. of another wrapped object.
  109. * [*Assignment (upon uninitialized):] To initialize the wrapped object with
  110. value of another wrapped object.
  111. * [*Deep Relational Operations (when supported by the type T):] To compare
  112. wrapped object values taking into account the presence of uninitialized states.
  113. * [*Value access:] To unwrap the wrapped object.
  114. * [*Initialization state query:] To determine if the object is formally
  115. initialized or not.
  116. * [*Swap:] To exchange wrapped objects. (with whatever exception safety
  117. guarantees are provided by `T`'s swap).
  118. * [*De-initialization:] To release the wrapped object (if any) and leave the
  119. wrapper in the uninitialized state.
  120. Additional operations are useful, such as converting constructors and
  121. converting assignments, in-place construction and assignment, and safe
  122. value access via a pointer to the wrapped object or null.
  123. [endsect]
  124. [section The Interface]
  125. Since the purpose of optional is to allow us to use objects with a formal
  126. uninitialized additional state, the interface could try to follow the
  127. interface of the underlying `T` type as much as possible. In order to choose
  128. the proper degree of adoption of the native `T` interface, the following must
  129. be noted: Even if all the operations supported by an instance of type `T` are
  130. defined for the entire range of values for such a type, an `optional<T>`
  131. extends such a set of values with a new value for which most
  132. (otherwise valid) operations are not defined in terms of `T`.
  133. Furthermore, since `optional<T>` itself is merely a `T` wrapper (modeling a `T`
  134. supertype), any attempt to define such operations upon uninitialized optionals
  135. will be totally artificial w.r.t. `T`.
  136. This library chooses an interface which follows from `T`'s interface only for
  137. those operations which are well defined (w.r.t the type `T`) even if any of the
  138. operands are uninitialized. These operations include: construction,
  139. copy-construction, assignment, swap and relational operations.
  140. For the value access operations, which are undefined (w.r.t the type `T`) when
  141. the operand is uninitialized, a different interface is chosen (which will be
  142. explained next).
  143. Also, the presence of the possibly uninitialized state requires additional
  144. operations not provided by `T` itself which are supported by a special interface.
  145. [heading Lexically-hinted Value Access in the presence of possibly
  146. uninitialized optional objects: The operators * and ->]
  147. A relevant feature of a pointer is that it can have a [*null pointer value].
  148. This is a ['special] value which is used to indicate that the pointer is not
  149. referring to any object at all. In other words, null pointer values convey
  150. the notion of nonexistent objects.
  151. This meaning of the null pointer value allowed pointers to became a ['de
  152. facto] standard for handling optional objects because all you have to do
  153. to refer to a value which you don't really have is to use a null pointer
  154. value of the appropriate type. Pointers have been used for decades—from
  155. the days of C APIs to modern C++ libraries—to ['refer] to optional (that is,
  156. possibly nonexistent) objects; particularly as optional arguments to a
  157. function, but also quite often as optional data members.
  158. The possible presence of a null pointer value makes the operations that
  159. access the pointee's value possibly undefined, therefore, expressions which
  160. use dereference and access operators, such as: `( *p = 2 )` and `( p->foo() )`,
  161. implicitly convey the notion of optionality, and this information is tied to
  162. the ['syntax] of the expressions. That is, the presence of operators `*` and `->`
  163. tell by themselves —without any additional context— that the expression will
  164. be undefined unless the implied pointee actually exist.
  165. Such a ['de facto] idiom for referring to optional objects can be formalized
  166. in the form of a concept: the __OPTIONAL_POINTEE__ concept.
  167. This concept captures the syntactic usage of operators `*`, `->` and
  168. contextual conversion to `bool` to convey the notion of optionality.
  169. However, pointers are good to [_refer] to optional objects, but not particularly
  170. good to handle the optional objects in all other respects, such as initializing
  171. or moving/copying them. The problem resides in the shallow-copy of pointer
  172. semantics: if you need to effectively move or copy the object, pointers alone
  173. are not enough. The problem is that copies of pointers do not imply copies of
  174. pointees. For example, as was discussed in the motivation, pointers alone
  175. cannot be used to return optional objects from a function because the object
  176. must move outside from the function and into the caller's context.
  177. A solution to the shallow-copy problem that is often used is to resort to
  178. dynamic allocation and use a smart pointer to automatically handle the details
  179. of this. For example, if a function is to optionally return an object `X`, it can
  180. use `shared_ptr<X>` as the return value. However, this requires dynamic allocation
  181. of `X`. If `X` is a built-in or small POD, this technique is very poor in terms of
  182. required resources. Optional objects are essentially values so it is very
  183. convenient to be able to use automatic storage and deep-copy semantics to
  184. manipulate optional values just as we do with ordinary values. Pointers do
  185. not have this semantics, so are inappropriate for the initialization and
  186. transport of optional values, yet are quite convenient for handling the access
  187. to the possible undefined value because of the idiomatic aid present in the
  188. __OPTIONAL_POINTEE__ concept incarnated by pointers.
  189. [heading Optional<T> as a model of OptionalPointee]
  190. For value access operations `optional<>` uses operators `*` and `->` to
  191. lexically warn about the possibly uninitialized state appealing to the
  192. familiar pointer semantics w.r.t. to null pointers.
  193. [caution
  194. However, it is particularly important to note that `optional<>` objects
  195. are not pointers. [_`optional<>` is not, and does not model, a pointer].
  196. ]
  197. For instance, `optional<>` does not have shallow-copy so does not alias:
  198. two different optionals never refer to the ['same] value unless `T` itself is
  199. a reference (but may have ['equivalent] values).
  200. The difference between an `optional<T>` and a pointer must be kept in mind,
  201. particularly because the semantics of relational operators are different:
  202. since `optional<T>` is a value-wrapper, relational operators are deep: they
  203. compare optional values; but relational operators for pointers are shallow:
  204. they do not compare pointee values.
  205. As a result, you might be able to replace `optional<T>` by `T*` on some
  206. situations but not always. Specifically, on generic code written for both,
  207. you cannot use relational operators directly, and must use the template
  208. functions __FUNCTION_EQUAL_POINTEES__ and __FUNCTION_LESS_POINTEES__ instead.
  209. [endsect]
  210. [endsect]