Subject: Re: [boost] [optional] Thoughts on disallowing assignment for wrapped references.
From: Mostafa (mostafa_working_away_at_[hidden])
Date: 2011-09-01 08:51:22


On Wed, 31 Aug 2011 09:41:58 -0700, Fernando Cacciola
<fernando.cacciola_at_[hidden]> wrote:

> Hi Mostafa,
>
> Let me start by warning that this discussion is likely to wind up in an
> endless argument, and I might not have the time to follow up. In any
> case, if you google for it you should be able to find the really long
> discussions that led to the current choice.
>

Just to clarify, I'm not arguing for or from a certain position, rather,
I'm looking for enlightenment as to what the consequences of disallowing
the assignment operator for optional<T&> are.

I would be greatly disappointed if you did not follow up to any of my
direct queries to you, even if it is just a pointer to look elsewhere.

> From the 3 possible choices, each one favors certain aspects at a
> certain expense, so no choice is a sensible winner, yet one has to be
> made, and so I did.
>
> A lot of people is concerned with the current semantics. And a lot of
> people was concerned with the old semantics (it used to assign the
> referee). In fact, the main reason (if not the only one) why
> Boost.Optional did not make it into Cpp0x is precisely the concerns
> about choice of assignment semantics for references.
>
> The problem with disabling assignment all toghether is basically the
> same as assigning the referee instead of the wrapper: it breaks
> consistency.
>
> In a highly generic context, which is so typical in modern C++, the T in
> optional<T> might very well be itself a reference type, so any special
> behavior might result in an practical shotcomming, even possibly a show
> stopper: it could simply rule out optional<> as an element of a generic
> library.
>
> To be a little more precise:
>
> A library that uses optional<T> such that the choice of T is entirely
> external to the library *requires* that optional<> is completely
> consistent regardless of T. If it where to behave specially in the case
> T is a reference type (or for that matter, a non-POD type, a compound
> type, or whatever) then the library itself would have to explicitely
> handle all such differences.
> Recall that in a generic context, the typename T could very well be a
> reference type even without the &, so any time you consider what
> optional<T&> should do, substitute that for optional<U> and think again.
>
> The current choice is to favor consistency for the sake of generic
> libraries, where the library itself would not discriminate whether T
> happens to be a reference type or not.
>

Ok, I think I understand your argument. To clarify, by consistency here
you mean consistency of programming in a generic environment, so that, as
you say, a generic library would not have to discriminate between T and T&.

Disclaimer1: What I will say below may have already been discussed, if so,
please feel free to tell me to google it.
Disclaimer2: I have very little experience with writing generic libraries
in the C++ sense.
Disclaimer3: Besides the documentation, I have no experience in actually
using optional.

What are the consequences of doing away with the assignment operator
totally, and just having a no-parameter reset method that resets
optional<...> state to uninitialized?

In my naive point-of-view, the majority of Boost.Optional use case would
involve member-variable types, or interface level types, ie, parameter
types and return types. Racking my brain, I can't think of a draw back
with respect to this use case if the above thought experiment were carried
out.

> Keep in mind that
>
> *Assignment to optional<T> is simply not the same as assignment to a T*.
>
> It cannot possibly be for the simple fact that you cannot assign to
> nothing. Hence, optional<> itself must define *its own* assignment
> semantics, so the argument that it should follow the assignment
> semantics of the underlying T is not that strong because it clearly
> cannot do that on all cases (when the lvalue is empty). It is a sensible
> argument of course, but it must be weighted against the equally sensible
> counter argument that it breaks consistency.
>

To clarify, in explaining my motivation for the intent of this thread I
was saying that a casual programmer would expect that the assignment
semantics of T would be a subset of the assignment semantics of
optional<T>, not the other way around.

In general, for any wrapper type class "wrap" and wrapped type T, I think
that a casual programmer would expect the semantics of the "natural
operations" of T to be a subset of the semantics of the those same
operations wherever defined on wrap. The reasoning being that the casual
user of wrap who is accustomed to the conventions of T will not be unduly
surprised when he/she applies those same conventions to wrap. And in this
sense, there is no inconsistency between T and wrap, since the "natural
operations" of T just seem to work with wrap, whenever wrap truly
represents its underlying type.

But, this is tangential to the intent of this thread.

>
> P.S.: Please do not just counter argument my counter arguments without
> having first googled, read and processed this very same discussion in
> the past.

Fair, I understand not wanting to sound like a broken tape recorder.
IMHO, this indicates a need to add a general "Design Rationale" section to
the documentation, maybe incorporating summaries of the discussions that
you allude to.

Thanks for your enlightening response,

Mostafa