编译时断言不可靠

Compile Time Assertion is Unreliable?

本文关键字:不可靠 断言 编译      更新时间:2023-10-16

我正在阅读"现代C++设计"一书的第一章。特别是编译时断言。我对以下代码有一些问题:

template<bool> struct CompileTimeChecker
{
  CompileTimeChecker(...) {}
};
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg)
{
  struct ERROR_##msg {ERROR_##msg() {}};
  CompileTimeChecker<((expr) != 0)>(ERROR_##msg());
}
int main()
{
  STATIC_CHECK(0, MessageNull);
  STATIC_CHECK(1, MessageOne);
}

这不会引发 g++ 7.4.0 和 clang++ 6.0.0 的编译时错误。但是,以下代码确实会引发错误(如预期(:

template<bool> struct CompileTimeChecker
{
  CompileTimeChecker(...) {}
};
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg)
{
  struct ERROR_##msg {ERROR_##msg(int i) {i;}};
  CompileTimeChecker<((expr) != 0)>(ERROR_##msg(0));
}
int main()
{
  STATIC_CHECK(0, MessageNull);
  STATIC_CHECK(1, MessageOne);
}

第二个代码中的唯一区别是使用带有参数的构造函数。


这两种情况下的预期错误消息都是:

  • G++: no matching function for call to ‘CompileTimeChecker<false>::CompileTimeChecker(main()::ERROR_MessageNull)
  • 叮当当++: no matching conversion for functional-style cast from 'ERROR_MessageNull' to 'CompileTimeChecker<(0 != 0)>'

被称为最令人烦恼的解析。 以下语句:

CompileTimeChecker<expr>(Type());

相当于

CompileTimeChecker<expr> Type();

它声明一个名为 Type 的函数。 您可以使用初始化的=形式解决此问题:

CompileTimeChecker<expr> var = Type();

这样,它就不能被解释为声明。 您还可以使用自 C++11 以来的{}初始化。 另一方面

CompileTimeChecker<expr>(Type(0));

是一个表达式语句,它根据需要创建对象Type(0)因为它不可能声明函数。

从 C++11 开始,只需使用 static_assert .