|
Boost : |
Subject: Re: [boost] [variant] Warning: variadic templates in boost::variant
From: Larry Evans (cppljevans_at_[hidden])
Date: 2013-12-10 08:47:35
On 12/09/13 22:36, Matt Calabrese wrote:> 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).
>
Such a type of "nullable" variant<> exists as
container<one_of_maybe,Index0,T...> here:
Index0 is a enumeration value.
The T's in T... are matched with
Index0, Index0+1, ... Index0+sizeof...(T)-1.
This allows duplicates in T... .
The "special value" you mention is Index0-1. At that special value,
what's stored in this "nullable" variant is a "special value" as
described in comments here:
Note there 2 types of "special values" for when sizeof...(T) is 0.
One is for tuple types and one is for variant types. As mentioned, the
variant types are named container<one_of_maybe,....> and the tuple
types are named container<all_of_aligned,...>.
-regards,
Larry
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk