2009年3月15日星期日

【原】Boost库之tuple、any和variant的使用

Boost库中提供了三种比较实用的数据结构,分别是tuple、any和variant。它们的共同优点就是支持类型安全地存储和获取数据。灵活地使用这三种数据结构,对我们进行程序设计无疑是大有裨益的。下面分别加以介绍。
tuple支持一次直接声明和使用n个不同数据类型的变量。对于有多个返回值的函数,我们再也不用定义一个结构体作为函数的返回值类型了,也不用通过对参数进行引用来传出返回值(这样返回值的概念不太明确),而是可以直接使用tuple。
◆ 声明一个tuple类型的对象:tuple<int,double,string> triple(42, 3.14, "hello world");
◆ 获得tuple中某个变量的值:string s = get<2>(triple);
◆ 获得tuple中所有变量的值:tie(nAdd, dbSub, strText) = triple;
◆ 通过几个变量构造一个tuple类型的变量:tuple<int,int> temp = make_tuple(3, 5);
any支持存储任意类型的变量,但它只允许你在知道类型的前提下访问它的值。如果类型不符合,则any会抛出一个bad_any_cast的异常。如果访问的是指针,则类型符合时返回的指针是一个有效值,否则返回的指针为空(此时不会抛出异常)。
◆ 给any赋任意类型的值:any a; a = 42; a= string("hello world"); a=3.14;
◆ 获得any中存储的值:double dbTemp = any_cast<double>(a);
◆ 获得any中存储值的指针:string *pString = any_cast<string *>(a);
variant支持存储和操作来自于多个不同类型的变量。获得variant中当前存储的值时,如果给定的类型与实际存储值的类型不符合,会抛出一个bad_get的异常。如果要获得的是指针,则类型符合时返回的指针是一个有效值,否则返回的指针为空(此时不会抛出异常)。这里需要着重谈一下variant与tuple和any的区别:tuple可以保存n个变量的值,而variant只能保存一个变量的值; any可以保存任意类型的变量,而variant只能保存指定数据类型的变量。
◆ 声明一个variant类型的对象:variant<int,double,string> va("hello world");
◆ 给variant赋值: va=3.14; va=42;
◆ 获得variant中当前存储的值:int nTemp = get<int>(va);
◆ 获得指向variant中存储的值的指针:string *pString = get<string *>(&va);

4 条评论:

  1. 1.tuple是个特殊的“结构体”(有人称之为匿名结构体),但是我们不用再在“全局”声明它,个人认为这是一个伟大的带有革命性的创举;有了tuple,你还会去定义一个结构体么?
    2.any犹如一个“基类”,类似于void *,比它强大些,但还不如MFC的CObject或者Java里的object这样的类型。3.variant比any稍微强调类型一点。
    4.最后比较这三种类型的部分说的比较好。

    最后总结一下,弱化类型或者说抽象“基类”将是编程语言的发展方向,因为它能够简化转换逻辑,增强代码可读性,提高开发效率,所以必将成为趋势。

    回复删除
  2. 我们的文章里出现'<'和'>'字符时,会被系统把之间的内容全部去掉,所以大家看这篇文章的时候,可能语法不太正确。以后可以用&lt代替<,用&gt代替>。

    回复删除
  3. 刚才和hujian沟通了下,tuple是支持自定义类型的,例如一个turple对象里有一个类对象,那它可以这样声明tuple < int,double,CTest > triple(42, 3.14, CTest()); CTest()是CTest类的构造函数。

    回复删除
  4. 不是一样的么,有什么区别?

    回复删除