
"Brock Peabody" <brock.peabody@npcinternational.com> escribió en el mensaje news:00ea01c525f2$73fb4e90$240a10ac@npci.com...
Hi Fernando,
Hi Brock
I don't know if you saw the rest of the discussion but I think that the consensus was that rebinding should be disabled on optional<T&> as you suggest, and along with it operator=. Optional<T&> would then only be initialized via constructor (like T& itself), and optional<T&>::operator= would be a compile time error rather than deferred to T::operator=. Does this seem right to you?
I'm not sure... I don't see a concensus on disabling operator= altoghether. That's overkill I think. But I definitely see your point about: int a = 1 ; int b = 2 ; int& ra = a ; int& rb = b ; optional<int&> opt(ra); opt = none opt = rb ; // rebinds in this case opt = ra ; // but not in this case! And I do see this as a problem. Disabling assignment to references altoghether would definitely solve this ambiguity but it can be too much of a change. Generic code just won't work anymore (because in generic code your T might happen to be a U&) I really think that optional<T&> should try to follow T& as much as possible, but you've shown that this can't be done completely because the effect of assignment directly depends on the original initialization state (that's why you drew a connection between being nullable and rebindable). The choices are: (1) Make optional<T&> non-assignable Pros: Gives optional's assignment a uniformly defined meaning. Cons: Badly breaks generic code. Badly because such code would be _forced_ to change completely as there won't by any way to make it work. If the final users feeds in a reference they'll get a compiler error unless the code uses *opt =val yet only when appropiate, which is an unlikely situation becuase if the value is going to be initialized before any assignment is _needed_ then probably optional<> isn't needed to begin with (2) Keep rebinding assignment Pros: Gives optional's assignment a uniformly defined meaning. Cons: It doesn't do as T& does, which means that current code is: (a) probably wrong (users are not aware of the odd semantic) (b) intentionally rebinding, which is odd if not unlikely (c) going to the trouble of using *opt=val to "fix" the bad semantics and exercising some rule about what to do if opt is uninitialized (which is very complex anyway) (3) Forward to operator=() WHEN THE LHS IS INITIALIZED or rebind when not Pros: Does as T& does when the lhs is initialized. Cons: Does NOT do as T& does when the lhs in uninitialized This probably means that client code still won't be able to "just" use operator=() without any regards to the prior initialization state, for if they do, the results are probably wrong. The way I see it: With choice (1) generic code won't compile unless it _only_ uses *opt=val to do assignment. With choice (3) generic code will compile but it might not do the right thing if it does not take into account the fact that the effect of assignment changes depending on the lhs state. I think that both (1) and (2) _requires_ the code to discriminate the initialization state prior to assignment, meaning that the the code will have to be of the form: if (!opt) [do something, but being aware that if opt wraps a reference you'll rebind it] else *opt = val ; The '*' is not required with choice (3) yet it is whith choice (1) In either case, ommitting it is "unnecesary" since this branch executes when opt is initialized. I don't think it is possible to avoid the pattern above and "just assign" unless you're willing to have differing effects depending on whether opt is initially empty or not. (and most likely you should NOT be willing to accept that) With choice (2) it is possible for generic code to "just assign": if it happens to be OK to rebind. If it isn't, user code must follow the same pattern above. Well, if my analysis was correct, choice (2) is the only one that doesn't _force_ ALL generic code to follow the pattern above. Thus, in spite of the fact that it breaks the rule "do as T& does" (becasue it can't follow it completely), it is the least impacting choice. What do you think? Best Fernando Cacciola