使用现代C++重构联合成员上的嵌套switch语句

bxjv4tth  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(70)

如何使用现代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的两个示例的this和其他函数编写几乎相同的嵌套switch语句,理想情况下,我希望能够执行以下操作:

Item add(Item lhs, Item rhs)
{
  return some_magic_here(std::plus{}, lhs, rhs);
}


但是我还没有弄清楚如何实现some_magic_here。基于std::variantItem和基于std::visitsome_magic_here乍一看似乎是合适的,直到我发现std::visit要求返回值对于变量中表示的所有替代项都具有相同的类型。我需要返回类型是两个参数类型中的std::common_type,这并不总是一样的。
实际上,我的用例有8种不同的数据类型,这导致了64种不同的情况,除了访问联合体的哪些成员之外,这些情况都是相同的。
添加2023-11-11:我的申请(解释型语言的实现)是独立的,(170'000行),并在整个过程中使用枚举/联合/结构。(有很多工作)用别的东西代替它们,但只有在有明显好处的情况下才想这样做,例如,对于不同的支持数据类型,摆脱了许多几乎重复的开关情况。
补充2023-11-15:我现在意识到我也需要一个类似的向量解决方案,但我不知道如何将当前问题的答案扩展到这种情况,所以我在这里提出了一个后续问题:Refactor nested switch statement on union members with vectors, using modern C++

8nuwlpux

8nuwlpux1#

你是正确的,传递给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
    );
}

字符串
Example
访问者的返回类型总是std::variant<int, float, double>,但是variant根据lhsrhs中包含的类型而持有不同的类型。

相关问题