Boost logo

Boost :

Subject: Re: [boost] [variant] Warning: variadic templates in boost::variant
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2013-12-09 23:36:50


On Mon, Dec 9, 2013 at 12:28 PM, Peter Dimov <lists_at_[hidden]> wrote:

> Steven Watanabe wrote:
>
>> The difference between tuple<> and variant<> is that tuple<> has exactly
>> one possible value, but variant<> has no possible values.
>>
>
> Not conceptually. tuple<X,Y> is struct { X x; Y y; }. variant<X,Y> is
> union { X x; Y y; }. tuple<> is struct {}. variant<> is union {}. All are
> valid.
>
> It's not that important though. The current variant doesn't support this
> case, so there's not much reason for the variadic one to do so. Sorry for
> bringing it up.

I'm going to have to back you up here that a variant<> does sometimes make
sense and I don't think we'd lose anything by supporting it. In real,
non-hypohetical code, I've encountered a place where I had a 0-element
variant come up and had to special-case my code so that it would work as
expected. The way it came up was I had a variant of several types (the type
list was the result of some metaprogramming) and a visitor of that variant
that returned the result of a member function call on the currently stored
object, whichever one it was (each type in the variant had the same named
function but the return type wasn't necessarily the same). I constructed
the return type based on the return types of the functions in question,
eliminating any duplicates. If one of the functions returned a void type,
no type was added to the list. I stored this result and later on did things
with it (such as display it).

What this meant in practice was that I was sometimes left with 0-element
and 1-element variants. It would be nice if the 0 case just worked as
expected rather than having to special-case. As well, in the case of a
single-element variant, it would be nice if the ID weren't explicitly
stored since it would always be the same value (I don't remember if
Boost.Variant makes this optimization). If there is some ambiguity with how
a 0-element variant should be handled, then I'd say perhaps we should leave
it as a compile-time error, but I think that in practice you'd just expect
it to be a stateless type that either always does nothing when visited,
passes some kind of special tag type when visited (this might be better
since it would work with n-ary visitation), or simply produces a
compile-time error when visited. I don't know what this means with respect
to Variant's "never-empty" guarantee or the result of .empty(), but
intuitively I'd just say that a variant satisfies the never-empty guarantee
iff the amount of types it is over is greater than 0. In the 0 case,
empty() would return false (it should also be static constexpr in any case).

-- 
-Matt Calabrese

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