使用现代 C++ 重构联合成员上的嵌套 switch 语句的后续问题,将其扩展到向量。如何使用 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);
}
但不知道如何让它发挥作用。
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);
}
这极大地减少了代码量。它仍然具有硬编码的二进制运算(此处为加法),但已经对原始代码进行了巨大改进。