Why does std.variant not have a tag?

evansl cppljevans at suddenlink.net
Mon Nov 5 06:13:40 PST 2012


On 11/05/12 00:33, Robert Jacques wrote:
> On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen
> wrote:
>> On 05-11-2012 00:31, evansl wrote:
>>>   http://dlang.org/phobos/std_variant.html
>>>
>>> says:
>>>
>>>  This module implements a discriminated union type (a.k.a. tagged union,
>>> algebraic type).
>>>
>>> Yet, the wiki page:
>>>
>>>   http://en.wikipedia.org/wiki/Tagged_union
>>>
>>> says:
>>>
>>>   a tag field explicitly indicates which one is in use.
>>>
>>> and I don't see any indication of a tag field in the std_variant.html
>>> page.  Another wiki reference:
>>>
>>>   http://en.wikipedia.org/wiki/Disjoint_union
>>>
>>> is more explicit because it pairs the tag with the value:
>>>
>>>   (x,i)
>>>
>>> where x is the value and i is the tag.
>>>
>>> One reason for an explicit tag is that the bounded types may contain
>>> the same type twice.  This has lead to problems in boost::variant as
>>> evidenced by the post:
>>>
>>>   http://article.gmane.org/gmane.comp.parsers.spirit.general/17118
>>>
>>> In addition, both variant and tuple have a common part, a metafunction
>>> mapping from a tag to a type; hence, this same common part could be used
>>> to implement both tuple and a tagged variant.
>>>
>>> A variant which actually contained a tag field I think would be more
>>> general in that it would allow duplicate types among the bounded types
>>> just as a tuple's bounded types can contain duplicate types.
>>>
>>> -regards,
>>> Larry
>>>
>>
>> Yes, this is a big problem with the current std.variant implementation
>> (among other problems such as no recursive variants....). The best
>> std.variant can offer right now is the 'type' property to identify
>> what's stored in it.
>>
>> std.variant is, unfortunately, not very useful if you want the
>> semantics of variants in ML-style languages.
> 
> I've been working on an update to std.variant whose formal
> submission has been held up by a PhD thesis and some health
> issues, although I'm currently (slowly) doing a code
> review/cleanup of it in the hope of finally submitting it. ( Old
> code: https://jshare.johnshopkins.edu/rjacque2/public_html/ )
> Anyways, my implementation has an internal 'tag' as does the
> current implementation, IIRC. However, as the tag is a
> meaningless random number, instead .type is provide access to the
> meaningful typeinfo object of that class. And .type provides most
> (all?) of the functionality of an int id:
> 
> auto var = Variant(5);
> if(var.type == typeid(int)) {
>      // Do something...
> } else if(var.type == typeid(string)) {
>     // Do something else...
> }

Robert, I see no bounded types in the above Variant.
Looking back at:

  http://dlang.org/phobos/std_variant.html

I see now that std.Variant doesn't require the set of
types to be bounded.  It's only Algebraic:

  http://dlang.org/phobos/std_variant.html#Algebraic

that has a bounded set of types.  I should have read
closer.  I mistakenly thought std.variant served the
same purpose as Boost.variant, but now I see that
Boost.variant and std.Algebraic serve similar purposes
in that they require a set of bounded types, but that
Boost.any and std.variant are similar in that the types
are unbounded (IOW, any type can be stored in std.variant
or Boost.any).

Sorry for not carefully reading.  So my question then is
why doesn't ALgebraic have a tag.  This would allow:

  Algebraic!(int,int)

> 
> But I am missing something as I found that the linked post wasn't
> clear what the exact issue was, only that there was an issue. If
> someone would like to clarify the problem (or any other with
> Variant) it would be appreciated.
> 

If std.Algebraic is like Boost.Variant, then duplicate
bounded types are not allowed and leads to the problem mentioned
in the post on the spirit mailing list which I linked to in my
OP.  OOPS,  now I see why reading that post was not clear enough.
Maybe this earlier post in same spirit thread would be clearer.

http://article.gmane.org/gmane.comp.parsers.spirit.general/17113

In particular, note the phrase:

  neither can you use variant<string,string,int>
  because variant can't take duplicate types.

This can lead to problems in the spirit parser because
the attributes of parsing:

    a | b

where:
  phrase a has an attribute of type A
  phrase b has an attribute of type B
is:

    variant<A,B>

as noted near the bottom of:


http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html

and if A and B are the same, then there's a problem because
Boost.variant can't handle duplicates.

Hope that's clearer.

-regards,
Larry

BTW, recently there was a review of
another Boost library that has some similarity to
Boost.any.  It's called type_erasure:


http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/doc/html/index.html

Since std.Variant is similar to Boost.any (as noted above),
and since Boost.any is, in some ways, like Boost.type_erasure,
and since you're working on a revised std.Variant,
you might be interested in looking at type_erasure.


More information about the Digitalmars-d mailing list