我需要创建一个工会,但工会的 2 个成员将具有相同的类型,因此我需要一种方法来识别它们。例如在 OCaml 中:
type A =
| B of int
| C of float
| D of float
Boost.Variant 似乎不支持这种情况,是否有已知的库支持这种情况?
如果你想这样做,我认为你最好的选择是将相同但不同的类型包装到一个结构中,然后让 boost 变体访问正确的变体:
struct Speed
{
float val_;
};
struct Darkness
{
float val_;
};
您可能可以使用BOOST_STRONG_TYPEDEF
自动执行此操作,但我不确定它是否保证生成在联合中合法使用的类型(尽管在变体中可能会很好)。
您目前不能,但幸运的是 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
。
这里的c++代码:
是真正的标记联合,因为它可以包含重复的类型。一个不错的功能是标签可以是枚举;因此,标签可以具有有意义的名称。
不幸的是,编译时间成本非常糟糕,我猜,因为实现使用递归继承。OTOH,也许编译器最终会找到一种减少编译时间成本的方法。
OTOH,如果您想坚持使用 boost::variant,您可以按照 Mark B 的建议包装类型。但是,您可以使用fusion::pair<mpl::int_<tag>,T_tag>
where T_tag
is 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。
-问候,拉里