编译时间断言不可靠?

ima*_*age 2 c++ static-assert

我正在阅读《现代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);
}
Run Code Online (Sandbox Code Playgroud)

对于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);
}
Run Code Online (Sandbox Code Playgroud)

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


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

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

L. *_* F. 5

这称为最烦人的解析。以下语句:

CompileTimeChecker<expr>(Type());
Run Code Online (Sandbox Code Playgroud)

相当于

CompileTimeChecker<expr> Type();
Run Code Online (Sandbox Code Playgroud)

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

CompileTimeChecker<expr> var = Type();
Run Code Online (Sandbox Code Playgroud)

这样,就不能将其解释为声明。{}从C ++ 11开始,您还可以使用初始化。另一方面,

CompileTimeChecker<expr>(Type(0));
Run Code Online (Sandbox Code Playgroud)

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

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

  • 括号并不能解决我的问题,因为`function((a))`等于`function(a)`。但是您对函数/构造函数的歧义是正确的。编写`CompileTimeChecker &lt;expr&gt;(Type {});`对我来说是固定的(即,使用统一初始化)。你能更新你的答案吗? (2认同)