在运行时使用枚举器值作为模板函数的模板参数的元程序

Metaprogram to use enumerator value as template parameter of a template function at runtime

本文关键字:函数 参数 程序 运行时 枚举      更新时间:2023-10-16

假设我有这段代码:

// the enumerator
enum class my_enum {
ONE,
TWO,
THREE
};
// the function
template <my_enum E>
int foo() {
return 0;
}
// a specialization
template<>
int foo<my_enum::TWO>() {
return 1;
}

我想编写一个专门针对my_enum的每个元素foobar函数,并在运行时根据bar参数的值调用其中一个函数。最简单的解决方案是编写一个开关并手动添加所有情况:

int bar(my_enum value) {
switch (value) {
using m = my_enum;
case m::ONE:
return foo<m::ONE>();
case my_enum::TWO:
return foo<m::TWO>();
case my_enum::THREE:
return foo<m::THREE>();
}
}

使用一些额外的技巧来处理意外值,添加开关的默认值。不幸的是,对于很长的枚举器,此解决方案带来了非常长且冗余的代码,很难维护。

是否有任何元编程解决方案可以简化此代码,例如使用Boost Hana或Boost MPL?

如果枚举值像您的示例一样,从零开始并且连续...给定一个辅助函数,如下所示

template <std::size_t ... Is>
std::array<int(*)(void), sizeof...(Is)>
getFuncArray (std::index_sequence<Is...>)
{ return {{ &foo<static_cast<my_enum>(Is)>... }}; }

您可以在bar()中添加一个static函数数组,并根据输入调用正确的函数数组。

我的意思是

int bar (my_enum value)
{
static auto const arrF
= getFuncArray(std::make_index_sequence<
1u+static_cast<std::size_t>(my_enum::THREE)>{});
return arrF[static_cast<std::size_t>(value)]();
}