boost — отмеченные союзы (также известный как вариант) в C ++ с одним и тем же типом несколько раз

Мне нужно создать профсоюз, но 2 члена профсоюза будут иметь один и тот же тип, поэтому мне нужен способ их идентификации. Например, в OCaml:

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

Boost.Variant, кажется, не поддерживает этот случай, есть ли известная библиотека, которая поддерживает это?

6

Решение

Если вы хотите сделать это, я думаю, что ваш лучший вариант — это обернуть те же, но разные типы в структуру, которая затем позволяет буст-варианту посетить нужный:

struct Speed
{
float val_;
};

struct Darkness
{
float val_;
};

Вы может быть быть в состоянии использовать BOOST_STRONG_TYPEDEF сделать это автоматически, но я не уверен, что он гарантированно сгенерирует типы, допустимые для использования в объединении (хотя это, вероятно, будет хорошо в варианте).

5

Другие решения

Код C ++ здесь:

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

действительно является теговым объединением в том смысле, что может содержать дубликаты типов. Одна приятная особенность
это теги могут быть перечислениями; следовательно, теги могут иметь значимые имена.

К сожалению, стоимость времени компиляции довольно плохая, я думаю, потому что реализация
использует рекурсивное наследование. OTOH, может быть, компиляторы со временем найдут способ
уменьшить стоимость времени компиляции.

OTOH, если вы хотите придерживаться Boost :: варианта, вы можете обернуть типы,
как предложил Марк Б. Однако вместо описательных имен классов Марка Б
которые требуют некоторой мысли, вы могли бы использовать fusion::pair<mpl::int_<tag>,T_tag>
где T_tag является тегом-ом элемента в источнике fusion::vector, IOW:

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

Как документы Fusion:

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

сказать, fusion::pair выделяет место только для второго аргумента шаблона; следовательно,
это не должно занимать больше места, чем boost::variant<T1,T2,...,Tn>,

НТН.

-С уважением,
Larry

2

Вы не можете в данный момент, но C ++ 17 реализация std::variant к счастью, позволяет это:

Вариант может содержать один и тот же тип более одного раза и содержать версии одного и того же типа с различной квалификацией.

В отличие от расширенной версии, вы можете получить значения по индексу, что-то вроде этого (не проверено):

// 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);

Майкл Парк написал реализация C ++ 14 C ++ 17 std::variant.

1
По вопросам рекламы [email protected]