
Joel de Guzman <joel@boost-consulting.com> writes:
David Abrahams wrote:
Joel de Guzman <joel@boost-consulting.com> writes:
Rebinding semantics are there _precisely_ and _only_ to solve a problem posed by nullability.
Sorry, I don't buy that.
Why not?
I think this is again an artifact of the confusion between the dual interfaces that optional provides. optional has an identity crisis of being a pointer (as the author's original model) and a variant<T, nil> (which I suggested later on). The rebinding behavior that Fernando rationalized was long and winding and confusing. I don't recall anymore his exact rationale. All I know is that when you have to explain your design using so much wordings, then something is wrong, and I don't buy the gobbledegook.
I *really* don't have an opinion about what the right choice should be. That said, terms like gobbledegook seem needlessly judgemental, and as such I think they only cloud the issues.
There *is* an alternative design which is a lot simpler and I've been saying that again and again: do as the structs do.
I guess you're assuming optional<T&> maps onto a struct with a T& member? That model is not 100% obvious to me. The only way to initialize a plain struct with a reference member is using an initializer list, and the assignment operator for such a struct can't be used. struct X { int& y; }; int z = 3; X x = { z }; X y( x = x ); -- "ComeauTest.c", line 1: error: implicitly generated assignment operator cannot copy: reference member "X::y" struct X { int& y; }; ^ detected during implicit generation of "X &X::operator=(const X &)" at line 5 So "the structs" in this case are never that simple, and they don't provide a guide for what to do with optional<T&>, since the assigment behavior for reference members is always explicitly decided by some class designer.
It is easier to visualize and understand and ultimately to explain. A more complex design and behavior will surely lead to more gotchas.
Seems to me there's plenty of room for confusion in the behavior you want. optional<X&> o; X x; o = x; // Reference bound; no copy ctor called. o = x; // X's copy ctor called
Keep it as simple as possible. variant<T&, nil> does the right thing. I don't understand why optional can't.
Surely it _can_ do the same thing as variant<T&, nil>. It's just not as obvious to everyone that it's the "one true behavior" for optional<T&>. It's not like we're discussing the choice between Emacs and every other editor on the planet ;-)
Perhaps it's because of the dual pointer interface. But, like Mat Marcus, I also don't buy the pointer model: "Pointers can be null or dereference-able, Optionals can be null or dereferenceable, therefore Optionals are models of Pointers".
I don't know if anyone actually made that argument or not, but optionals don't have to be models of Pointers in order to justify the operator*, operator->, and operator safe_bool. The Pointer and Optional concepts could be refinements of some concept that includes nullability and dereferenceability. I'd really like to see a careful and non-judgemental comparison of the two possible design choices, describing the advantages and disadvantages of each one. Until we see something like that, I doubt we will be able to come to a useful consensus. -- Dave Abrahams Boost Consulting www.boost-consulting.com