原文出处:http://www.who1753.com/static_assert/
断言表示为一些布尔表达式,表示表达式在程序中某个特定点的值必须为真,否则就是程序设计或执行错误。程序员可以在任何时候启用或禁用断言验证,因此可以在测试时启用断言而在部署时禁用断言。使用断言可以创建更稳定、品质更好的代码。在之前的C++03标准中,可以使用两种断言:
1. 使用预处理中的条件编译和#error指令,可以在预处理阶段检查一些编译条件;2. 可以使用宏assert来进行运行时检查,以确保程序逻辑的正确性。
使用条件编译并不能对模版参数进行检查,这是因为模版实例化是在编译期进行的,而#error方法是在预处理阶段进行的。宏asser则是在运行时检查。很显然,这里缺少了可以在编译期对模版进行检查的工具。而静态断言恰好可以很好的解决这一问题。
静态断言的作用是提供一种编译阶段的断言机制,如果断言内指定的常量表达式为0(false),那么将出现一个编译错误,同时编译器会将用户指定的错误信息显示出来,否则没任何影响。
静态断言的使用语法如下:
static_assert(constant-expression, // 执行判断的常量表达式string-literal // 指定输出的错误信息);
第一个参数为可以转化为布尔类型的常量表达式(注意,必须为常量表达式,即在编译阶段就可以确定其值的表达式);第二个参数为一个字符串。实例如下:
static_assert(sizeof(void*)== 4, "64-bit code generation is not supported.");
而下面的用法则是错误的:
int d = rand()% 2;static_assert(d == 0, "variable is not even.");
由于在运行时才能确定d的值,所以d == 0不是常量表达式,不能使用静态断言。
下面举一个更复杂的例子来说明静态断言在处理模版参数方面的作用来作为结束内容。
#include <type_traits>#include <iosfwd>namespace std {template <class CharT, class Traits = std::char_straits<CharT>>class basic_string {static_assert(trl::is_pod<CharT>::value, "Template argument CharT must be a POD type in class template basic_string");// ...} ;}struct NonPOD {NonPOD(const NonPOD &){}virtual ~NonPOD{}};int main(){std::basic_string<char> bs;}
在上述代码中,静态断言在类作用域中,static_assert用于验证模版参数是否为POD类型。编译器在类定义时检查static_assert声明,但是直到在main()函数中将模版实例化为basic_string类时才能确定静态表达式参数的值。