编译时断言不可靠?
Compile Time Assertion is Unreliable?
我正在阅读本书的第一章 "Modern C++ Design"。特别是编译时断言。我对以下代码有一些问题:
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)
- clang++:
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
.
我正在阅读本书的第一章 "Modern C++ Design"。特别是编译时断言。我对以下代码有一些问题:
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)
- clang++:
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
.