Boost logo

Boost :

From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2005-10-18 09:24:04


Sam Partington wrote:
> Hi there,
>
> Firstly whilst reviewing this thread and the optional docs I spotted a
> couple of minor typos :
>
> "(Re)binds thee wrapped reference." : thee -> the
> "untitialized" -> uninitialized
>
> In the In-place factory discussion, the last code segment has been
> corrupted slightly : template<class inplacefactory=""></class>
>
> should presumably be :
>
> template&lt;class InPlaceFactory&gt;
>
Ha, thanks.

> Also, whilst the docs I think in general are good, I find some of the
> acronyms used in the docs slightly too informal for formal
> documentation, for instance IMO and w.r.t.. Whilst they are well
> known, it does cause the brain to stall momentarily whilst trying to
> understand some quite difficult concepts.
>
OK.

> Now, onto the discussion at hand.
>
> I must admit I find the whole rebinding interface very ambiguous.

Just to keep the discussion clear, is a matter of semantics not interface.

>
> What we have is a reference that is potentially null.
> In my mind that is a pointer (wrapped up obviously),
> and not an optional at all.

Maybe you meant "not a reference at all"?
Well, in optional<> this is implemented as a true reference, not as a
pointer like in reference_wrapper().
So is more like that there is a reference or nothing.

> I use a class called ref_ptr<> for that purpose, and it has served me
> well - A smart pointer with no ownership.
>
> That this discussion is going on so long and is so disputed it seems
> to me that there is no right-way, and the best way of fixing it is to
> disallow T& altogether.
>
This is one choice, yes.
I hope we can solve it because dorpping T& totally breaks generic
programming.

> But if it were to stay I would say that the rebinding is very
> surpising for someone used to using references.

And so is the no-rebinding alternative.
Look for _my_ thought experiment in another pos.
Do it yourself, show it to your mate, and share with me the results.

>
> In the rationale the first example states "If you assign to an
> uninitialized optional<T&> the effect is to bind (for the first time)
> to the object. Clearly, there is no other choice".
>
> [...]
>
> Remove the operator=(const T&)
>
Yes, this could also work.
Initially I was against such operator, but for the wrong reasons, so in the
end I accepted it.

> int i = 0;
> optional< int & > o(i);
> int n = 0;
> *o = i; // assigns new value
> o = optional<int&>(i); // rebinds, nice and explicitly

The problem which was raised is that it adds an unnecesary verbosity.
That is, why can't you define:

o = val ;

as a convenient shortcut for:

o = optional<T>(val);

All by itself, is looks quite reasonable.

Now you brought this issue back but into the context of optional references.

Is it totally clear to everyone that this rebinds?

o = optional<int&>(i);

Joel de Guzman said that he wouldn't be against rebinding in this case. He's
against rebinding in the direct-assignment case, so simply dropping
direct-assignment is definitely a way out, even at the cost of dropping some
sugar.
One could say: optional does not support a convenient direct assignment
operator becasue it could hide the true semantics of the assignment, which
are clear if only assignment from another optional is used. (Followed by an
example)

A related note about the use of operator *

You said that, even for optional<T&>, it is clear that this:

 *o = i;

is UB if 'o' is uninitialized. And so there is no problem defining that
assignment as really just the assignment of the underlying type, which in
the case of optional<T&> doesn't rebind.

Now I wonder, if instead of operator*, we used value() (or whatever), would
it be just as clear?
Consider:

int a = 1 ;
int b = 2 ;
int c = 3 ;
int& ra = a ;
int& rb = b ;
int& rc = c ;
optional<int&> o(ra) ; // binds to a

// Nullable interface

*o = rb ; // assing 'b' to 'a'
o = none ; // releases 'a'
*o = rc ; // !!! UB !!! Cleary IMO

// Container interface

o.value() = rb ; // assing 'b' to 'a'
o.reset() ; // releases 'a'
o.value() = rc ; // !!! Still UB !!! ¿But cleary enough?

-- 
Fernando Cacciola
SciSoft
http://fcacciola.50webs.com/

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk