【问题标题】:c++ preprocessor directive for choosing variable in runtime用于在运行时选择变量的 c++ 预处理器指令
【发布时间】:2017-12-21 12:55:45
【问题描述】:

我正在尝试实现这样的目标:我有

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

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

更新:忘了说,不能修改给定的结构,因此不能使用数组

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

【问题讨论】:

  • 预处理器在运行时不能做任何事情,它只是编译时的事情。
  • 忘了说,我不能修改给定的结构代码
  • (&this->var1)[offset].
  • @Christoph:那是便携的吗?
  • 它可能不会比this更漂亮了。

标签: c++ preprocessor


【解决方案1】:

如果您确实希望可以使用预处理器生成if-else 链(您可能不这样做),但如果只是这种情况,那很可能不是值得。我认为你真的应该重新考虑在结构中使用数组或偏移量的可能性。

您可以在一定程度上在预处理器中构造循环。限制是您无法编写正确的循环,因此您最终会遇到一个迭代次数有限的构造。基本上你循环n次的方法是将LOOP(n,...)扩展为LOOP#n(...),然后定义LOOPn# for all possible values ofn`。

所以我们想要的是这样的:

 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 当然在范围内之后)。

【讨论】:

  • offsetof 仅适用于标准布局类型。那里应该有一个静态断言来验证StructName 是标准布局。
  • @StoryTeller 我在想 C,在 C++ 中我不认为 offsetof 适合这种情况 - 我已经修改了答案以使用指向成员的指针(我认为无论标准如何,它们都应该工作布局)。
猜你喜欢
  • 1970-01-01
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
相关资源
最近更新 更多