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

qij5mzcb  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(80)

这是Refactor nested switch statement on union members using modern C++的后续问题,将其扩展到向量。我如何使用std::variant摆脱联合成员上的嵌套switch语句,以实现向量上的二进制操作?我目前的代码(历史很长)类似于

enum Value_type_id { i, f, d };
union Pointer { int* i; float* f; double* d; };
struct Item { Value_type_id type; Pointer data; size_t element_count; };

// Item::data points at the beginning of a std::vector
// of the appropriate type with the given element_count.

void add(const Item& lhs, const Item& rhs, Item& result)
{
  assert(lhs.element_count == rhs.element_count);
  assert(lhs.element_count == result.element_count);
  // the type of the data values accessible through
  // "result" is the highest of the types of the data
  // values accessible through "lhs" and "rhs".
  auto n = lhs.element_count;
  auto lhsdata = lhs.data;
  auto rhsdata = rhs.data;
  auto resultdata = result.data;
  switch (lhs.type)
  {
    case i:
      switch (rhs.type)
      {
        case i:
          while (n--)
            *resultdata.i++ = *lhsdata.i++ + *rhsdata.i++;
          break;
        case f:         
          while (n--)
            *resultdata.f++ = *lhsdata.i++ + *rhsdata.f++;
          break;
        case d:
          while (n--)
            *resultdata.d++ = *lhsdata.i++ + *rhsdata.d++;
          break;
      }
      break;
    case f:
      switch (rhs.type)
      {
        case i:         
          while (n--)
            *resultdata.f++ = *lhsdata.f++ + *rhsdata.i++;
          break;
        case f:
          while (n--)
            *resultdata.f++ = *lhsdata.f++ + *rhsdata.f++;
          break;
        case d:
          while (n--)
            *resultdata.d++ = *lhsdata.f++ + *rhsdata.d++;
          break;
      }
      break;
    case d:
      switch (rhs.type)
      {
        case i:         
          while (n--)
            *resultdata.d++ = *lhsdata.d++ + *rhsdata.i++;
          break;
        case f:
          while (n--)
            *resultdata.d++ = *lhsdata.d++ + *rhsdata.f++;
          break;
        case d:
          while (n--)
            *resultdata.d++ = *lhsdata.d++ + *rhsdata.d++;
          break;
      }
      break;
  }
}

字符串
这有许多几乎相同的代码副本,不同之处仅在于使用了哪个联合成员。

using Data = std::variant<std::vector<int>, std::vector<float>, std::vector<double>>;

Data add(const Data& lhs, const Data& rhs)
{
  return some_magic_here(std::plus(){}, lhs, rhs);
}


但不知道怎么做

mrwjdhj3

mrwjdhj31#

一个朋友想出了

Data add(const Data& lhs, const Data& rhs)
 {
   return std::visit([](auto lhsv, auto rhsv)
   {
     using AddType = decltype(lhsv[0] + rhsv[0]);
     auto count = std::min(lhsv.size(), rhsv.size());
     std::vector<AddType> result(count);
     auto lhsp = lhsv.data();
     auto rhsp = rhsv.data();
     auto p = result.data();
     for (int i = 0; i < element_count; i++)
       *p++ = *lhsp++ + *rhsp++;
     return result;
   }, lhs, rhs);
}

字符串
这极大地减少了代码量,它仍然有二进制操作(这里是加法)硬编码,但已经是对原始代码的巨大改进。

相关问题