----- Original Message ----- From: "William E. Kempf" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Tuesday, December 10, 2002 7:04 PM Subject: Re: [boost] Formal review: Optional library
> > Fernando Cacciola said: > > > But if I wrote: > > > > optional<int> x = foo(); > > if ( x ) > > some(x); > > > > it really looked as if it were testing if 'x' is initialized > > while it was acutally comparing the 'x' value against 0. > > I'm not sure I find this compelling. Knowing that a test for > initialization is done through optional::initialized(), I'd never mistake > the if above for testing this. This would cause problems only with > someone unfamiliar with optional, but they are going to have problems no > matter what interface you choose until they read the documentation. > ... but I would make such mistakes, and I know too many people that would also do it. > > Eventually, I realized that value semantics are not really appropiate to > > deal > > with unininitialized states since it blurs the distinction between > > testing against other values and testing whether it is initialized or > > not. So I wonder which other semantics would deal with it properly, > > and pointers poped into my mind quickly. > > But pointers are just the inverse of the problem above. Test for validity > is bald. Only if safe_bool isn't used. But, I'm just about to be convinced to added it, in which case, test for validity will look just like it looks like for any other smart/bare pointer. >, while access to the "value" requires some supporting syntax (in > this case, operator*). This leaves users in the exact same scenario where > a simple mistake leads to code that compiles but doesn't do what the > programmer meant. Can you give me an example of something that compiles but doesn't do what the programmer meant? Remeber that currently *opt=x is defined even if opt is uninitialized > I think you're trying just a little too hard to make > the interface "idiot proof". > Fair enough. I tend to do this, I know. Maybe is becasue I use to work late at night, so I better protect myself from myself :-)) > >> Now, assuming we stick with pointer semantics, let's make this as > >> close to the "normal" smart pointer interface as possible: > >> > >> template <typename T> > >> class optional > >> { > >> public: > >> optional(); > >> explicit optional(T const& value); > >> optional(optional const& other); > >> template <typename U> > >> optional(optional<U> const& other); > >> ~optional(); > >> > >> T& operator*() const; > >> T* operator->() const; > >> T* get() const; > >> // T* release(); > >> void reset(); > >> void reset(T const& value); > >> operator unspecified-bool-type() const; > >> }; > >> > >> > > This interface is greatly simplified mainly because > > my interface offers deep-constantness: > > > > T const* peek() const ; > > T* peek(); > > T const& operator*() const; > > prxy operator*() ; > > > > instead of: > > > > T* peek() const ; > > T& operator*() const; > > > > The proxy is needed *only* to achieve deep-constantness. > > If this feature weren't introduced, my interface would have looked just > > like yours. > > I still don't see the need for the proxy. The interface I gave could > provide "deep-constantness" with out a proxy. I'm not sure where I stand > on whether or not optional<> should provide this, however. > Right. I mistakenly forgot what the proxy is for... it has nothing to do with deep-constantness... o-) it is required to support *opt=x for uninitialized optionals, which reset 'opt' to initilized. But wait.... I will have to discuss this feature (?) on its own, so I'll top post this issue. > >> Semantics and rationale: > >> > >> optional() > >> > >> Constructs an "uninitialized" optional. > >> > >> explicit optional(T const& value) > >> > >> Constructs an optional initialized to value through copy > >> construction. > >> > >> optional(optional const& other) > >> > >> Copy constructs an optional using the value-type's copy > >> constructor. > >> > >> template <typename U> optional(optional<U> const& other) > >> > >> Allows copy construction from "compatible" optionals (optionals > >> with > >> value types that can be used for constructing this optional's value > >> type). I'm not sure how important this one is for optional, to be > >> honest. > >> > > I've never needed to convert between optinals. > > On a related note, if deep-constantess is not supported > > (as in your interface), an implicit conversion from > > optional<T> to optional<T const> is needed because > > the user will have to use <T const> to attach constantess > > to the value. > > Actually, it's still not needed. > > optional<int> opt1(666); > optional<const int> opt2(*opt1); > > Granted, it *IS* an important convenience, since you don't have to check > the initialized state, but it's not strictly necessary. ? Did you mean that conversion from <T> to <T const> can only be explicit? Otherwise we said the same: there has to be a mechanism to convert from <T> to <T const> > > >> ~optional() > >> > >> If the optional is initialized, calls the value-type's destructor. > >> > > > > Why isn't assignment supplied? > > Because I believe the reset is clearer, and safer. > I see. We'll get back to this reset() issue on the post about: uninitialized assignment (doing *opt=x when opt is uninitialized) Fernando Cacciola _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost