"William E. Kempf" <[EMAIL PROTECTED]> escribi� en el mensaje [EMAIL PROTECTED]">news:[EMAIL PROTECTED]... > > Fernando Cacciola said: > > [snip William's comments about the interface with operator T&] > I agree with your comments about the interface with operator T&. I show it in the post, actually, because I wanted to follow again the line of reasonging I had in the past. That interface didn't had safe_bool but it was a bad choice anyway.
> > Safe_bool will allow the familiar idioms: > > > > if ( opt ) > > if ( !opt ) > > if ( opt == 0 ) > > if ( opt != 0 ) > > > > The first form, which is probably the most used, comunicates exactly > > what it means. > > But the second form, using operator ==, appears to me confusing for > > value-semantic objects because a comparison against 0 as indication of > > uninitialization is typical of pointers but not of containers. > > Some would consider it confusing, and they'd just avoid using it. Others > won't, and I see no reason to prevent them from using this. > Actually, *I* wouldn't find it that much confusing either. I was thinking of it from the POV of those who see the pointer-like interface confusing: I argue that if we want to have 'ref()' instead of 'opertor*()' because the later makes optional look like something it isn't; then safe_bool would confuse just the same, so either we keep safe_bool and the rest of the pointer-like interface (because safe_bool is itself a pointer-like interface) or we drop both. > > No container-like object that I know of uses that idiom to indicate > > emptyness() so I believe it would we wrong to have it in this sort of > > interface > > > > As a conclusion, I agree that it is possible to model optional<> > > entirely as a 1-element-sequence provided that its > > interface uses explicit member funcions for both value access and > > emptyness testing. > > I can live with that, but I honestly see no reason to avoid the safe-bool. > I don't see reason either, but along the same argument I don't see reason to drop operator*() and ->() My point is that safe_bool is a pointer-like interface; you use it to write code like: if ( p ) or if ( p == 0 ); which is the behaviour of a pointer (notice that it is not comparing the optional value against 0 but its initialization state); so if this interface makes sense, then the rest of the pointer-like interface makes sense too. > > I concluded then, and I still think, that > > for the possible unexisting value access operation, > > operator*() and ->() allows for a very familiar and comunicative > > syntax which expresses _exactly_ the semantic of the operation. > > I don't agree. ref() on it's own may not indicate anything, but since the > type's name is "optional", I think everything is conveyed nicely. > Yes, but the name optional is not neccesarily near the variable name. In fact, it seldom is, AFAICT. Think about data members, for instance. > On the > other hand, operator*() and operator->() are only unambiguous in meaning > when the type fully models a pointer, which optional can not. > I disagree. It is unambiguous when this _particular part_ of the inteface fully models a pointer; and in optional<>, this part does. > > It is not just a minor convenience IMO. > > > > And to be honest, the fact that this interface allows optional<> > > to be replaced by a pointer is not the reason why I adopted it, > > and having though about droping it, I realized that it is not > > even the reason why the pointer interface is really good. > > It is really good because it comunicates _clearly_ and _each time_ you > > access an optional value that the operation will be undefined unless the > > initialized condition is met. > > For dumb programmers like me, this is a very important feature > > of the interface; and I know this based on experience, since I stop > > being caught often by uninitialized optionals<> once I adopted it. > > Are you sure that you've not just become used to the interface, and thus > don't find the "mixed metaphor" intuitive? > Entirely possible, yes. > Did you ever use an interface > with an explicit ref() and actually find it difficult to understand? > No I didn't. > > Anyway, I concede that the pointer interface is really just a visual > > aid. And of course, smart programmers don't need this aid, and can > > safely deal with whatever consistent interface you gave them. > > But I'd like to stress out that this particular aid is significantly > > important. > > I'm not so sure. > I see. ... but I'm :-) so I will hold on to it > > Anyway, I notice that _only_ operator *() and ->(), which are used to > > access the value, > > are the part of the pointer-like interface that I consider really > > important. operator safe_bool() is just handy and it is consistent with > > optional<> (a value-based container) even though it allows expressions > > of the form: > > > > if ( opt == 0 ) > > > > just because it goes along with the pointer-like interface. > > Because this expression (with the intended meaning) is used with > > pointers. I think that if the pointer-like interface is dropped, this > > should be dropped too. > > By dropping bool conversion entirely? I think you'll find this > inconvenient, especially with Mr. Dimov's classic: > > if ((opt = foo()) != 0) > My point is not to drop the bool conversion; my point is that with optional<>, this bool conversion tests for initialization state, not optional value, so if it makes sense to have it, and I think it does, it makes exactly as much sense to have operators *() and ->(). > > A pro of modeling this concept is that allows optionals<> to be > > interchanged with true pointers; but I concede that this pro is not > > really that much important. > > A con is that it could make the programmer believe it is a pointer. > > And it makes relational comparisons either non-intuitive, or difficult to > use! That's key, I think. > Agreed. This is a _big_ problem indeed. > > Since it is fundamental that optional<> is not mistaken to be a pointer, > > but rather a value-based container modeling the OptionalValue concept, > > proper documentation is not enough. > > It is required that the interface of optional<> that looks like a > > pointer follow _exactly_ pointer semantics. This way, if it comes to > > ocurr that a programmer did think that optional<> is a pointer, the code > > he wrote won't behave abnormally. > > But you can't do this with relational operations. > Right, I can't do this with relops. > > A way to measure this potential problem is to consider what would happen > > if optional<T> were actually be replaced by T* > > With the current definition of the OptionalValue concept, the code will > > have _exactly_ the same effect, so the potential danger of mistakenly > > consider optional<T> as a pointer is conceptual but not practical. > > > > However, and very unfortunately, this _requires_ the properly well > > defined relational operators to be disallowed, because they can > > effectively create practical problems if optional is mistaken for a > > pointer and used, for example, to test for aliased equivalence as you do > > when you compare pointers. > > So, just to keep pointer-like operations you're going to make the > interface difficult to use for many valid use cases? > I don't know yet. This is a though call. Having both well defined relational operators and a pointer like interface _might_ confuse people, but I don't know at to what extent. if you see: if ( opt0 == opt1 ), out of context, you expect this to do _exactly_ 0what it would actually do with a value-based definition of relops. The only problem is if you see this _and_ you think opt _is_ a pointer, so you think it is not comparing optional values. Therefore, we can just _require_ users to keep in mind what optional really is and have both relops and a pointer-like interface. Some people, mostly _me_, argued that this is not a good idea because code would change meaning if optional<> is replaced by a pointer. However, after I realized that not being optional a pointer, thinking it is would get you in trouble no matter how the interface tries to prevent it. I'm not so sure anymore that forbiding a useful-in-itself operation in the name of safety is really worth it. ...BTW, this is what you have been telling me from the beginning, isn't it :-) But, if I add deep relops, the problem remains, only that with a different face: optional is not a pointer even though it looks like it. If optional is used in generic code _and_ you use comparisons directly (without *), the semantics will be inconsistents. But I can choose to _prevent_ users about this mistake on the documentation. This would bring the most useful model if used properly. Fernando Cacciola _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
