15_optional_references.qbk 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. 
  2. [section Optional references]
  3. [section Overview]
  4. This library allows the template parameter `T` to be of reference type:
  5. `T&`, and to some extent, `T const&`.
  6. However, since references are not real objects some restrictions apply and
  7. some operations are not available in this case:
  8. * Converting constructors
  9. * Converting assignment
  10. * InPlace construction
  11. * InPlace assignment
  12. * Value-access via pointer
  13. Also, even though `optional<T&>` treats it wrapped pseudo-object much as
  14. a real value, a true real reference is stored so aliasing will ocurr:
  15. * Copies of `optional<T&>` will copy the references but all these references
  16. will nonetheless refer to the same object.
  17. * Value-access will actually provide access to the referenced object
  18. rather than the reference itself.
  19. [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].]
  20. [heading Rvalue references]
  21. Rvalue 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.
  22. const int& i = 1; // legal
  23. optional<const int&> oi = 1; // illegal
  24. [endsect]
  25. [section Rebinding semantics for assignment of optional references]
  26. If you assign to an ['uninitialized ] `optional<T&>` the effect is to bind (for
  27. the first time) to the object. Clearly, there is no other choice.
  28. int x = 1 ;
  29. int& rx = x ;
  30. optional<int&> ora ;
  31. optional<int&> orb(x) ;
  32. ora = orb ; // now 'ora' is bound to 'x' through 'rx'
  33. *ora = 2 ; // Changes value of 'x' through 'ora'
  34. assert(x==2);
  35. If you assign to a bare C++ reference, the assignment is forwarded to the
  36. referenced object; its value changes but the reference is never rebound.
  37. int a = 1 ;
  38. int& ra = a ;
  39. int b = 2 ;
  40. int& rb = b ;
  41. ra = rb ; // Changes the value of 'a' to 'b'
  42. assert(a==b);
  43. b = 3 ;
  44. assert(ra!=b); // 'ra' is not rebound to 'b'
  45. Now, if you assign to an ['initialized ] `optional<T&>`, the effect is to
  46. [*rebind] to the new object instead of assigning the referee. This is unlike
  47. bare C++ references.
  48. int a = 1 ;
  49. int b = 2 ;
  50. int& ra = a ;
  51. int& rb = b ;
  52. optional<int&> ora(ra) ;
  53. optional<int&> orb(rb) ;
  54. ora = orb ; // 'ora' is rebound to 'b'
  55. *ora = 3 ; // Changes value of 'b' (not 'a')
  56. assert(a==1);
  57. assert(b==3);
  58. [heading Rationale]
  59. Rebinding semantics for the assignment of ['initialized ] `optional` references has
  60. been chosen to provide [*consistency among initialization states] even at the
  61. expense of lack of consistency with the semantics of bare C++ references.
  62. It is true that `optional<U>` strives to behave as much as possible as `U`
  63. does whenever it is initialized; but in the case when `U` is `T&`, doing so would
  64. result in inconsistent behavior w.r.t to the lvalue initialization state.
  65. Imagine `optional<T&>` forwarding assignment to the referenced object (thus
  66. changing the referenced object value but not rebinding), and consider the
  67. following code:
  68. optional<int&> a = get();
  69. int x = 1 ;
  70. int& rx = x ;
  71. optional<int&> b(rx);
  72. a = b ;
  73. What does the assignment do?
  74. If `a` is ['uninitialized], the answer is clear: it binds to `x` (we now have
  75. another reference to `x`).
  76. But what if `a` is already ['initialized]? it would change the value of the
  77. referenced object (whatever that is); which is inconsistent with the other
  78. possible case.
  79. If `optional<T&>` would assign just like `T&` does, you would never be able to
  80. use Optional's assignment without explicitly handling the previous
  81. initialization state unless your code is capable of functioning whether
  82. after the assignment, `a` aliases the same object as `b` or not.
  83. That is, you would have to discriminate in order to be consistent.
  84. If in your code rebinding to another object is not an option, then it is very
  85. likely that binding for the first time isn't either. In such case, assignment
  86. to an ['uninitialized ] `optional<T&>` shall be prohibited. It is quite possible
  87. that in such a scenario it is a precondition that the lvalue must be already
  88. initialized. If it isn't, then binding for the first time is OK
  89. while rebinding is not which is IMO very unlikely.
  90. In such a scenario, you can assign the value itself directly, as in:
  91. assert(!!opt);
  92. *opt=value;
  93. [endsect]
  94. [endsect]