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