Subject: Re: [boost] [variant2] Need rationale for never-empty guarantee
From: Robert Ramey (ramey_at_[hidden])
Date: 2019-03-01 16:50:25
On 2/28/19 5:13 AM, Andrzej Krzemienski via Boost wrote:
> Hi Peter,
> Thank you for writing and sharing this implementation of variant.
> I am sorry if I am bringing back an issue that has been already discussed
> and solved before, but I do not understand the rationale behind doing
> compromises in order to provide the never-empty guarantee.
At the risk of inserting something totally irrelevant, I'd offer my own
experience with variant types.
In my case this comes up as the result of an integer operation which
might produce an integer or some error condition such as
positive_overflow. I've characterized this as "extended integer type"
as opposed to "integer" which has infinite range. These types can take
on a value from 0 to some N or one value of and enum. Arithmetic
operations are defined so that if i and j are both extended integer
types, i + j is defined for all types. For example if i & j both hold
values "positive_overflow" then i + j would result a value of
"positive_overflow". (For those who are interested - the set of values
representable by this type and the addition operator constitute a
non-associative, commutative group. So the concept is well defined.)
Also, of late, I'm been influenced by the discussions about "monad" and
it's value in provably correct programs generally.
Of course "variant" comes to mind immediately when a C++ programmer
starts thinking about this. I looked into it and was dissatisfied with
the complexity and ambiguity of the current offerings. I started to
think about writing my own. This is always a red flag that something's
very wrong somewhere.
I eventually concluded that the source of my difficulties was the
assignment operation. This of course is derived from the idea that a
C++ type should be in general mutable. But the idea that an instance of
s set "extended integer" can change to a different member of the same
set is mathematically weird. This is why assignability conflicts on
fundamental level with the ideas behind functional programming - an idea
which has influenced me. So I implemented "extended integer" in the
simplest way possible - and deleting the assignment operator. Seems to
me that this resolved all my issues. In the few occasions I've been
inclined to use assignment, I've found that code was either flawed or
could easily be refactored to avoid the need for assignment.
I didn't need any "library" type solution as my the implentation of my
ad hoc solution is/was trivially obvious. For those interested you can
see in the safe numerics library as the type "checked_integer".
C++ starts from the idea that every instance should be mutable and hence
gives you an assignment operator by default. The design discussions
around variant (expected, outcome, ...) presume that this operation must
be implemented. I question this. Not only for variant, but for many
other C++ data types.