原文地址:http://www.cnblogs.com/TianFang/archive/2008/09/29/1301880.html
Boost的轉換函式(二)
在c++中,我們經常需要把不同類型的數字互相轉換,如將一個數字在long和short之間轉換。但由於各數位精度不同,當一個數字從"大"類型到"小"類型就可能導致轉換失敗,如下所示:
long n1 = 99999999;
short n2 = static_cast<short>(n1);
對於如上轉換,n2得到的是一個負數,顯然這個不是我們所期望的,並且這種運行時的錯誤是很難檢測的,一旦使用了這個錯誤的轉換後的資料,後果不堪設想。
boost::numeric_cast可以協助我們解決這一問題,對於上面的轉換,boost::numeric_cast會拋出一個boost:: bad_numeric_cast這個異常對象。從而保證轉換後值的有效性。上述代碼可以改寫為如下:
try
{
long n1 = 99999999;
short n2 = boost::numeric_cast<short>(n1);
}
catch(boost::bad_numeric_cast&)
{
std::cout<<"The conversion failed"<<std::endl;
}
numeric_cast是如何知道這樣的數字轉換失敗的呢?numeric_cast合理的應用了std::numeric_limits<>,而std::numeric_limits<>就是內建數字類型的type_tratis。當然也可以將自己定義的數字抽象類別型添加到std::numeric_limits<>的特化版本中,這樣numeric_cast就可以作用於自訂的類型了。由於相對複雜點,本文是介紹其功能和用法,就不分析其源碼了,感興趣的朋友可以參看boost文檔和代碼。
對於numeric_cast的使用也是有些要求的。
- 源類型和目標類型必須都是可拷貝構造的
- 源類型和目標類型必須都是數字型類型。也就是被std::numeric_limits<>::is_specialized的特化定義為true
- 源類型必須能被static_cast轉換為目標類型
其實對我們用的系統內建的數字來說,這幾條都不是限制,只有我們在需要通過它轉換自訂的資料類型時,才需要注意,否則編譯不通過(其實這個錯誤還比較好發現和解決)。
在C/C++程式開發中,往往需要將數字型對象的值轉換為字元文字格式設定,或反之操作。雖然C語言就提供了不少系統函數來進行這種操作,如scanf、atoi等。這些函數小巧簡潔,使用很方便,但缺少擴充性。在std中引入了stringstream來以一個通用的方式實現各種轉換,但缺少對錯誤轉換的檢測。而boost::lexical_cast是在stringstream上的一個擴充,增加了對錯誤的類型轉換的檢測:
#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
int main()
{
try
{
int i = 100;
string str = boost::lexical_cast<string>(i);
cout<<"The string is:"<<str<<endl;
str = "error";
i = boost::lexical_cast<int>(str);
}
catch(boost::bad_lexical_cast& exobj)
{
cout<<"Convert err:"<<endl;
cout<<exobj.what()<<endl;
}
}
在上述轉換中,第二個轉換從"err"到int的轉換是失敗的,會拋出一個boost::bad_lexical_cast的異常,從而能協助我們構造更安全穩定的程式。
boost::lexical_cast內部實現其實也是一個stringstream的封裝,其函數簡化如下:
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)操作,用於判斷操作是否成功。
完
在c++中,我們經常需要把不同類型的數字互相轉換,如將一個數字在long和short之間轉換。但由於各數位精度不同,當一個數字從"大"類型到"小"類型就可能導致轉換失敗,如下所示:
long n1 = 99999999;
short n2 = static_cast<short>(n1);
對於如上轉換,n2得到的是一個負數,顯然這個不是我們所期望的,並且這種運行時的錯誤是很難檢測的,一旦使用了這個錯誤的轉換後的資料,後果不堪設想。
boost::numeric_cast可以協助我們解決這一問題,對於上面的轉換,boost::numeric_cast會拋出一個boost:: bad_numeric_cast這個異常對象。從而保證轉換後值的有效性。上述代碼可以改寫為如下:
try
{
long n1 = 99999999;
short n2 = boost::numeric_cast<short>(n1);
}
catch(boost::bad_numeric_cast&)
{
std::cout<<"The conversion failed"<<std::endl;
}
numeric_cast是如何知道這樣的數字轉換失敗的呢?numeric_cast合理的應用了std::numeric_limits<>,而std::numeric_limits<>就是內建數字類型的type_tratis。當然也可以將自己定義的數字抽象類別型添加到std::numeric_limits<>的特化版本中,這樣numeric_cast就可以作用於自訂的類型了。由於相對複雜點,本文是介紹其功能和用法,就不分析其源碼了,感興趣的朋友可以參看boost文檔和代碼。
對於numeric_cast的使用也是有些要求的。
- 源類型和目標類型必須都是可拷貝構造的
- 源類型和目標類型必須都是數字型類型。也就是被std::numeric_limits<>::is_specialized的特化定義為true
- 源類型必須能被static_cast轉換為目標類型
其實對我們用的系統內建的數字來說,這幾條都不是限制,只有我們在需要通過它轉換自訂的資料類型時,才需要注意,否則編譯不通過(其實這個錯誤還比較好發現和解決)。
在C/C++程式開發中,往往需要將數字型對象的值轉換為字元文字格式設定,或反之操作。雖然C語言就提供了不少系統函數來進行這種操作,如scanf、atoi等。這些函數小巧簡潔,使用很方便,但缺少擴充性。在std中引入了stringstream來以一個通用的方式實現各種轉換,但缺少對錯誤轉換的檢測。而boost::lexical_cast是在stringstream上的一個擴充,增加了對錯誤的類型轉換的檢測:
#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
int main()
{
try
{
int i = 100;
string str = boost::lexical_cast<string>(i);
cout<<"The string is:"<<str<<endl;
str = "error";
i = boost::lexical_cast<int>(str);
}
catch(boost::bad_lexical_cast& exobj)
{
cout<<"Convert err:"<<endl;
cout<<exobj.what()<<endl;
}
}
在上述轉換中,第二個轉換從"err"到int的轉換是失敗的,會拋出一個boost::bad_lexical_cast的異常,從而能協助我們構造更安全穩定的程式。
boost::lexical_cast內部實現其實也是一個stringstream的封裝,其函數簡化如下:
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)操作,用於判斷操作是否成功。