我的问题类似于Can one unroll a loop when working with an integer template parameter?但我想混合编译时间和运行时间。具体来说,我在编译时知道一个常量 NBLOCK
并且我想在变量 start_block
上写一个开关,它只在运行时才知道 NBLOCK
是开关中的条目数。这是我使用宏得到的结果:
#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。
我想知道是否可以使用一些模板元编程来编写它。困难的部分是,出于性能原因,使用跳转表而不是嵌套条件序列编译开关是至关重要的。
请注意,该问题与 C++/C++11 - Switch statement for variadic templates? 非常相似但据我所知,这里提出的解决方案是通过使用混合编译/调谐时间初始化函数指针数组来删除开关。我不能付钱给王子在这里调用一个函数。
如果需要一些讨厌的扩展,我会使用 GCC。
最佳答案
您可以简单地将 Boost.Preprocessor 与 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);
}
关于用于使用开关展开循环的 C++ 模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16982283/