如何使用现代 C++ 获得与
相同的效果enum Value_type_id { i, f, d };
union Value { int i; float f; double d; };
struct Item { Value_type_id type; Value value; };
Item add(Item lhs, Item rhs)
{
Item result;
switch (lhs.type)
{
case i:
switch (rhs.type)
{
case i:
result.type = i;
result.value.i = lhs.value.i + rhs.value.i;
break;
case f:
result.type = f;
result.value.f = lhs.value.i + rhs.value.f;
break;
case d:
result.type = d;
result.value.d = lhs.value.i + rhs.value.d;
break;
}
break;
case f:
switch (rhs.type)
{
case i:
result.type = f;
result.value.f = lhs.value.f + rhs.value.i;
break;
case f:
result.type = f;
result.value.f = lhs.value.f + rhs.value.f;
break;
case d:
result.type = d;
result.value.d = lhs.value.f + rhs.value.d;
break;
}
break;
case d:
switch (rhs.type)
{
case i:
result.type = d;
result.value.d = lhs.value.d + rhs.value.i;
break;
case f:
result.type = d;
result.value.d = lhs.value.d + rhs.value.f;
break;
case d:
result.type = d;
result.value.d = lhs.value.d + rhs.value.d;
break;
}
break;
}
return result;
}
但不必为
Item
的两个实例的此函数和其他函数编写几乎相同情况的嵌套 switch 语句?理想情况下,我希望能够做类似的事情
Item add(Item lhs, Item rhs)
{
return some_magic_here(std::plus{}, lhs, rhs);
}
但我还没有弄清楚如何实施
some_magic_here
。
乍一看,基于 Item
的 std::variant
和基于 some_magic_here
的 std::visit
似乎很合适,直到我发现 std::visit
要求返回值对于变体中表示的所有替代项具有相同的类型。我需要的返回类型是两个参数类型的 std::common_type
,这并不总是相同的。
实际上,我的用例有 8 种不同的数据类型,这导致了 64 种不同的情况,除了访问联合体的成员之外,这些情况都是相同的。
您是正确的,传递给
std::visit
的访问者必须在所有情况下返回相同的类型,但没有理由该类型本身不能是 std::variant
:
using Item = std::variant<int, float, double>;
Item add(Item lhs, Item rhs)
{
return std::visit(
[](auto lhs, auto rhs) { return Item{lhs + rhs}; },
lhs,
rhs
);
}
访问者的返回类型始终是
std::variant<int, float, double>
,但是 variant
根据 lhs
和 rhs
中包含的类型持有不同的类型。