-
Notifications
You must be signed in to change notification settings - Fork 68
Description
(Took a while to get this posted, but here is sort of my line of thinking.)
References cannot be default constructed or changed to point to a different address. So when assignment to one reference from another is performed, the value the right-hand reference points to is copied over the value in the left-hand reference:
int i1 = 1;
int i2 = 2;
int & ir1 = i1;
int & ir2 = i2;
ir1 = ir2;
cout << i1; // Will output 2
Using std::experimental::optional gives a different result:
int i1 = 1;
int i2 = 2;
optional<int &> ir1 = i1;
optional<int &> ir2 = i2;
ir1 = ir2;
cout << i1; // Will output 1
There has apparently been lengthy debate on the subject of whether optional references should act more like references in this case (copying their target values) or more like pointers (retargeting to the new reference). The conclusion is summarized here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3527.html#optional_ref.rationale.assign
This statement is made:
Neither of these models appears more valid than the other.
Not having easy access to the full range of debate, I wanted to mention something that seems it would be addressed in that document but is not.
What I think tips the scale to where it is not all equal is that many cases of optional will come by introduction into existing codebases...perhaps they could be piecewise transforming a T into an optional<T>. In this light, the difference seen in my integer reference transformation above would be a source of error. Such sources of error can be big problems in large codebases attempting to leverage a new standard library feature. And of course, they get trickier if they're not source-level but in general-purpose abstractions, that used to work one way but now work differently.
If std::reference_wrapper did not exist, then perhaps there would be a stronger argument to have optional adopt this container-friendly behavior. Yet the composability of C++ is reliant upon the parts following predictable rules; and breaking those understandings leads to things like auto_ptr. I'd argue this case shows optional<T> deviating in its characteristics relative to T in a way that I think is beyond the scope of its proposal...and could be achieved other ways. Achieving a smoother transition from T to optional<T> cannot be achieved another way.
So it seems to me that the assignment of an optional reference to another should fail with a runtime error on nullopt source or target, and do a value copy assignment if they both contain a reference. If it's too late to consider such a change, then perhaps at least this line of argumentation could be addressed in the proposal...as it currently does not seem to be.