初始化函数指针的constexpr数组

我想将运行时值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个值,但是对于更多的值,或者当限制本身是由其他编译时值计算得出的,这是不切实际的。

如何在编译时初始化LUT 2 而不在初始化程序中明确列出各种实例hello<0>,...

这是我想出的:

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问题,如何在没有LUT(但至少具有LUT效率)的情况下实现hello_dispatch

jayztimes 回答:初始化函数指针的constexpr数组

您可以直接初始化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

,

使用std::integer_sequencefold expressions

GET http://127.0.0.1:8080/api/projects?filter[tasks.id]=1

{
  "data" : [ ]
}
  • template <int... Is> constexpr std::array<fn_type*,sizeof...(Is)> make_lut(std::integer_sequence<int,Is...>) { std::array<fn_type*,sizeof...(Is)> res{}; ((res[Is] = &hello<Is>),...); return res; } template <int Max> constexpr auto make_lut() { return make_lut(std::make_integer_sequence<int,Max>{}); } static constexpr auto lut2 = make_lut<3>(); 创建一个std::make_integer_sequence<int,N>{}类型的对象。
  • 我们使用第一个函数模板捕获这些值,并使用折叠表达式std::integer_sequence<int,1,2,...,N - 1>将每个hello<N>分配给res[N]
  • 我们可以对res[Is] = &hello<Is>折痕左侧的值应用逗号运算符。
,

现在,对于完全不同的东西...

如果可以使用C ++ 20,则可以使用template-lambdas,并且可以完全避免使用lut数组

#include <iostream>
#include <utility>

template <int v>
void hello()
 { std::cout << "hello: " << v << std::endl; }

void hello_dispatch (int v)
 {
   [&]<int ... Is>(std::integer_sequence<int,Is...> const &)
      { ((v == Is ? (hello<Is>(),0) : 0),...); }
         (std::make_integer_sequence<int,100u>{}); // 100 is top limit (former lut size)
 }

int main ()
 {
   hello_dispatch(42);
 }

如果您只能使用C ++ 17 ...不是那么优雅,但是您可以使用递归通用lambda

#include <iostream>
#include <utility>

template <int v>
void hello()
 { std::cout << "hello: " << v << std::endl; }

template <int I>
using IC = std::integral_constant<int,I>;

void hello_dispatch (int v)
 {
   auto lf = [&](auto self,auto ic)
    { if constexpr ( ic < 100 )
         v == ic ? (hello<ic>(),0)
                 : (self(self,IC<ic+1>{}),0); };

   lf(lf,IC<0>{});
 }

int main ()
 {
   hello_dispatch(42);
 }
本文链接:https://www.f2er.com/3148251.html

大家都在问