Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;使用开关展开循环的模板?_C++_Templates_C++11_Switch Statement_Template Meta Programming - Fatal编程技术网

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

C++ C++;使用开关展开循环的模板?,c++,templates,c++11,switch-statement,template-meta-programming,C++,Templates,C++11,Switch Statement,Template Meta Programming,我的问题与类似,但我想混合编译时和运行时。具体来说,我在编译时知道一个常量NBLOCK,我想在变量start\u块上写一个开关,该变量只有在运行时才知道,其中NBLOCK是开关中的条目数。以下是我使用宏得到的结果: #define CASE_UNROLL(i_loop) \ case i_loop : \ dst.blocks[i_loop+1] -= (load_unaligned_epi8(srcblock) != zero) & block1; \

我的问题与类似,但我想混合编译时和运行时。具体来说,我在编译时知道一个常量
NBLOCK
,我想在变量
start\u块
上写一个开关,该变量只有在运行时才知道,其中
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

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

请注意,问题非常类似于,但据我所知,这里提出的解决方案是通过使用混合编译/tun时间初始化函数指针数组来移除开关。我不能付钱给王子在这里调用函数


如果需要一些讨厌的扩展,我将与GCC合作

您只需将Boost.Preprocessor与
Boost\u PP\u REPEAT(计数、宏、数据)
一起使用即可:

这应扩大到:

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

基于模板的展开:

template<int N>
struct loopUnroller
{
  template<typename Operation>
  inline void operator(Operation& op) { op(); loopUnroller<N-1>(op); }
};

template<>
struct loopUnroller<0>
{
  template<typename Operation>
  inline void operator(Operation& op) { op(); }
};
具有对数复杂性:

template<int N>
struct loopUnroller
{
  template<typename Operation>
  inline void operator(Operation& op) { 
       loopUnroller<N/2>(op);
       loopUnroller<N/2>(op);
       if (N%1) { op(); } // Will be optimized out if N is even.
  }
};
template<int L>
struct loopUnroller
{
  template<typename Operation>
  inline void operator(Operation& op, int i) {
     if (i & (1<<L)) {
       for(int j = 0; j != 1<<L; ++j)
       {
         op();
       }
     }
     loopUnroller<L-1>(op, i);
  }
};
模板
结构循环展开器
{
模板
内联无效运算符(操作和操作){
活套展开器(op);
活套展开器(op);
if(N%1){op();}//将在N为偶数时进行优化。
}
};
具有动态复杂性:

template<int N>
struct loopUnroller
{
  template<typename Operation>
  inline void operator(Operation& op) { 
       loopUnroller<N/2>(op);
       loopUnroller<N/2>(op);
       if (N%1) { op(); } // Will be optimized out if N is even.
  }
};
template<int L>
struct loopUnroller
{
  template<typename Operation>
  inline void operator(Operation& op, int i) {
     if (i & (1<<L)) {
       for(int j = 0; j != 1<<L; ++j)
       {
         op();
       }
     }
     loopUnroller<L-1>(op, i);
  }
};
模板
结构循环展开器
{
模板
内联无效运算符(操作和op,int i){

如果(i&(1不可能重复。它不是重复。在我的情况下,起点在运行时已知,终点在编译时已知。GCC能够展开代码,但它使用了大量跳转。此版本速度更快,因为只有一个跳转。但是它使用宏。我宁愿编写模板。我问为什么?它真的比编译代码?是的,快了30%。这里的开关在我的内部计算循环中。谢谢你的提示。它仍然不能回答模板是否可行的问题。我认为这不是,但我希望得到专家的答案。重点是,我想确保有一个开关,因为我只知道在运行时到起始点@hivert:这又是一个XY问题。您正在假设一个特定的解决方案。最后一段代码也将
int i
作为运行时的起点,只是没有开关。