使用开关展开循环的 C++ 模板?

我的问题类似于 在使用整数模板参数时可以展开循环吗? 但我想混合编译时间和运行时.具体来说,我在编译时知道一个常量 NBLOCK 并且我想在一个变量 start_block 上编写一个开关,该变量仅在运行时知道 NBLOCK是交换机中的条目数.这是我使用宏得到的结果:

My question is similar to Can one unroll a loop when working with an integer template parameter? but I want to mix compile time and runtime. Specifically, I know at compile time a constant NBLOCK and I want to write a switch on a variable start_block which is only known at runtime where NBLOCK is the number of entries in the switch. Here is what I got using macros:

#define CASE_UNROLL(i_loop)         
  case i_loop : 
    dst.blocks[i_loop+1] -= (load_unaligned_epi8(srcblock) != zero) & block1; 
    srcblock += sizeof(*srcblock);

  switch(start_block)
    {
      CASE_UNROLL(0);
#if NBLOCKS > 2
      CASE_UNROLL(1);
#endif
#if NBLOCKS > 3
      CASE_UNROLL(2);
#endif
#if NBLOCKS > 4
      CASE_UNROLL(3);
#endif
...
...
#if NBLOCKS > 15
      CASE_UNROLL(14);
#endif
#if NBLOCKS > 16
#error "Too many blocks"
#endif
    }

我觉得它很丑.特别是如果我想将界限从 16 提高到 32.

I find it very ugly. Especially if I want to raise the bound from 16 to 32.

我想知道是否可以使用一些模板元编程来编写它.困难的部分是,出于性能原因,使用跳转表而不是嵌套条件序列来编译开关至关重要.

I would like to know if it is possible to write that using some template meta programming. The hard part is that for performance reasons it is crucial that the switch is compiled with a jump table than a sequence of nested conditional.

请注意,该问题与 C++/C++11 非常相似 -可变参数模板的 Switch 语句? 但据我了解,这里提出的解决方案是通过使用混合的编译/调谐时间初始化函数指针数组来删除开关.我不能付钱给王子在这里调用一个函数.

Note that the question is very similar to C++/C++11 - Switch statement for variadic templates? but as far as I understand the solution proposed here is to remove the switch by using a mixed compile/tun time initialized functions pointer array. I can't pay the prince a calling a function here.

如果需要一些讨厌的扩展,我正在使用 GCC.

I'm working with GCC if some nasty extensions is needed.

推荐答案

你可以简单地使用 Boost.Preprocessor 和 BOOST_PP_REPEAT(COUNT, MACRO, DATA):

You could simply use Boost.Preprocessor with BOOST_PP_REPEAT(COUNT, MACRO, DATA):

#define APPLY_FUNC(INDEX, FUNC) FUNC(INDEX);

// ...

switch(start_block)
{
    BOOST_PP_REPEAT(NBLOCK, APPLY_FUNC, CASE_UNROLL);
}

应该扩展为:

switch(start_block)
{
    CASE_UNROLL(0);
    CASE_UNROLL(1);
    CASE_UNROLL(2);
    // ...
    CASE_UNROLL(NBLOCK-1);
}

相关文章