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

问题描述 投票:0回答:1

如何使用现代 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 种不同的情况,除了访问联合体的成员之外,这些情况都是相同的。

c++ nested switch-statement
1个回答
0
投票

您是正确的,传递给

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
中包含的类型持有不同的类型。

© www.soinside.com 2019 - 2024. All rights reserved.