C++使用枚举变量调度模板
我的功能具有两个枚举变量的模板。有什么方法可以通过enuma
和enumb
的不同组合来派遣函数f
?如果,我不想写太多。在这种情况下,我可能只需要编写4个分支,但是在实际情况下,我需要编写Tens分支。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cassert>
using namespace std;
enum EnumA
{
enumA0,
enumA1
};
enum EnumB
{
enumB0,
enumB1
};
template <EnumA enumA, EnumB enumB>
void f()
{
if (enumA == enumA0)
{
if (enumB == enumB0)
{
// something here
return;
}
else if (enumB == enumB1)
{
// something here
return;
}
else
{
assert(false);
}
}
else if (enumA == enumA1)
{
if (enumB == enumB0)
{
// something here
return;
}
else if (enumB == enumB1)
{
// something here
return;
}
else
{
assert(false);
}
}
}
int main()
{
int a, b;
cin >> a >> b;
const auto enumA = a < 0 ? enumA0 : enumA1;
const auto enumB = b < 0 ? enumB0 : enumB1;
f<enumA, enumB>(); // Is there a way to dispatch this with different enumA and enumB combinations?
return 0;
}
I have a function with a template of two enum variables. Is there any way to dispatch the function f
with different combinations of enumA
and enumB
? I do not want to write too much if
. In this case, I may only need to write 4 branches, but in actual case, I need to write tens branches.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cassert>
using namespace std;
enum EnumA
{
enumA0,
enumA1
};
enum EnumB
{
enumB0,
enumB1
};
template <EnumA enumA, EnumB enumB>
void f()
{
if (enumA == enumA0)
{
if (enumB == enumB0)
{
// something here
return;
}
else if (enumB == enumB1)
{
// something here
return;
}
else
{
assert(false);
}
}
else if (enumA == enumA1)
{
if (enumB == enumB0)
{
// something here
return;
}
else if (enumB == enumB1)
{
// something here
return;
}
else
{
assert(false);
}
}
}
int main()
{
int a, b;
cin >> a >> b;
const auto enumA = a < 0 ? enumA0 : enumA1;
const auto enumB = b < 0 ? enumB0 : enumB1;
f<enumA, enumB>(); // Is there a way to dispatch this with different enumA and enumB combinations?
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您的主要关注点是避免重复的,如果/else或switch/case构造,则可以在Igor指出的那样创建一个查找表。
为此,您可以将功能(您的“这里”部分)分为单个功能,然后您的查找表将其检索。
因此,我们将从您的模板功能中删除分支。现在,这只是不确定组合的全部内容。
为了根据组合指定应该发生的事情,我们可以专业化功能模板。
定义了应该发生的事情时,我们必须桥接的唯一差距是如何“转换”运行时已知的枚举值为非类型模板参数(又称编译时已知的枚举值),我们在函数定义中使用了。换句话说,我们如何从枚举值传递到一个函数(例如
dispatch(enuma1,enumb0)
到我们函数专业化的调用(例如f&lt; enuma1,enumb0&gt;
>
现在,您的主要内容看起来像这样:
caveats
奖励
在技术上可以自动创建查找表,从而大大减少向枚举添加更多值所需的工作量。但是,它不能解决组件中的任何设计缺陷,同时肯定会增加复杂性。
您可以在编译器资源管理器这里
If your main concern is avoiding repetitive, nested if/else or switch/case constructs you could create a lookup table instead as Igor pointed out.
For this you could separate the functionality (your "something here" parts) into individual functions that will then be retrieved by your lookup table.
Thus we would remove the branching from your template function. This is now only a catch-all for undefined combinations.
To specify what should happen depending on the combination we can specialize the function template.
Having defined what should happen when, the only gap we have to bridge is how to "convert" enum values known at runtime to the non-type template parameters (aka. enum values known at compile time) we have used in our function definitions. In other words how do we get from enum values passed to a function (e.g.
dispatch(enumA1, enumB0)
to the call of our function specialization (e.g.f<enumA1, enumB0>
). This is where the lookup table comes into play.We store the corresponding function pointer to one of the specializations at the key for that combination. Dispatching to the right function is now a simple lookup.
Now your main would look like this:
Caveats
Bonus
It is technically possible to create the lookup table automatically which drastically reduces the amount of work needed when adding further values to the enums. It does not however solve any design flaws in the component while definitely adding complexity.
You can play around with it on compiler explorer here