偷窥Boost Conversion Library

转载 2005年05月07日 12:23:00
偷窥Boost Conversion Library

 

yewuyu提示:类型转换

 

一、与多态类型相关的转换

1、 polymorphic_castdynamic_cast

dynamic_cast可以安全地将一个指向多态对象的指针向下转换为派生类指针。但是,当dynamic_cast转换失败时,返回的是NULL,也就是说,dynamic_cast的转换成功与否是在运行期确定,而不像其他C++内建cast那样在编译期确定。换言之,如果在进行dynamic_cast之后,不检测返回值,就等于埋下了一个定时炸弹。

Boostpolymorphic_castdynamic_cast的基础上增加了对返回值的检测,如果转换失败,它就会抛出std::bad_cast

2、 polymorphic_downcastdynamic_cast

但是抛出异常会降低程序的效率,而且dynamic_cast更会查询一个type_info结构来确定正确的类型,所以不管是空间上的成本还是时间上的成本,都会大大增加。

polymorphic_downcast可以把成本降低到最低,甚至是编译期上。不过使用这个转换必须非常的小心。

//#define NDEBUG

#include<cassert>

using namespace std;

struct A{

   virtual ~A(){}

};

class B:public A{};

class C:public A{};

 

int main(){

    A *pa=new C;

    B *pb=polymorphic_downcast<B*>(pa);

}

注意上面没有定义NDEBUG(或编译器的调式模式),这样才能在调试时,判断polymorphic_downcast是否成功。最后,当一切OK的时候,再将定义NDEBUG(或关闭编译器的调试模式)。这样在最终的软件中,polymorphic_downcast即保证了安全的转换,又保证了低运行成本。

3、 窥其内部

template <typename Target, typename Source>

inline Target polymorphic_cast(Source*x){

        Target tmp = dynamic_cast<Target>(x);

        if ( tmp == 0 ) throw std::bad_cast();

        return tmp;

}

polymorphic_cast本质上还是一个dynamic_cast

现在来关心一下polymorphic_downcast

template <typename Target, typename Source>

inline Target polymorphic_downcast(Source* x){

        assert( dynamic_cast<Target>(x) == x );

        return static_cast<Target>(x);

}

可以看到polymorphic_downcast里用到了assert。当在调试模式下,assert将起到非常关键的作用。如果dynamic_cast转换成功,那么static_cast必然不会出现问题。当在调试模式下一切就绪后,关闭assert的功能,那么就可以保证最后在static_cast下也不会出现问题。这样就把运行成本降低了。

 

二、与数字相关的转换

1numeric_caststatic_cast和隐式转换

先来看一个将double类型的整数转换为int类型的数static_cast的转换。

double d=10;

int i=static_cast<int>(d); //int i(d);

对于这个转换看不出任何的缺陷,不过唯一可以肯定的是double8Bytes,而int只有4Bytes,这也说明了转换后的值极有可能不正确。例如尝试把d的值改为9999999999,你就会发现转换后i的值变得极为畸形。虽然这样的转换算得上是失败的转换,但是并不是所有从“大”类型到“小”类型的转换都是失败的转换,也不是所有从“小”类型到“大”类型的转换都是合格的转换。

Boostnumeric_cast可以帮我们解决这样的问题。例如对于上面的,当d9999999999,那么转换必将失败,numeric_cast就抛出boost:: bad_numeric_cast这个异常对象。这样,就能保证转换后值的有效性。用法见下。

double d=10;

int i;

try{

   i=boost::numeric_cast<int>(d);

}

catch(boost::bad_numeric_cast&){

     std::cout<<”The conversion failed”<<std::endl;

}

对于numeric_cast的使用是有要求的。

1、 源类型和目标类型必须都是可拷贝构造的

2、 源类型和目标类型必须都是数字型类型。也就是被std::numeric_limits<>::is_specialized的特化定义为true

3、 源类型必须能被static_cast转换为目标类型

2、窥其内部

numeric_cast是如何知道这样的数字转换失败的呢?numeric_cast合理的应用了std::numeric_limits<>,而std::numeric_limits<>就是内建数字类型的type_tratis。当然也可以将自己定义的数字抽象类型添加到std::numeric_limits<>的特化版本中,这样numeric_cast就可以作用于自定义的类型了。

template<typename Target, typename Source>

inline Target numeric_cast(Source arg){

      typedef detail::fixed_numeric_limits<Source> arg_traits;

      typedef detail::fixed_numeric_limits<Target> result_traits;

if (

(arg<0 && !result_traits::is_signed)   //条件一

|| (arg_traits::is_signed && arg < result_traits::min())  //条件二

|| arg > result_traits::max()) ) //条件三

{

            throw bad_numeric_cast();

      }

        return static_cast<Target>(arg);

} // numeric_cast

条件一:如果源类型对象的当前值小于0,而且目标类型是无符号型(unsigned)的,那么转换失败。

条件二:如果源类型对象是有符号型的,而且它的当前值小于目标类型所容纳的最小值,那么转换失败。

条件三:如果源类型对象的当前值大于目标类型的最大值,那么转换失败。

如果这三个条件都不满足,那么就可以放心大胆的用static_cast转换这个数字类型。

 

三、与值和类型相关的类型转换

1、 lexical_cast

在程序开发中,往往需要将数字型对象的值转换为字符文本格式,或反之操作。我们在C/C++标准程序库中可以找到这样的函数来进行转换,例如atoi。但是他们都有个通病,使用复杂,缺少扩展性,更重要的是不够安全。

使用lexical_cast就可以把这样的操作简单化。

 

try{

     int i= 100;

     string str= lexical_cast<string>(i);

     cout<<"The string is:"<<str<<endl;

        

     str="error";

     i=lexical_cast<int>(str);

}

catch(bad_lexical_cast& exobj){

     cout<<"No, you can't convert a /"error/" to a int"<<endl;

     cout<< exobj.what() << endl;

}

 

当把"error"转换为int时,这个错误就会被lexical_cast发现,然后抛处boost::bad_lexical_cast这个异常对象。

对于lexical_cast的使用也是有要求的:

1、 源类型必须能被输出流std::ostreamstd::wostream对象用operator<<()操作

2、 目标类型必须能被输入流std::istreamstd::wostream对象用operator>>()操作

3、 源类型和目标类型必须都是可拷贝构造的

4、 目标类型必须拥有default constructor

2、 窥其内部

template<typename Target, typename Source>

Target lexical_cast(Source arg){

        detail::lexical_stream<Target, Source> interpreter;

        Target result;

        if(!(interpreter << arg && interpreter >> result))

            throw_exception(bad_lexical_cast(typeid(Target), typeid(Source)));

        return result;

}

其中lexical_stream<>对字符串流做了一系列的包装,主要提供了operator<<(Source)operator>>(Target)操作,这两个操作的返回类型是bool,用于判断操作是否成功。

Target result;用于返回,这说明了目标类型必须拥有default constructor的原因。

interpreter<< arginterpreter>>result就是将arg的值放入到字符串流,把字符串流里的值放入result

如果操作失败,就抛出bad_lexical_cast对象。其中bad_lexical_cast对象里保存了源类型和目标类型的type_info对象的地址,这样就方便了对错误类型的查询。

 

return 0; //end

参考来源:Boost Conversion Library Documents

C++“准”标准库Boost学习指南(2):Boost.Conversion

Conversion库包含有一些函数,它们是现有的强制类型转换操作符(static_cast, const_cast, 和 dynamic_cast)的增强。Conversion为安全的多态转换增加了...
  • cbNotes
  • cbNotes
  • 2016年10月19日 13:17
  • 781

C++“准”标准库Boost学习指南(2):Boost.Conversion

Conversion库包含有一些函数,它们是现有的强制类型转换操作符(static_cast, const_cast, 和  dynamic_cast)的增强。Conversion为安全的多...
  • pud_zha
  • pud_zha
  • 2014年07月10日 14:37
  • 612

分隔和截断字符串, boost string algorithm library中的split和trim

http://www.boost.org/doc/libs/1_46_1/doc/html/string_algo.html 这个库是个 headers only library  这个库提供了...

了解 Boost Filesystem Library

C++ 语言(实际上是 C++ 标准)的最常见问题之一是,缺乏定义良好的库来帮助处理文件系统查询和操作。由于这个原因,程序员不得不使用本机操作系统提供的应用程序编程接口(Application Pro...

Thread Interruption in Boost Thread Library

One of the new features introduced in the upcoming 1.35.0 release of the boost thread library is s...

Visual Studio install boost library

boost是C++开发的一个第三方类库,并且是很重要的一个类库,下面简单讲述一下其安装和使用过程。...

使用C++ Boost Graph Library 进行社交网络分析入门篇

前言:      社交网络分析是一个常常会遇到的业务问题,故而笔者也一致在不断尝试不同的社交网络分析工具。之前使用过python networkx, igraph C library, 今日再介...

使用boost graph library计算图中点和边的betweenness

项目中用到的东西,betweenness是社交网络里的概念。基于的思想是betweenness高的点和边在网络中更重要。betweenness具体定义见这里 搜了一下发现boost已经有实现,但是用...

Boost Lambda Library——BLL C++ 模板库

Boost Lambda Library(简称为 BLL)是一个 C++ 模板库,为 C++ 实现了 lambda abstractions 的形式。这个术语起源于函数式编程和 lambda 演算,一...

Boost Graph Library 快速入门

Boost Graph Library 快速入门    图领域的数据结构和算法在某些方面比容器更为复杂,图算法在图中移动有着众多的路线,而STL使用的抽象迭代器接口不能有效的支持这些。作为替换,我们...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:偷窥Boost Conversion Library
举报原因:
原因补充:

(最多只允许输入30个字)