用于在运行时选择变量的c ++预处理器指令

时间:2017-07-17 05:32:50

标签: c++ preprocessor

我试图实现这样的目标:我有

struct {
   int var1;
   int var2;
   int var3;
   ......
   int var31;
}

现在我有一些整数' r'我在运行时读取,并且我想打印var ## r的值(即,如果r = 6,从结构打印var6),是否可以通过预处理器指令?我理解我可以通过跳转var1的地址sizeof(int)* r次来做到这一点,但我希望预处理器能够生成整个if-else链,我能以某种方式做到这一点吗?

更新:忘了提,不能修改给定的struct,因此不能使用数组

UPDATE2:我有这些限制(没有数组,nu跳转),因为最后我解析了clang生成的语法树,我希望在那里有纯粹的if / else语句

1 个答案:

答案 0 :(得分:0)

如果您可以使用预处理器生成if - else链,如果您真的想要(您可能不这样做),但是如果它只是出现这种情况它最有可能不值得。我认为你应该重新考虑使用数组或偏移到结构中的可能性。

您可以在预处理器中以某种有限的程度构造循环。限制是您不能编写正确的循环,因此您将最终进入一个最终将进行有限迭代次数的构造。基本上你要循环n次的是将LOOP(n,...)扩展为LOOP#n(...),然后定义LOOPn# for all possible values of n`。

所以我们想要的是:

 if( 0 )                 ; // Note: empty statement
 else if( r == 1 )       return o->var1;
 else if( r == 2 )       return o->var2;
 // etc

if(0)是使每个变量在文本上处理相同。所以我们可以做第一步来定义:

 #define HANDLE_VAR(n) else if( r == n ) return o->var ## n;

这意味着我们写了它

 if(0) ;
 HANDLE_VAR(1)
 HANDLE_VAR(2)
 //  etc

然后我们定义循环结构:

 #define LOOP(n,M) LOOP ## n(M)
 #define LOOP(1) M(1)
 #define LOOP(2) M(1) M(2)
 // etc

然后我们的构造将是

 if( 0 ) ; LOOP(31,HANDLE_VAR)

最后我们将它们全部包装成一个宏:

 #define RETURN_VAR if(0) ; LOOP(31,HANDLE_VAR)

但是还有其他选择。最常见的解决方案是使用数组来存储变量。

另一种方法是编写自己的预处理器,支持正确的循环,有支持它的现成的模板处理器(例如genshi)。

第三个是计算结构中的偏移量。但是,建议的方法不符合标准。您需要做的是存储一组偏移量:

int StructName::* var_off[] = {
    NULL,
    &StructName::var1,
    &StructName::var2,
    // etc
};

然后使用o.*var_off[r]访问var##r(在检查r是否在范围内之后)。