是否可以编写这些 pure_assert 和 const_assert 宏?

发布于 2024-11-17 02:30:23 字数 503 浏览 0 评论 0原文

GCC __attribute__((pure))__attribute__((const)) 分别允许将函数声明为无副作用和引用透明;假设我想编写 pure_assertconst_assert 宏,其参数必须是适当严格级别的表达式,即:

assert(oops_a_side_effect());

默默地导致调试和发布中的不同行为,但是:

pure_assert(oops_a_side_effect());
const_assert(oops_read_a_global());

至少在调试版本中会出现编译时错误。由于我希望是显而易见的原因,您不能只创建一个声明 __attribute__((pure))pure_assert_impl 并将宏扩展到它。那么这些宏可以写吗?

The GCC __attribute__((pure)) and __attribute__((const)) allow functions to be declared as non–side-effecting and referentially transparent, respectively; let's say I want to write pure_assert and const_assert macros, whose argument must be an expression of the appropriate level of strictness, that is:

assert(oops_a_side_effect());

Silently results in different behaviours in debug and release, but:

pure_assert(oops_a_side_effect());
const_assert(oops_read_a_global());

Would be a compile-time error, at least in debug builds. For what I should hope are obvious reasons, you can't just create a pure_assert_impl declared __attribute__((pure)) and have the macro expand to it. So is it possible to write these macros?

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

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

发布评论

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

评论(4

十六岁半 2024-11-24 02:30:23

gcc 是否强制规定 pureconst 函数不能分别调用非纯函数或非常量函数?如果是这样,您可以定义一个正确属性的函数模板,它将函数指针作为模板参数,并让宏扩展为该函数模板的调用。我假设您需要支持带有参数的函数,这对于 C++0x 可变参数模板或 lambda 来说效果更好。

Does gcc enforce that pure and const functions cannot call non-pure or non-const functions, respectively? If so, you could define a properly attributed function template which takes a function pointer as a template parameter, and let the macro expand to an invocation of that function template. I assume you need to support functions that take parameters, this would work better with C++0x variadic templates or lambdas.

一片旧的回忆 2024-11-24 02:30:23

gcc 不以任何方式强制纯度或引用透明度。这些属性只是给优化器的提示。所以答案是否定的。

gcc does not enforce purity or referential transparency in any way. These attributes are just hints for the optimiser. So the answer is no.

多情癖 2024-11-24 02:30:23

我怀疑是否有一个真正好的解决方案,但我发现了类似const_assert()的可能性,它似乎可以工作我有两个版本的 gcc(4.1.2 和 4.4.4)。

#include <assert.h>

extern void dummy_void_function(void);

#define const_assert(x) \
  assert(__builtin_choose_expr(__builtin_constant_p((x) == (x)), \
         (x), dummy_void_function()))

extern int function(void);
extern int __attribute__((pure)) pure_function(void);
extern int __attribute__((const)) const_function(void);
extern int global;
extern volatile int volatile_global;

void test(int arg)
{
  /* These cause compile-time errors: */
  const_assert(function() == 0);
  const_assert(pure_function() == 0);
  const_assert(volatile_global == 0);

  /* These don't: */
  const_assert(const_function() == 0);
  const_assert(arg == 0);
  const_assert(global == 0);
}

这实际上是在检查表达式 (x) == (x) 是否被编译器视为编译时常量,如果不是,则会造成损坏。 “好的”情况实际上变成了 assert(x); 而坏的情况会生成编译时错误:

$ gcc -c const_assert.c
const_assert.c: In function 'test':
const_assert.c:18: error: void value not ignored as it ought to be
const_assert.c:19: error: void value not ignored as it ought to be
const_assert.c:20: error: void value not ignored as it ought to be

但是,启用优化后,它仍然会在预期的情况下产生错误,但其中之一是有点奇怪:

$ gcc -O -c const_assert.c
const_assert.c: In function 'test':
const_assert.c:18: error: void value not ignored as it ought to be
const_assert.c:19: error: first argument to '__builtin_choose_expr' not a constant
const_assert.c:20: error: void value not ignored as it ought to be

...您会期望 __builtin_constant_p() 的结果根据定义被视为常量!所以我不确定我是否真的会相信真正的代码......

(而且我现在对 pure_assert() 没有任何好主意!)

I doubt that there's a really good solution for this, but I've found a possibility for something like const_assert(), which appears to work with the two versions of gcc I have readily to hand (4.1.2 and 4.4.4).

#include <assert.h>

extern void dummy_void_function(void);

#define const_assert(x) \
  assert(__builtin_choose_expr(__builtin_constant_p((x) == (x)), \
         (x), dummy_void_function()))

extern int function(void);
extern int __attribute__((pure)) pure_function(void);
extern int __attribute__((const)) const_function(void);
extern int global;
extern volatile int volatile_global;

void test(int arg)
{
  /* These cause compile-time errors: */
  const_assert(function() == 0);
  const_assert(pure_function() == 0);
  const_assert(volatile_global == 0);

  /* These don't: */
  const_assert(const_function() == 0);
  const_assert(arg == 0);
  const_assert(global == 0);
}

This is really checking whether the expression (x) == (x) is regarded as a compile-time constant by the compiler, and creating brokenness if it's not. The "good" cases effectively become assert(x); and the bad ones generate compile-time errors:

$ gcc -c const_assert.c
const_assert.c: In function 'test':
const_assert.c:18: error: void value not ignored as it ought to be
const_assert.c:19: error: void value not ignored as it ought to be
const_assert.c:20: error: void value not ignored as it ought to be

However, with optimisation enabled, it still produces errors in the expected cases, but one of them is a bit odd:

$ gcc -O -c const_assert.c
const_assert.c: In function 'test':
const_assert.c:18: error: void value not ignored as it ought to be
const_assert.c:19: error: first argument to '__builtin_choose_expr' not a constant
const_assert.c:20: error: void value not ignored as it ought to be

...you'd expect the result of __builtin_constant_p() to be regarded as a constant by definition! So I'm not sure that I would really trust this for real code...

(And I don't have any good ideas right now for pure_assert()!)

素年丶 2024-11-24 02:30:23

恐怕运气不好。即使在编译器开始查看代码之前,预处理器也会扩展宏。

解决方案可能是让断言测试表达式在无论发布或调试模式下都进行评估,但仅在调试模式下测试结果。

Tough luck, I'm afraid. Macros are expanded by the preprocessor, even before the compiler starts looking at the code.

What maybe could be a solution, is to let the assert test expression be evaluated regardless of release or debug mode, however let the result be tested only in debug mode.

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