]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/optional/doc/15_optional_references.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / optional / doc / 15_optional_references.qbk
CommitLineData
7c673cae
FG
1
2[section Optional references]
3
4[section Overview]
5
6This library allows the template parameter `T` to be of reference type:
7`T&`, and to some extent, `T const&`.
8
9However, since references are not real objects some restrictions apply and
10some operations are not available in this case:
11
12* Converting constructors
13* Converting assignment
14* InPlace construction
15* InPlace assignment
16* Value-access via pointer
17
18Also, even though `optional<T&>` treats it wrapped pseudo-object much as
19a real value, a true real reference is stored so aliasing will ocurr:
20
21* Copies of `optional<T&>` will copy the references but all these references
22will nonetheless refer to the same object.
23* Value-access will actually provide access to the referenced object
24rather than the reference itself.
25
26[caution On compilers that do not conform to Standard C++ rules of reference binding, some operations on optional references are disabled in order to prevent subtle bugs. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].]
27
28[heading Rvalue references]
29
30Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability, therefore to avoid surprising effects it is not possible to initialize an optional references from a temporary. Optional rvalue references are disabled altogether. Also, the initialization and assignment of an optional reference to const from rvalue reference is disabled.
31
32 const int& i = 1; // legal
33 optional<const int&> oi = 1; // illegal
34
35[endsect]
36
37[section Rebinding semantics for assignment of optional references]
38
39If you assign to an ['uninitialized ] `optional<T&>` the effect is to bind (for
40the first time) to the object. Clearly, there is no other choice.
41
42 int x = 1 ;
43 int& rx = x ;
44 optional<int&> ora ;
45 optional<int&> orb(x) ;
46 ora = orb ; // now 'ora' is bound to 'x' through 'rx'
47 *ora = 2 ; // Changes value of 'x' through 'ora'
48 assert(x==2);
49
50If you assign to a bare C++ reference, the assignment is forwarded to the
51referenced object; its value changes but the reference is never rebound.
52
53 int a = 1 ;
54 int& ra = a ;
55 int b = 2 ;
56 int& rb = b ;
57 ra = rb ; // Changes the value of 'a' to 'b'
58 assert(a==b);
59 b = 3 ;
60 assert(ra!=b); // 'ra' is not rebound to 'b'
61
62Now, if you assign to an ['initialized ] `optional<T&>`, the effect is to
63[*rebind] to the new object instead of assigning the referee. This is unlike
64bare C++ references.
65
66 int a = 1 ;
67 int b = 2 ;
68 int& ra = a ;
69 int& rb = b ;
70 optional<int&> ora(ra) ;
71 optional<int&> orb(rb) ;
72 ora = orb ; // 'ora' is rebound to 'b'
73 *ora = 3 ; // Changes value of 'b' (not 'a')
74 assert(a==1);
75 assert(b==3);
76
77[heading Rationale]
78
79Rebinding semantics for the assignment of ['initialized ] `optional` references has
80been chosen to provide [*consistency among initialization states] even at the
81expense of lack of consistency with the semantics of bare C++ references.
82It is true that `optional<U>` strives to behave as much as possible as `U`
83does whenever it is initialized; but in the case when `U` is `T&`, doing so would
84result in inconsistent behavior w.r.t to the lvalue initialization state.
85
86Imagine `optional<T&>` forwarding assignment to the referenced object (thus
87changing the referenced object value but not rebinding), and consider the
88following code:
89
90 optional<int&> a = get();
91 int x = 1 ;
92 int& rx = x ;
93 optional<int&> b(rx);
94 a = b ;
95
96What does the assignment do?
97
98If `a` is ['uninitialized], the answer is clear: it binds to `x` (we now have
99another reference to `x`).
100But what if `a` is already ['initialized]? it would change the value of the
101referenced object (whatever that is); which is inconsistent with the other
102possible case.
103
104If `optional<T&>` would assign just like `T&` does, you would never be able to
105use Optional's assignment without explicitly handling the previous
106initialization state unless your code is capable of functioning whether
107after the assignment, `a` aliases the same object as `b` or not.
108
109That is, you would have to discriminate in order to be consistent.
110
111If in your code rebinding to another object is not an option, then it is very
112likely that binding for the first time isn't either. In such case, assignment
113to an ['uninitialized ] `optional<T&>` shall be prohibited. It is quite possible
114that in such a scenario it is a precondition that the lvalue must be already
115initialized. If it isn't, then binding for the first time is OK
116while rebinding is not which is IMO very unlikely.
117In such a scenario, you can assign the value itself directly, as in:
118
119 assert(!!opt);
120 *opt=value;
121
122[endsect]
123[endsect]