首页 > 解决方案 > 编译时间断言不可靠?

问题描述

我正在阅读“现代 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);
}

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


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

标签: c++static-assert

解决方案


这被称为最令人头疼的解析。以下声明:

CompileTimeChecker<expr>(Type());

相当于

CompileTimeChecker<expr> Type();

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

CompileTimeChecker<expr> var = Type();

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

CompileTimeChecker<expr>(Type(0));

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

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


推荐阅读