天天看点

关键字 static_assert

C++0x中引入了static_assert这个关键字,用来做编译期间的断言,因此叫做静态断言。

其语法很简单:static_assert(常量表达式,提示字符串)。

如果第一个参数常量表达式的值为真(true或者非零值),那么static_assert不做任何事情,就像它不存在一样,否则会产生一条编译错误,错误位置就是该static_assert语句所在行,错误提示就是第二个参数提示字符串。

说明

使用static_assert,我们可以在编译期间发现更多的错误,用编译器来强制保证一些契约,并帮助我们改善编译信息的可读性,尤其是用于模板的时候。

static_assert可以用在全局作用域中,命名空间中,类作用域中,函数作用域中,几乎可以不受限制的使用。

编译器在遇到一个static_assert语句时,通常立刻将其第一个参数作为常量表达式进行演算,但如果该常量表达式依赖于某些模板参数,则延迟到模板实例化时再进行演算,这就让检查模板参数成为了可能。

由于之前有望加入C++0x标准的concepts提案最终被否决了,因此对于检查模板参数是否符合期望的重任,就要靠static_assert来完成了,所以如何构造适当的常量表达式,将是一个值得探讨的话题。

性能方面,由于是static_assert编译期间断言,不生成目标代码,因此static_assert不会造成任何运行期性能损失。

范例

下面是一个来自MSDN的简单范例:

static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");      

该static_assert用来确保编译仅在32位的平台上进行,不支持64位的平台,该语句可以放在文件的开头处,这样可以尽早检查,以节省失败情况下的编译时间。

再看另一个范例:

1: struct MyClass      
2: {      
3:     char m_value;      
4: };      
5:        
6: struct MyEmptyClass      
7: {      
8:     void func();      
9: };      
10:        
11: // 确保MyEmptyClass是一个空类(没有任何非静态成员变量,也没有虚函数)      
12: static_assert(std::is_empty<MyEmptyClass>::value, "empty class needed");      
13:        
14: //确保MyClass是一个非空类      
15: static_assert(!std::is_empty<MyClass>::value, "non-empty class needed");      
16:        
17: template <typename T, typename U, typename V>      
18: class MyTemplate      
19: {      
20:     // 确保模板参数T是一个非空类      
21:     static_assert(      
22:         !std::is_empty<T>::value,      
23:         "T should be n non-empty class"      
24:         );      
25:        
26:     // 确保模板参数U是一个空类      
27:     static_assert(      
28:         std::is_empty<U>::value,      
29:         "U should be an empty class"      
30:         );      
31:        
32:     // 确保模板参数V是从std::allocator<T>直接或间接派生而来,      
33:     // 或者V就是std::allocator<T>      
34:     static_assert(      
35:         std::is_base_of<std::allocator<T>, V>::value,      
36:         "V should inherit from std::allocator<T>"      
37:         );      
38:        
39: };      
40:        
41: // 仅当模板实例化时,MyTemplate里面的那三个static_assert才会真正被演算,      
42: // 藉此检查模板参数是否符合期望      
43: template class MyTemplate<MyClass, MyEmptyClass, std::allocator<MyClass>>;      

通过这个例子我们可以看出来,static_assert可以很灵活的使用,通过构造适当的常量表达式,我们可以检查很多东西。比如范例中std::is_empty和std::is_base_of都是C++新的标准库提供的type traits模板,我们使用这些模板可以检查很多类型信息。

-------------------------------------------------------------------------------------------------------------------------------------------------

                                  以上内容为本人学习摘录,来源多为网上搜索所得,如您认为侵犯您的版权,请留言告知,不胜感激。

---------------------