8

我需要创建一个工会,但工会的 2 个成员将具有相同的类型,因此我需要一种方法来识别它们。例如在 OCaml 中:

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

Boost.Variant 似乎不支持这种情况,是否有已知的库支持这种情况?

4

3 回答 3

8

如果你想这样做,我认为你最好的选择是将相同但不同的类型包装到一个结构中,然后让 boost 变体访问正确的变体:

struct Speed
{
    float val_;
};

struct Darkness
{
    float val_;
};

可能可以使用BOOST_STRONG_TYPEDEF自动执行此操作,但我不确定它是否保证生成在联合中合法使用的类型(尽管在变体中可能会很好)。

于 2013-07-18T15:40:52.750 回答
3

您目前不能,但幸运的是 C++17 的实现std::variant允许它:

一个变体被允许多次持有相同的类型,并且持有相同类型的不同的 cv 限定版本。

与 boost 版本不同,您可以按索引获取值,如下所示(未测试):

// 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 编写了 C++17 的 C++14 实现std::variant

于 2017-03-30T11:05:31.173 回答
2

这里的c++代码:

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

是真正的标记联合,因为它可以包含重复的类型。一个不错的功能是标签可以是枚举;因此,标签可以具有有意义的名称。

不幸的是,编译时间成本非常糟糕,我猜,因为实现使用递归继承。OTOH,也许编译器最终会找到一种减少编译时间成本的方法。

OTOH,如果您想坚持使用 boost::variant,您可以按照 Mark B 的建议包装类型。但是,您可以使用fusion::pair<mpl::int_<tag>,T_tag> where T_tagis the tag-th element in source代替 Mark B 的描述性类名,这需要一些思考fusion::vector。爱荷华州:

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

作为融合文档:

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

比如说,fusion::pair只为第二个模板参数分配空间;因此,这不应该占用比 更多的空间boost::variant<T1,T2,...,Tn>

HTH。

-问候,拉里

于 2014-02-25T17:11:59.193 回答