1. 静态断言的引入
我们知道,在C++03中我们可以使用两种断言:
(1)使用预处理中的条件编译和#error指令(后面简称#error方法),可以在预处理阶段检查一些编译条件;
(2)可以使用宏assert来进行运行时检查,以确保程序逻辑的正确性。
但使用#error方法很是烦琐,并且不能够对模板参数进行检查(因为模板实例化是在编译时进行,而#error方法是在预处理阶段进行的)。而assert是在运行时进行检查。不难发现,我们缺少了一样东西,那就是可用于在编译时检查的工具。于是,静态断言应运而生。
其实,BOOST对静态断言已支持多年(BOOST_STATIC_ASSERT),其内部实现中大量使用了静态断言。另外,在Modern C++ Design书中实现的Loki库也包含了静态断言。但这些实现都有明显的缺陷:
(1)诊断信息不够充分,难于准确定位错误根源(本质上源于它们的实现所限制);
(2)由于实现时需要产生新的类型来表示断言,在某种程序上造成了名字污染。
因此,在新版C++标准(C++0x)中,从语言层面加入了对静态断言的支持,引入了新的关键字static_assert来表示静态断言,并支持如下需求:
(1)编译时处理,不会产生任何运行时开销(包括时间和空间);
(2)断言失败会产生有意义的且充分的诊断信息;
(3)能够在名字空间、类和块的作用域内使用;
(4)易于学习和使用;
(5)误用能够在编译时被发现。
2. 静态断言的使用
静态断言声明的语法形式:static_assert (constant-expression, string-literal);
其中,constant-expression需要是整型常量表达式,string-literal是在断言失败时输出的提示信息。当constant-expression的布尔值为true时,该静态断言声明不会产生任何影响;否则,编译器将给出错误诊断信息。
3. 应用举例
(注:下面的示例均使用MinGW GCC 4.3版编译器编译测试,只有GCC 4.3以上版本才支持静态断言)
F:\tmp>gcc --version
gcc (GCC) 4.3.0 20080305 (alpha-testing) mingw-20080502
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
例1:在名字空间(包括全局名字空间)中使用静态断言
F:\tmp>type static_assert_eg1.cpp
static_assert(sizeof(int) == 8, "A 64-bit machine needed!");
int main()
{
return 0;
}
F:\tmp>gcc -std=c++0x static_assert_eg1.cpp
static_assert_eg1.cpp:1: error: static assertion failed: "A 64-bit machine needed!"
F:\tmp>type static_assert_eg2.cpp
static_assert(sizeof(int) == 4, "A 32-bit machine needed!");
int main()
{
return 0;
}
F:\tmp>gcc -std=c++0x static_assert_eg2.cpp
F:\tmp>
例2:在模板类中使用静态断言
F:\tmp>type static_assert_eg3.cpp
#include
#include
template >
class my_string
{
static_assert(std::tr1::is_pod::value,
"Template argument CharT must be a POD type in class template my_string");
// ...
};
struct NonPOD
{
NonPOD(const NonPOD &) {}
virtual ~NonPOD() {}
};
int main()
{
my_string s;
}
F:\tmp>gcc -std=c++0x static_assert_eg3.cpp
static_assert_eg3.cpp: In instantiation of 'my_string >':
static_assert_eg3.cpp:20: instantiated from here
static_assert_eg3.cpp:7: error: static assertion failed: "Template argument CharT must be a POD type in class template my_string"
(注:请读者把my_string的参数改为char再尝试编译)
F:\tmp>
例3:在函数中使用静态断言
F:\tmp>type static_assert_eg4.cpp
#include
using namespace std;
int CountOnes32(unsigned int num)
{
static_assert(sizeof(num) == 4, "int is NOT 32-bits!");
num = ((num >> 1) & 0x55555555) + (num & 0x55555555);
num = ((num >> 2) & 0x33333333) + (num & 0x33333333);
num = ((num >> 4) & 0x0F0F0F0F) + (num & 0x0F0F0F0F);
num = ((num >> 8) & 0x00FF00FF) + (num & 0x00FF00FF);
num = ((num >> 16) & 0x0000FFFF) + (num & 0x0000FFFF);
return (int)num;
}
int main()
{
cout << CountOnes32(0xFFFFFFFF) << endl;
cout << CountOnes32(0x00000000) << endl;
cout << CountOnes32(0x11111111) << endl;
cout << CountOnes32(0x55555555) << endl;
cout << CountOnes32(0x33333333) << endl;
cout << CountOnes32(0x0F0F0F0F) << endl;
cout << CountOnes32(0x00FF00FF) << endl;
cout << CountOnes32(0x0000FFFF) << endl;
cout << CountOnes32(0x3F9A83D1) << endl;
cout << CountOnes32(0x708DC8A2) << endl;
return 0;
}
F:\tmp>g++ -std=c++0x static_assert_eg4.cpp
F:\tmp>a.exe
32
0
8
16
16
16
16
16
17
13
F:\tmp>
参考:
Ref-1:
阅读(3432) | 评论(3) | 转发(0) |