Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1065440
  • 博文数量: 77
  • 博客积分: 11498
  • 博客等级: 上将
  • 技术积分: 1840
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-04 11:10
文章分类

全部博文(77)

文章存档

2011年(1)

2010年(16)

2009年(5)

2008年(55)

分类: C/C++

2008-11-23 14:19:42

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:
阅读(3382) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-12-22 22:06:10

1 把你的问题描述清楚 2 把你出问题的代码简化后贴出来 BTW,我希望你不是误解了BOOST_STATIC_ASSERT

chinaunix网友2009-12-22 20:47:28

sorry, I thought u were using BOOST_STATIC_ASSERT. I am using the gcc version 3.4.4 , it is supposed that BOOST_STATIC_ASSERT can be used, however, it did not work out. Do you know where the problem is?(of course I included the header file and implemented in a right way, there still were some error msg indicated static assert can not been used). Thank u in advance

chinaunix网友2009-12-22 20:41:59

只有GCC 4.3以上版本才支持静态断言??version 3.3,3.4 can be used according to the src