我怎样才能转换这个c++模板函数是 C 语言的替代品吗?

发布于 2024-12-20 10:49:56 字数 698 浏览 1 评论 0原文

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

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

由于 C 中没有模板,我要么使用函数,要么使用宏。海湾合作委员会提供了 方便的扩展类型。也许我可以用 void* 来做到这一点?如果是这样怎么办?

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

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

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

int x = AtomicStoreRelease(&bla);

我将如何解决这个问题?

I'm converting parts of a small C++ library to C (gcc). In doing so I'm wanting to convert the following template function to a macro (comments removed for readibility). CpuReadWriteFence() is another function that I've converted to a macro successfully.

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

Since there are no templates in C I'm either using functions or macros. GCC provides a
convenient typeof extension. Perhaps I could do it with void*? if so how?

What I have so far is this:

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

However, that won't allow me to do this:

int x = AtomicStoreRelease(&bla);

How would I get around this ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不及他 2024-12-27 10:49:56

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

#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);

You can't return a value with a macro. Try this:

#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);
冰雪梦之恋 2024-12-27 10:49:56

你几乎做对了。 GCC “表达式中的语句和声明” 扩展不必返回 void。

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

因此您可以将宏定义为:

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

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

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

You almost got it right. The GCC "statements and declarations in expressions" extension does not have to return void.

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)

So you can define your macro as:

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

Note the v; at the end of the macro. That's where the magic comes from.

Also note that the first typeof takes *addr as an argument and there is no star after volatile typeof(addr). Those were some minor bugs unrelated to your main problem.

走过海棠暮 2024-12-27 10:49:56

您可以将返回值添加为宏参数吗?类似这样的东西:

#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)”,这样会更安全,恕我直言。

Can you add the return value as a macro parameter? Something like that:

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

It's ugly but this will do this for you:

AtomicLoadAcquire(someaddr, x);

translated to:

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

Which would be exactly as you want it.

Other option (as mentioned by miaout17) is to declare x before calling the macro, and then remove the "typeof(addr)" in the beginning, that would be safer, IMHO.

雄赳赳气昂昂 2024-12-27 10:49:56

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

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);

Passing the type in the macro is probably the best you can do:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文