![]() |
Boost : |
From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2002-12-12 09:45:21
----- Original Message -----
From: "Peter Dimov" <pdimov_at_[hidden]>
To: "Boost mailing list" <boost_at_[hidden]>
Sent: Thursday, December 12, 2002 9:41 AM
Subject: Re: [boost] Formal review: Optional library
> From: "Fernando Cacciola" <fernando_cacciola_at_[hidden]>
> >
> > Let me check if I followed your logic:
> >
> > optional<T> opt(v) does a 'copy' of the 'v'; it does not hold onto the
> > 'v' itself as if it were given a handle. So it clearly has deep copy
> > semantics.
> > Your argument is that since it has deep copy semantics, it should have
> > deep-constantness
> > too, right?
>
> Right.
>
> "Pointer semantics" means that copies of the pointer refer to the same
> object. This is clearly not the case with optional<> as it contains a
value,
> it doesn't merely point to one. Optional simply does not have pointer
> semantics. It provides a pointer-like interface which may be controversial
> but I'm not convinced that better alternatives exist.
>
This is correct.
See my response to Augustus where I realize that optional<> mixes value and
pointer
semantics on two different parts of the interface.
As I argumented there, in spite of the oddity, the separation is made in
such a way that
there is no -or little- confusion (once you get how it is)
>
> > > > void swap ( optional& rhs ) ;
> > >
> > > Doesn't the standard std::swap do the job, by the way?
> > >
> > With the current implementation, yes, it does.
> > But if optional<> is eventually changed to use an implementation
> > with stronger exception guarantees, wouldn't it require a member swap()?
>
> Yes, I thought about that, too. But if the current swap semantics are
> retained, it should simply be removed. Otherwise optional<T>::swap must
> offer at least swap(T&, T&)'s guarantee.
>
I'm not sure I follow.
What are swap(T&, T&) guarantees in general?
I thought this depended on the specific type.
>
> > > > template<class T> inline T* get ( optional<T> const& opt ) ;
> > >
> > > Why the free function?
> > >
> > On the user code I **really** prefer to write: get(opt) instead of
> opt.get()
> > becasue I like to decouple from class types as much as possible.
>
> Free functions with generic names should be avoided.
>
I agree.
> > Perhaps this could be called get_pointer() as shared_ptr<> does.
>
> get_pointer() would be... less objectionable. :-)
>
This particular free function is precisely intended to decouple this
functionality (get a pointer that points to the value) from the class type
(optional<> in this case); so it makes sense to be a commonly named free
function.
But then, get_pointer() is the common name, so it has to be that one.
> > > I think that the comparisons we were discussing as a possible
candidate
> > > required both the initialized states and the held values to match.
> > >
> > > This is consistent with the "optional as a container of zero/one" and
> the
> > > "optional as a value with an additional unitialized state" models.
> > >
> > I don't follow 'exactly'
> > Can you elaborate?
>
> bool operator==(optional const & a, optional const & b)
> {
> if(a.initialized() != b.initialized()) return false;
> return a.initialized()? *a == *b: true;
> }
>
> That is, an unitialized optional is equal to an unitialized optional, and
> not equal to an initialized one.
>
> Two initialized optionals are equal when their values compare equal.
>
> If you think of an optional as a constrained std::vector<T>, you'll see
that
> the above semantics correspond to vector<>::operator==.
>
> The other way of thinking about an optional<T> is that it is capable of
> storing all possible values of type T plus an additional value
corresponding
> to the uninitialized state. In other words, optional<int> can be thought
of
> as an integer that can store INT_MIN...INT_MAX+1, with INT_MAX+1 being
> interpreted as uninitialized. The above comparison does the right thing
for
> this model, too.
>
> A variant<T, nil_t> would have the same operator==, too.
>
Well, this is exactly what William suggested.
Still I don't like it.
But thanks to William insistance on a sound rationale, I realize now that
the real problem
is not the personally-odd definition that something is definitely not equal
to nothing
(instead of undefined); since this definition doesn't look odd to many of
you,
but the fact that such definition would look ackward with respect to
the pointer-like interface.
Anyway, as I posted recently, I'm just about to conclude that relational
operators
could be properly defined as a synonim for: get_pointer(o1) .relop.
get_pointer(o2).
I found this definition totally consistent with pointer semantics and the
implied
aliasings.
Fernando Cacciola
Boost list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk