【问题标题】:How can I convert this c++ template function to a C alternative?如何将此 c++ 模板函数转换为 C 替代方案?
【发布时间】:2011-12-07 10:10:09
【问题描述】:

我正在将一个小型 C++ 库的一部分转换为 C (gcc)。在这样做时,我想将以下模板函数转换为宏(为便于阅读而删除了 cmets)。 CpuReadWriteFence() 是另一个我已经成功转换为宏的函数。

template<typename T>
static inline T AtomicLoadAcquire(T const* addr)
{
    T v = *const_cast<T const volatile*>(addr);
    CpuReadWriteFence();
    return v;
}

由于 C 语言中没有模板,我要么使用函数,要么使用宏。 GCC 提供了一个 方便的类型扩展。也许我可以用 void* 做到这一点?如果有怎么办?

到目前为止,我所拥有的是:

#define AtomicLoadAcquire(addr)                                       \
    ({ typeof (addr) v = *(volatile typeof (addr) *)(addr); CpuReadWriteFence(); })

但是,这不允许我这样做:

int x = AtomicStoreRelease(&bla);

我将如何解决这个问题?

【问题讨论】:

  • 我想知道,你为什么要从 C++ 转换为 C ?在旁注中,如果您的编译器支持 C1x 功能,您可以使用 _Generic 关键字。
  • 没有 c1x。我将把这段代码链接到用 C 编写的更大的代码中。我真的不想为此引入 C++ 库。现在这里很少有 C++ 位。

标签: c++ c templates gcc equivalent


【解决方案1】:

您不能使用宏返回值。试试这个:

#define AtomicLoadAcquire(addr, ref)                                       \
  ({ typeof (addr) v = *(volatile typeof (addr) *)(addr); CpuReadWriteFence(); ref = v; })

int x;
AtomicStoreRelease(&bla, x); // Instead of int x = AtomicStoreRelease(&bla);

【讨论】:

    【解决方案2】:

    你几乎猜对了。 GCC "statements and declarations in expressions" 扩展不必返回 void。

    复合语句的最后应该是一个表达式,后跟一个分号;此子表达式的值用作整个构造的值。 (如果在大括号中最后使用某种其他类型的语句,则该构造的类型为 void,因此实际上没有值。)

    因此您可以将宏定义为:

    #define AtomicLoadAcquire(addr)                                       \
    ({ typeof (*addr) v = *(volatile typeof (addr) )(addr); CpuReadWriteFence(); v; })
    

    注意宏末尾的v;。这就是魔法的来源。

    还要注意第一个typeof*addr 作为参数,volatile typeof(addr) 之后没有星号。这些是与您的主要问题无关的一些小错误。

    【讨论】:

    • +1,如果已经使用了也可以使用其他gcc扩展!
    • Matt H 已经在使用 ({ }) 扩展,只是没有完全使用它。
    【解决方案3】:

    能否将返回值添加为宏参数?类似的东西:

    #define AtomicLoadAcquire(addr, ret)                                       \
        ( typeof (addr) v = *(volatile typeof (addr) *)(addr); CpuReadWriteFence(); )
    

    这很丑,但它会为你做到这一点:

    AtomicLoadAcquire(someaddr, x);
    

    翻译成:

    /* assuming someaddr is int* */
    int x = *(volatile int *)(someaddr); CpuReadWriteFence(); 
    /* now you have x defined */.
    

    这正是你想要的。

    其他选项(如 miaout17 所述)是在调用宏之前声明 x,然后删除开头的“typeof(addr)”,这样会更安全,恕我直言。

    【讨论】:

      【解决方案4】:

      在宏中传递类型可能是你能做的最好的事情:

      static inline const volatile void* AtomicLoadAcquire_f(void const* addr)
      {
          const volatile void* v = (void const volatile*)addr;
          CpuReadWriteFence();
          return v;
      }
      #define AtomicLoadAcquire(type, pointer) \
       (*((const volatile type*)AtomicLoadAcquire_f(pointer)))
      
      int x = AtomicLoadAcquire(int, &bla);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-12
        • 1970-01-01
        • 2019-09-29
        相关资源
        最近更新 更多