枚举值的组合爆炸(729个组合...) [英] Combination explosion of an enum value (729 combinations...)
问题描述
让我们说我有这种类型的结构
template <typename ...NodeKindTs>
struct Element{
std::tuple<NodeKindTs...> nodes;
}
我有一个整数向量,该向量将一个Node与另一个节点相关联,以及一个枚举向量,该枚举表明每种类型的Node.类型可以是A,B或C.
enum class Kind {A,B,C};
std::vector<int> relationShip;
std::vector<Kind> kind;
例如,如果我有
relationShip = {1,2,-1};
kind = {A,B,A}
表示第一个节点的类型为A,并且与第二个节点的类型为B.
现在,我必须创建Elements并将它们插入到向量中,具体取决于每个节点和该关系所附带的NodeKind.此元素最多由6个NodeKinds进行模板化.为了解决这个问题,我需要检查每个节点的种类,然后调用Element ctor.
对于2 NodeKinds情况,这意味着要做类似的事情
if (node1.type == A && node2.type == A) {
auto &simNode1 = containerOfAs(node1.id);
auto &smiNode2 = containerOfAs(node2.id);
insertElement(elementFactory(simNode1, simNode2));
}
if (node1.type == A && node2.type == C)
{
auto &simNode1 = containerOfAs(node1.id);
auto &smiNode2 = containerOfCs(node2.id);
insertElement(elementFactory(simNode1, simNode2));
}
if (node1.type == B && node2.type == C)
{
auto &simNode1 = containerOfBs(node1.id);
auto &smiNode2 = containerOfCs(node2.id);
insertElement(elementFactory(simNode1, simNode2));
}
...
inserElement是我创建的元函数,如果适合容器列表,则可以将该元素插入容器.
对于这2种情况,最多需要9个ifs.对于3种情况,它需要27个ifs;对于6种情况,它需要729 ifs.我真的不想对它们进行编码.
关于如何解决这个问题的任何想法吗?
谢谢!
使用std::variant
,您可能会遇到类似这样的情况:
std::variant<std::reference_wrapper<NodeA>,
std::reference_wrapper<NodeB>,
std::reference_wrapper<NodeC>> getNodeAsVariant(Kind kind, int id)
{
switch (kind) {
case Kind::A: return containerOfAs(id);
case Kind::B: return containerOfBs(id);
case Kind::C: return containerOfCs(id);
}
throw std::runtime_error("Invalid kind");
}
然后
auto v1 = getNodeAsVariant(node1.type, node1.id);
auto v2 = getNodeAsVariant(node2.type, node2.id);
auto v3 = getNodeAsVariant(node3.type, node3.id);
auto v4 = getNodeAsVariant(node4.type, node4.id);
auto v5 = getNodeAsVariant(node5.type, node5.id);
auto v6 = getNodeAsVariant(node6.type, node6.id);
// r1, .., r6 would be the correct reference_wrapper<T>
std::visit([](auto r1, auto r2, auto r3, auto r4, auto r5, auto r6) {
insertElement(elementFactory(r1/*.get()*/, r2, r3, r4, r5, r6));
}, v1, v2, v3, v4, v5, v6);
所以std::visit
会为您生成729个重载.
im facing a problem in which I have to generate a huge amount of code, all of it fairly similar, and I want to know if there is any way to templatized.
Lets say I have a structure of this type
template <typename ...NodeKindTs>
struct Element{
std::tuple<NodeKindTs...> nodes;
}
I have a vector of ints which related a Node with another, and a vector of an enum which says which kind of Node is each. The kind can be A, B or C.
enum class Kind {A,B,C};
std::vector<int> relationShip;
std::vector<Kind> kind;
For example, if I have
relationShip = {1,2,-1};
kind = {A,B,A}
would mean that the first node is of kind A and is related to the second node, which is of kind B. You get it.
Now, I have to create Elements and insert them into a vector depending on the NodeKind that each node and the relation ship. This Elements are templatized by up to 6 NodeKinds. For solving this, I need a huge if that check the Kind of each node and then call the Element ctor.
For the 2 NodeKinds case, this means doing something like
if (node1.type == A && node2.type == A) {
auto &simNode1 = containerOfAs(node1.id);
auto &smiNode2 = containerOfAs(node2.id);
insertElement(elementFactory(simNode1, simNode2));
}
if (node1.type == A && node2.type == C)
{
auto &simNode1 = containerOfAs(node1.id);
auto &smiNode2 = containerOfCs(node2.id);
insertElement(elementFactory(simNode1, simNode2));
}
if (node1.type == B && node2.type == C)
{
auto &simNode1 = containerOfBs(node1.id);
auto &smiNode2 = containerOfCs(node2.id);
insertElement(elementFactory(simNode1, simNode2));
}
...
inserElement is a meta-function I have create which insert the element into the container if fits in from a list of containers.
For this 2 case, this requires up to 9 ifs. For the 3 case it requires 27 ifs and for the 6 case it requires 729 ifs. I really dont want to code them.
Any idea on how I could solve this?
Thanks!
With std::variant
, you might have something like:
std::variant<std::reference_wrapper<NodeA>,
std::reference_wrapper<NodeB>,
std::reference_wrapper<NodeC>> getNodeAsVariant(Kind kind, int id)
{
switch (kind) {
case Kind::A: return containerOfAs(id);
case Kind::B: return containerOfBs(id);
case Kind::C: return containerOfCs(id);
}
throw std::runtime_error("Invalid kind");
}
And then
auto v1 = getNodeAsVariant(node1.type, node1.id);
auto v2 = getNodeAsVariant(node2.type, node2.id);
auto v3 = getNodeAsVariant(node3.type, node3.id);
auto v4 = getNodeAsVariant(node4.type, node4.id);
auto v5 = getNodeAsVariant(node5.type, node5.id);
auto v6 = getNodeAsVariant(node6.type, node6.id);
// r1, .., r6 would be the correct reference_wrapper<T>
std::visit([](auto r1, auto r2, auto r3, auto r4, auto r5, auto r6) {
insertElement(elementFactory(r1/*.get()*/, r2, r3, r4, r5, r6));
}, v1, v2, v3, v4, v5, v6);
So std::visit
would generate the 729 overloads for you.
这篇关于枚举值的组合爆炸(729个组合...)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!