Brian McNamara <[EMAIL PROTECTED]> 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.
One can think of an optional<T> as conceptually a specialized but nevertheless, *IS-A* T, with the added specialization that it can be in a dead-uninitialized state. Maybe we'll call it a zombie object, undead object, you name it ;-) Point well taken though. > 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! Even if I agree with you that an optional<T> should not be a T, an optional<T> is definitely not a pointer to T. >> 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. You are right. That was some sloppy code above. Thanks for spotting that, but I guess you got the idea. > 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 Right. > The point is that optional<T> is not a T, and most notably, a template Your point. > 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>). Right. > As another example, FC++ lists support conversion-to-bool 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. > > >> 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'). Right. In fact, looking at it more closely, I *could* almost agree with you that an optional<T> is not a T. There is in fact a getter function (get). In fact all three (tuple, optional and variant) have a get function. That's fine, yet, here again, the optional does not jive well because it returns access *by pointer* whereas both tuple and variant return access by reference. -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost