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

时间:2011-06-27 09:53:18

标签: c++ gcc attributes const

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

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

4 个答案:

答案 0 :(得分:2)

gcc是否强制 pure const 函数分别不能调用非纯函数或非const函数?如果是这样,您可以定义一个正确归因的函数模板,该函数模板将函数指针作为模板参数,并让宏扩展为该函数模板的调用。我假设您需要支持带参数的函数,这样可以更好地使用C ++ 0x可变参数模板或lambdas。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

我怀疑是否有一个真正的良好的解决方案,但我发现像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()没有任何好的想法!)

答案 3 :(得分:0)

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

可能可能是一个解决方案,就是无论发布模式还是调试模式都要评估断言测试表达式,但是只能在调试模式下测试结果。