Joel de Guzman <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > Fernando Cacciola <[EMAIL PROTECTED]> wrote: > > Hi Mat, > > > > Thanks for the input. > > > > optional<> is now out on the field and it is the only utility of its kind > > I've ever seen in C++, at least in real use. This has the drawback that there > > is very little experience with it. Therefore, in a way it is a sort of > > There's a lot of experience with it in other languages. Why not leverage that? > Haskell::Maybe for instance. > Do you know of anything else besides Haskell? I don't, and I took the time to investigate Maybe looking at Haskell programs using it. As Brian pointed out, it is not so easy to port Maybe to C++ because its usage is extensively supported by Haskell features that are not present in C++. The most fundamental point is that being Haskell a pure functional language there is no possibly undefined behaviour to worry about, so Maybe doesn't need to address this issue as optional<> does.
> > > experiment, even though it is now a fixed part of Boost. > > optional<> will evolve, that's for sure, as user's experience show which > > design desicions were right and which were wrong. > > I might even deprecate it and submit a replacement if it becomes clear that a > > drastic change is neccesary. > > > > Right now I still believe that the pointer-like interface is correct, because > > I add it specifically to solve a real problem and it did solve it. > > My first optional (named differently then) had the problem that it was really > > difficult to track which variables were 'optionals' and hence it was easy to > > forget to make the neccesary steps to mantain integrity (not to use an > > uninitialized optional). At some point I realized that I needed something at > > the syntax level that help me keep in mind that those variables are possibly > > uninitialized, and so I moved from value() member functions to operatos * and > > -> > > If that's the only rationale for having the pointer-like interface, then pardon > me but, I find that very flimsy. There should be other means to attack the > problem (if it is a problem) without sacrificing the beauty of the interface. > I account the possibly undefined behavior of accesing an uninitialized optional as a real and important problem. >From now on I'll refer to this as the Possibly Uninitialized Problem: the PU problem in short. The interface, in one way or another, should address this. > > The pointer-like interface is just about syntax really. > > Instead of opt.value() you type (*opt) or opt-> > > This alone shouldn't be a problem. > > Right. > > > What I think it is a problem are other design descicions that I made in order > > to make other parts of the interface with the pointer-like interface. Namely, > > the lack of implicit construction and direct assignment. > > Sacrificing this in order to "track which variables were 'optionals'" ?, IMO, > is not a good idea. > I agree. > > > These two points are raised here by Mat and have been raised by many others > > in the past. > > > > My main argument is that if those were allowed, you could write: > > > > optional<int> opt ; > > opt = 1 ; > > int i = *opt ; > > > > and the assymetry didn't look right to me. > > If optional had value semantics, it would be a lot cleaner: > > optional<int> opt; > opt = 1; > i = opt; > First of all, let's not confuse syntax with semantics. optional<> HAS strict value semantics. If the choice of 'operators *', 'operator ->' and 'get()' as value accessors makes the appearance that is has pointer semantics, then it is the documentation that has to be fixed, not the interface. vector<>::begin returns an object with operators * and ->, yet these objects are not pointers, and once that is learned, people do not think they are pointers. Also, let's not think of the pointer-like interface as a unity: there are three items involved, namely *,-> and get(). We'll be better off considering them separately. Direct initialization: opt = 1 seems right since this operation is never undefined. This would mirror variant's interface. Direct value accesing via implicit conversion: int i = opt seems wrong because this is the operation that can lead to undefined behaviour. > For those concerned about "track"ability, they can use an easy to > grep alternative: > > optional<int> opt; > opt .reset(1); > i = opt.get(); > Addressing the PU problem via a 'get()' function returning a _reference_ seems right, but OTOH, using operator * seems even better because the expressions of the form (*a) have a very familiar meaning and is that meaning _exactly_ what we need here. But don't let the rest of the optional<> interface get in the way of this argument. If we agree that _some_ explicit function/operator is needed as a value accesor, then in itself, operator* is IMO clearly the best choice. > > Now I understand that generic uses of optional<> beg for conventional > > 'syntax' for assignment and initialization. > > True! > > > I could drop the pointer-like interface but only if replaced by some member > > function that aids to the fact that the value being accessed may be > > undefined, that is, I know from previous experience that the following code > > better be invalid: > > That's a very reasonable solution. > > [snip] > > > Today, on the face of all the versions I've tried and the user report I have > > now about the uses you want but are unsupported, I will carefully think about > > adding direct initialization and implict construction yet retaining the > > To be honest, I'm not really so sure about implict construction. > Why? variant supports implicit construction, FWIW. The key is not to provide an implicit convertion to T at the same time. > > pointer like interface which is intended to be a familiar 'syntax' for > > _accessing_ the optional in those contexts were uninitialized optionals have > > undefined behavior. > > Is the pointer like interface really worth keeping? I think the right question is: is each of the value accessors operator*, operator-> and T* get() the right choices for what they provide? The answer you be given for each of them separately. >That's the point Mat was trying to make, right? Not really. He complained about the pointer-like interface because _other_ parts of the interface were wrong and the pointer-like part was used as an excuse. If optional<> supports implicit conversion and direct initialization, as variant does, then Mat's problems are gone, and there is no need to drop the pointer-like interface, at least not all of it. > IMO, I can't see a reasonably balanced rationale, yet. > The pointer like interface sacrifices a lot for a small gain: > Actually, the pointer-like interface per see does not sacrifice anything. The other related decisions do. So let's fix _that_ instead of dropping what I believe is a useful part of the interface. > to make it easy > to detect automatically. For those who are concerned that this is indeed a > problem, why son't they just use: opt.get(). Surely, that's very easy to track. > opt.get() is easy to track but it doesn't tell anything to the eye. *opt and opt->foo(), OTOH, convey very clearly the existence of possibly undefined behaviour. The current get() is another story. I agree that it should return a reference, but I'll address it in more detail in another post. Fernando Cacciola _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
