此代码使用模板演示编译时断言。 我发现它只能用g ++(4.4.7)编译,并带有以下cmd行。
$ g++ -std=c++98 a.cpp -o a
Nether icc(13.0.1)和visual c ++(80x86的14.00.50727.762)都可以编译它。对于icc,它会像这样生成错误消息
$ icpc a.cpp -o a
a.cpp(13): error: non-integral operation not allowed in nontype template argument
COMPILE_TIME_ASSERT(true && "err msg");
^
a.cpp(13): error: class "CompileTimeAssert<<error-constant>>" has no member "Check"
COMPILE_TIME_ASSERT(true && "err msg");
^
compilation aborted for a.cpp (code 2)
但是我发现像true && "err msg"
这样的断言在运行时断言中广泛用作Add custom messages in assert?
问题是
演示代码如下所示。
#include <iostream>
template<bool B> class CompileTimeAssert { };
template<> class CompileTimeAssert<true> {
public:
static inline void Check() { }
};
#define COMPILE_TIME_ASSERT(b) CompileTimeAssert<(b)>::Check()
int main()
{
COMPILE_TIME_ASSERT(true && "err msg");
std::cout<<(true && "err msg")<<std::endl;
return 0;
}
答案 0 :(得分:0)
对第一个问题的回答是“否”。传递给模板的参数称为“非类型模板参数”。根据标准,这些论点必须是:
常量表达式,具有外部链接的函数或对象的地址,或静态类成员的地址。
严格来说,true && "err msg"
这样的表达式无法在编译时确定。这就是为什么它可以用于运行时断言,但不能用于编译时断言。 G ++在这里演示了非标准行为。
作为对第二个问题的回答,我提出以下模式:
#define STATIC_ASSERT(e,m) extern char (*__static_assert_failed(void)) [ 1 - 2*!(e) ]
__static_assert_failed
这里是一个指向外部函数的指针,返回一个字符数组。该数组的大小为1 - 2*!(e)
,如果e
为false,则会导致编译时错误。