提问人:Louis Strous 提问时间:11/11/2023 最后编辑:Louis Strous 更新时间:11/15/2023 访问量:96
使用现代 C++ 重构联合成员上的嵌套开关语句
Refactor nested switch statement on union members using modern C++
问:
如何使用现代 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;
}
但是,不必繁琐地对嵌套的 switch 语句进行编码,对于这两个实例的 this 函数和其他函数,使用几乎相同的大小写?理想情况下,我希望能够做这样的事情Item
Item add(Item lhs, Item rhs)
{
return some_magic_here(std::plus{}, lhs, rhs);
}
但我还没有弄清楚如何实现.
乍一看,基于 和 on 似乎很合适,直到我发现要求返回值对于变体中表示的所有替代项具有相同的类型。我需要两种参数类型的返回类型,这并不总是相同的。some_magic_here
Item
std::variant
some_magic_here
std::visit
std::visit
std::common_type
实际上,我的用例有 8 种不同的数据类型,这导致了 64 个不同的案例,这些案例除了访问了哪些联合成员之外是相同的。
补充 2023-11-11:我的应用程序(解释型语言的实现) 是独立的大型(170'000 行),并使用枚举/联合/结构 整个。我可以(做很多工作)用一些东西代替它们 否则,但只有在有明显好处的情况下才想这样做,例如 摆脱许多近乎重复的开关案例,用于不同的 支持的数据类型。公认的答案(迈尔斯·布德内克(Miles Budnek))提供了这一点。
补充 2023-11-15:我现在意识到我也需要一个类似的向量解决方案,但我不知道如何将当前问题的答案扩展到这种情况,所以我在这里提出了一个后续问题:使用现代 C++ 重构带有向量的联合成员上的嵌套开关语句
答:
您说得对,传递给的访问者必须在所有情况下返回相同的类型,但没有理由该类型本身不能是: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
上一个:从对象列表创建嵌套对象
评论
std::vist
variant
vist
Item
add()