"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

Reply via email to