我想转换一个运行时值 int v
使用非类型模板参数调用相应函数 v
,例如 template <int v> void hello()
.
下面是暴力写法:
using fn_type = void();
template <int v>
void hello() {
// of course ITRW this function requires v to be a
// constexpr value
printf("hello: %d\n", v);
}
static std::array<fn_type *, 3> lut = {
hello<0>,
hello<1>,
hello<2>
};
void hello_dispatch(int v) {
lut[v](); // we don't handle OOB values b/c we are naughty like that
}
我可以接受 3 个值,但是对于更多值,或者当限制本身是根据其他编译时值计算的时,这变得不切实际。
如何在编译时初始化 LUT2 而无需显式列出各种实例 hello<0>, hello<1>, ...
在初始化程序中?
这是我想出的:
template <size_t I, size_t MAX>
constexpr void make_helper(std::array<fn_type *, MAX>& a) {
if constexpr (I < MAX) {
a[I] = hello<I>;
make_helper<I + 1, MAX>(a);
}
}
template <size_t MAX>
constexpr std::array<fn_type *, MAX> make_lut() {
std::array<fn_type *, MAX> ret{};
make_helper<0, MAX>(ret);
return ret;
}
static constexpr std::array<fn_type *, 3> lut2 = make_lut<3>();
C++17 中必须有更简单、更好和更惯用的东西 - 特别是不需要递归。
2 或者,如果这是一个 XY 问题,我该如何实现 hello_dispatch
没有 LUT(但至少具有 LUT 的效率)。
最佳答案
您可以直接初始化std::array
,即不需要递归一个一个地分配元素。
template<std::size_t... I>
constexpr auto make_helper(std::index_sequence<I...>) {
return std::array<fn_type *, sizeof...(I)> { hello<I>... };
}
template <std::size_t MAX>
constexpr auto make_lut() {
return make_helper(std::make_index_sequence<MAX>{});
}
关于c++ - 初始化函数指针的 constexpr 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58740177/