Boost logo

Boost :

From: Mat Marcus (mmarcus-boost_at_[hidden])
Date: 2003-08-31 13:11:10

--On Sunday, August 31, 2003 1:35 PM -0400 Brian McNamara
<lorgon_at_[hidden]> wrote:

> So I completely disagree that optionals should mix the interfaces of
> optional and the wrapped object into one. I think there should be an
> explicit unwrapping operation. But this is just my opinion, based
> on no practical evidence/experience, and I'm sure there are
> trade-offs either way. I'll explain the crux of my own reasoning
> below.
> On Sun, Aug 31, 2003 at 11:59:42PM +0800, Joel de Guzman wrote:
>> It's really strange (and hard to explain) that you have to
>> dereference optional<B>. Example:
>> F(tuple<A, optional<B>, C> args)
>> {
>> A a = get<1>(args);
>> B b = *get<2>(args); // strange!
>> C c = get<3>(args);
>> }
> I don't think it's strange at all; an optional<B> is not a B!

That doesn't make it a pointer to B! I think the above code is strange
for two independent reasons. First, as I said before I think that
though pointers may model possibly uninitialized variables, the
converse does not always hold. Second, I think that it might be useful
to treat variables and possibly uninitialized variables uniformly as
much as possible (except where it overly compromises safety). I hold
strongly to the first argument, though I admit that the second one may
not stand up in the end.

>> Not only is it strange, it complexifies the code a lot when the
>> code is automatically generated by some meta-program. Example:
>> template <class A, class B, class C>
>> F(tuple<A, B, C> args)
>> {
>> A a = get<1>(args);
>> B b = get<2>(args);
>> C c = get<3>(args);
>> }
>> Whoops, have to do a special case IFF B is an optional!
> Well, no. B==optional<Bprime> via template unification, right?
> If you want to do something with a Bprime, then yes, you have to
> special-case it, as you should.
> Here's a (contrived) example of how the implicit conversion breaks
> generic code:
> template <class Container>
> void contrived( Container& c ) {
> c.begin();
> }
> ...
> vector<int> v;
> contrived(v); // fine
> optional<vector<int> > ov( v );
> contrived(ov); // fails
> The point is that optional<T> is not a T, and most notably, a
> template function will never perform the coercion. Replace the
> lines like B b = get<2>(args);
> in your example with real calls to, e.g.
> do_something( get<2>(args) )
> and do_something() is likely to fail if it's a template function
> (expecting a T and not an optional<T>).
> As another example, FC++ lists support conversion-to-bool

There's conversion-to-bool again. I still wonder whether dispensing
with this would open the door to implicit conversions.

> as a test
> for NIL:
> fcpp::list<int> l = NIL;
> if( l ) // if l not empty
> cout << head(l); // print first element
> Clearly if 'l' were an optional, the "if" test would have a different
> meaning. I know you've been supporting a separate way to do the test
> (with "==none"), but I think that's completely arbitrary. The two
> issues are both really the same issue, in my mind.

I'm still not clear as to why.

>> Of all the types involved in the passing of arguments to the
>> semantic actions, the optional doesn't fit nicely because it is the
>> only one that has mixed value/pointer semantics. I am tempted to
>> not use optional<T> because of this and instead use variant<T,
>> none>, but I hate to miss the performance advantage of optional vs.
>> variant<T, none>.
> I have not used variant and know little about it, but I imagine you
> have to explicitly tell a variant "which type" you expect to get out
> of it. I think the same is true of optional; the call to operator*()
> (or whatever) says "I want the T type" (rather than the 'none').
> My two cents. Again let me stress I'm arguing based on no practical
> experience working with any of these datatypes.
> --
> -Brian McNamara (lorgon_at_[hidden])

 - Mat

Boost list run by bdawes at, gregod at, cpdaniel at, john at