对宏的唯一可识别调用

时间:2017-03-10 16:19:10

标签: c++ macros c-preprocessor

上下文

我正在尝试在我的C ++代码中实现一个易于使用的async/await模式,我有一种方法可以让我发现它非常简单易用。但是,由于我使用的是宏,因此在对外来代码的弱点方面也会付出代价。

这是一个想法:

  • 我们将执行上下文包装在一个类中,该类的成员是async函数使用的变量。
  • async函数的主体内部,我使用宏来实现成员entrypoint上的一个开关,用于跟踪恢复执行函数时的跳转位置:< / p>

    switch(this->entrypoint)
    {
        // All the async code occurs here, like:
        await(this->foo = bar());
        std :: cout << this->foo << std :: endl;
        await(this->foo2 = bar2());
        std :: cout << this->foo2 << std :: endl;
    }
    
  • await(assignment)宏实际上定义了表单中的内容:

    this->entrypoint = (some value x);
    return;
    case x:
    

现在,这显然不如我们可以拥有的成熟async function那么紧凑,例如,在Javascript中,但它足以满足我的需求。这也防止了嵌套开关(我很少使用它),你不能在本地定义变量,除非你以某种方式将它们包装在{ /*..*/ }中。但是我得到了一种使用同步样式进行异步操作的超级紧凑方式。

备注:这个策略的缺点和缺点对我来说非常清楚,这不是我的问题,我只是添加了这个来帮助理解我需要的东西。

问题

以上编译并运行良好。但是,我遇到了一个严重的问题:在await宏中,我需要生成一些在x语句中使用的唯一值case。到目前为止,我正在使用__LINE__来完成它,它可以很好地工作并防止碰撞用于大多数实际目的。但是,当您在同一行上写两个await语句时会发生什么?

所以我想知道:有没有比使用__LINE__唯一标识对宏的调用更好的方法,这样每当我从代码中的两个不同位置调用相同的宏时,我会得到不同的扩展值?< / p>

1 个答案:

答案 0 :(得分:3)

模板实例化(不稳定)

类型系统提供了创建编译时变量的方法;但是,它没有提供任何在调用之间维持状态的方法。

但是,使用here描述的方法,您可以通过检查已创建的哪些函数可以在模板系统中创建constexpr计数器,这可能对您有用;然而,这个系统依赖于gcc生成函数的方式的一些承诺,并且可能在将来不起作用,它目前在clang上失败。

因为这里的所有内容都在编译时运行(主要在类型系统中),所以你既可以使用switch语句中的值,也可以在运行时使用(几乎)零开销。

宏功能(全局范围)

This post描述了一种完全用宏构建编译时间计数器的方法;但是,要使值constexpr创建新函数,只能从函数外部递增。

__COUNTER__分机号

预处理器的标准没有提供请求唯一值的方法;但是,如__COUNTER__评论中提到的#define aswitch(x) \ int position_counter=0; if(this->entrypoint==position_counter++) #define await(x) \ this->entrypoint=position_counter; \ }else if(this->entrypoint==position_counter++){ aswitch(this->entrypoint) { await(bar()); std :: cout << this->foo << std :: endl; await(bar2()); std :: cout << this->foo2 << std :: endl; } 将执行请求的任务。 GCC has an extensionVisual Studio也支持此功能。

不使用开关

一个简单的修复(虽然我对你的实现知之甚少)可能是删除switch语句,而不是链接if else-if集。

static struct addr_map
{
   __u32 paddr,vaddr;
   ssize_t size;
}*lp;