在运行时使用枚举值作为模板函数的模板参数的元程序
Metaprogram to use enumerator value as template parameter of a template function at runtime
假设我有这个代码:
// 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;
}
我想编写一个 bar
函数专门针对 my_enum
的每个元素 foo
,并在 运行 时调用其中一个基于参数 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)]();
}
假设我有这个代码:
// 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;
}
我想编写一个 bar
函数专门针对 my_enum
的每个元素 foo
,并在 运行 时调用其中一个基于参数 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)]();
}