提问人:Louis Strous 提问时间:11/15/2023 更新时间:11/18/2023 访问量:72
使用现代 C++ 重构带有向量的联合成员的嵌套 switch 语句
Refactor nested switch statement on union members with vectors, using modern C++
问:
这是使用现代 C++ 重构联合成员的嵌套 switch 语句的后续问题,并将其扩展到向量。如何使用联合成员摆脱嵌套的 switch 语句来实现对向量的二进制操作?我当前的代码(具有很长的历史)类似于std::variant
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);
}
但不知道如何让它工作。
答:
0赞
Louis Strous
11/18/2023
#1
一个朋友想出了
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);
}
这大大减少了代码量。它仍然具有硬编码的二进制操作(此处为加法),但已经是对原始代码的巨大改进。
评论
using Data = std::vector<std::variant<int*,float*,double*>>
const *
auto *
FunctionalStyleVisitor
SimpleVisitor
operator ()(Type)
Type
std::variant
std::variant