【问题标题】:An assert macro which expands to static_assert when possible?在可能的情况下扩展为 static_assert 的断言宏?
【发布时间】:2013-08-13 18:15:12
【问题描述】:

我有一些通用代码需要对成员函数的结果运行断言。这个成员函数可能是constexpr,也可能不是。

template<typename T>
void foo(T t) {
  assert(t.member_function() == 10);
}

因为t.member_function() 可能 是一个常量表达式,我想知道在这种情况下是否可以将其视为static_assert,否则默认为普通assert。这可能吗?

【问题讨论】:

标签: c++ assert static-assert


【解决方案1】:

这是一个有点疯狂的解决方案。

取消注释Const c; foo(c); 行,您会发现它无法编译。这是编译时断言。

它需要variable length arrays,也许还有其他编译器特定的东西。我在 g++-4.6 上。

数组的大小是 0 或 -1,取决于成员函数是否返回 10。所以如果这可以在编译时计算,那么编译器会意识到它是一个非可变长度数组,并且它有负尺寸。负尺寸允许它抱怨。否则,它会落入传统的断言。

请注意:在运行时断言失败后,我收到了一些运行时版本的核心转储。也许它不喜欢尝试free 一个负大小的数组。更新:我收到任何断言失败的核心转储,甚至是int main() {assert (1==2);}。这正常吗?

#include <iostream>
#include <cassert>
using namespace std;

struct Const {
        constexpr int member_function() { return 9; }
};
struct Runtime {
                  int member_function() { return 9; }
};

template<typename T>
void foo(T t) {
        if(0) {  // so it doesn't actually run any code to malloc/free the vla
            int z[(t.member_function()==10)-1]; // fails at compile-time if necessary
        }
        assert(t.member_function()==10);
}


int main() {
        //Const c; foo(c);
        Runtime r; foo(r);
}

【讨论】:

  • 酷黑客。尽管我假设编译器足够聪明,可以直接忽略 if(0)。大声笑,如果 if 语句中有一个 false 的 constexpr 会怎样。但我想如果可以尝试用 constexpr 创建 -1 大小的数组来编译里面的内容,这会导致断言失败。
猜你喜欢
  • 2015-03-22
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 2019-05-06
  • 1970-01-01
  • 1970-01-01
  • 2021-11-21
  • 1970-01-01
相关资源
最近更新 更多