Boost logo

Boost :

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


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