c++ - 初始化函数指针的 constexpr 数组

标签 c++ optimization c++17 template-meta-programming lookup-tables

我想转换一个运行时值 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>{});
}

LIVE

关于c++ - 初始化函数指针的 constexpr 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58740177/

相关文章:

c++ - 在沙盒中运行插件

c++ - 使用 boost::asio 和 std::wstring 解析网络节点

java - 在 Java 中将 3D int 数组转换为八叉树

css - 是否有一个 CSS 优化器可以在选择器中发现相同的单个属性并将它们组合在一起?

ubuntu - Clang 7 在 Ubuntu 18.04 上找不到 <filesystem> header

c++ - 采用 N 个参数并返回 N 个值的高性能解决方案

c++ - 共享指针的 copy-and-swap 效率

javascript - 如何最大化异步调度程序的性能?

c++ - 是否可以检查是否为给定类型和参数定义了用户文字?

c++ - 如何编写一个错误结构,它可以包含不同的强类型枚举作为错误代码?