Tagged union (aka variant) in C ++ with the same type several times

I need to create a union, but 2 members of the union will have the same type, so I need a way to identify them. For example, in OCaml:

type A = | B of int | C of float | D of float 

Boost.Variant does not seem to support this case, is there a known library that supports this?

+6
source share
3 answers

If you want to do this, I think your best option is to wrap the same, but different types in a structure, which then allows the boost option to go to the right one:

 struct Speed { float val_; }; struct Darkness { float val_; }; 

You might be able to use BOOST_STRONG_TYPEDEF to do this automatically, but I'm not sure if it guarantees the creation of types that are legal for use in the union (although this will probably be nice in the variant).

+5
source

C ++ code here:

http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_storage/pack/container_one_of_maybe.hpp

really is a labeled union, as it may contain duplicate types. One nice feature is that tags can be enumerations; therefore, tags can have meaningful names.

Unfortunately, compilation time is pretty bad, I think, because the implementation uses recursive inheritance. OTOH, perhaps compilers will eventually figure out a way to reduce compilation time.

OTOH, if you want to stick with boost :: variant, you can wrap types as suggested by Mark B. However, instead of the descriptive names of the Mark B classes that require some thought, you can use fusion::pair<mpl::int_<tag>,T_tag> where T_tag is the tag element in the fusion::vector source. IOW:

 variant < fusion::pair<mpl::int_<1>,T1> , fusion::pair<mpl::int_<2>,T2> ... , fusion::pair<mpl::int_<n>,Tn> > 

How to merge documents:

http://www.boost.org/doc/libs/1_55_0/libs/fusion/doc/html/fusion/support/pair.html

say, fusion::pair allocates only space for the argument of the 2nd template; therefore, this should not take up more space than boost::variant<T1,T2,...,Tn> .

NTN.

-regards, Larry

+2
source

You cannot at the moment, but the C ++ 17 std::variant implementation , fortunately, allows you to:

In the variant, it is allowed to store the same type more than once and store different versions with the same type.

Unlike the boost version, you can get values ​​by index, something like this (not verified):

 // Construct a variant with the second value set. variant<string, string, string> s(std::in_place_index<1>, "Hello"); // Get the second value. string first = std::get<1>(s); 
Michael Park wrote an implementation of C ++ 14 C ++ 17 std::variant .
+1
source

Source: https://habr.com/ru/post/949760/


All Articles