注: 转载请保证文章完整性 一、介绍 lexical_cast是boost中一个非常有用,常用,好用的库,我现在的小数据转换用的都是lexical_cast。 lexical_cast最大的特点是安全,包括长度安全,类型安全。 下面我来介绍下lexical_cast的基本使用方法。 Target lexical_cast(Source arg) 例如 #include <boost/lexical_cast.hpp> //lexical_cast的头文件 using namespace std; //stl的域 using namespace boost; //boost的域 int main() { const double PI=3.1415926535; string str; str=lexical_cast<string>(PI); cout<<str; return 0; } 非常容易吧,简单也是他的优势之一。 二、异常 lexical_cast在执行失败时会抛出异常bad_lexical_cast 上面的例子改为 #include <boost/lexical_cast.hpp> //lexical_cast的头文件 using namespace std; //stl的域 using namespace boost; //boost的域 int main() { try { string str="3.1415926535"; double PI=lexical_cast<double>(str); cout<<PI; return 0; } catch(bad_lexical_cast& E) { cout<<E.what()<<endl; } } 当str为ABCD时, 无法转成PI抛出异常 输出 bad lexical cast: source type value could not be interpreted as target 三、一个小例子 为了加深大加理解 下面使用lexical_cast实现一个简单的文本输入是否为指定类型的小程序 #include <boost/lexical_cast.hpp> #include <iostream> using namespace std; //stl的域 using namespace boost; //boost的域 template<typename _T,typename _R> bool isElement(_R r) { try { lexical_cast<_T>(r); return true; //转换成功 } catch(...) { return false; } } int main() { try { if(isElement<double>("3.14d159")) cout<<"YES"<<endl; else cout<<"NO"<<endl; } catch(bad_lexical_cast& E) { cout<<E.what()<<endl; } return 0; } 测试:isElement<double>("3.14d159") 输出:NO 测试:isElement<string>("3.14d159") 输出:YES 测试:isElement<long>("314159") 输出:YES 测试:isElement<long>("31.4159") 输出:NO 测试:isElement<char>("314159") 输出:NO 四、源码分析 : #ifdef BOOST_NO_STRINGSTREAM //我们知道stringstream和strstream分别是string和char*结构,lexical_cast考虑很全面的。 #include <strstream> #else #include <sstream> #endif // bad_lexical_cast是bad_cast的继承,所以很标准,支持和扩充性都很好。 class bad_lexical_cast : public std::bad_cast { public: bad_lexical_cast() : source(&typeid(void)), target(&typeid(void)) { } bad_lexical_cast( const std::type_info &s, const std::type_info &t) : source(&s), target(&t) { } //提供了两个返回type_info的函数,为我们跟踪调试类形转换起到很好 const std::type_info &source_type() const 的做用。 作者: 221.239.187.* 2006-1-2 15:09 回复此发言 2boost的lexical_cast { return *source; } const std::type_info &target_type() const { return *target; } virtual const char *what() const throw() { return "bad lexical cast: " "source type value could not be interpreted as target"; } virtual ~bad_lexical_cast() throw() { } private: const std::type_info *source; const std::type_info *target; }; type_info的具体用法是: E.source_type().name()就可能到类型名。 核心转换部分,用的是留的概念,从流内数据的剩余情况与流转换成功与否情况来判断操作是否成功。在不加域时这里就像一个黑盒子。 bool operator<<(const Source &input) { return !(stream << input).fail(); } template<typename InputStreamable> bool operator>>(InputStreamable &output) { return !is_pointer<InputStreamable>::value && stream >> output && (stream >> std::ws).eof(); } bool operator>>(std::string &output) { #if defined(BOOST_NO_STRINGSTREAM) stream << '\0'; #endif output = stream.str(); return true; } 仅提供该入口,具体实现被封在detail域里面。 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; } 最后 我们可以发现 bad_lexical_cast(typeid(Target), typeid(Source) 与上面 bad_lexical_cast(const std::type_info &s,const std::type_info &t) :source(&s), target(&t) 之间的区别,在我看来是写倒了,不过不影响,也算是个不算bug的bug 五、总结 lexical_cast是强大的,但不是万能的,但在很多情况下他有着独特的优点,安全方便快捷!!!