頭文件
boost/lexical_cast.hpplexical_castbad_lexical_cast標準c和c++庫提供了一些易用的實現來做這樣的轉換。但是,它們因其易使用程度而變化,另外因其安全性而差異。
舉個例子,對於在標準c家族中的函數,它們有一系列的限制。以atoi為代表:
標準C++庫為正要討論的內置格式轉換提供了stringstream。它對從格式化和I/O轉換以及任意類型和字符類型的轉換提供了強有力的控制。但是,使用stringstream進行直接的轉換會是拙劣的(含有對額外的本地變量的說明和缺少中綴表達式便利性)或者晦澀的(stringstream對像在表達式中以臨時對象的形式被創建)。facet為控制文本表達提供了更充分的概念和靈活性,但是它們的高度複雜性和高起點需要(對stringstream)相當高程度的熟悉度---即使是為了簡單的轉換,從而把大多數程序員排除在外了。
Lexical_cast函數模版為以文本表示的任意的類型之間的轉換提供了方便和一致的形式。它提供的簡化形式是在表達式級別上的簡單性易用性。對於更多相關的轉換,比如比lexical_cast提供的默認行為更為精確的或者需要更嚴密的格式轉換控制,這時推薦傳統的stringstream。當在numeric和numeric之間轉換的時候,numeric_cast 可能提供了比lexical_cast更好的行為。
關於基於字符串格式化的相關選項和問題的更多討論,包括 stringstream,
lexical_cast, 和其它的對照,請見 Herb Sutter 的論文, The String Formatters of
Manor Farm.
下面的例子使用字符串表達式來表示數字:int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector<short> args;
while(*++argv)
{
try
{
args.push_back(lexical_cast<short>(*argv));
}
catch(bad_lexical_cast &)
{
args.push_back(0);
}
}
...
}
void log_message(const std::string &);
void log_errno(int yoko)
{
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
}
"boost/lexical_cast.hpp":
單元測試定義在namespace boost
{
class bad_lexical_cast;
template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
}
"lexical_cast_test.cpp".
lexical_cast將 arg 輸入到一個標準庫的基於字符串的流,返回其結果並以template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
Target 對像輸出。其中 Target 要麼是 std::string 要麼是 std::wstring, 對整個字符串的內容進行流提取,包括空格,而非依賴於默認的
operator>> 行為。如果轉換不成功,則拋出一個
bad_lexical_cast 異常。
對於參數和返回類型的要求有:
operator<<被定義了---在左邊有一個 std::ostream 或者 std::wostream 對象並且在右邊有一個參數類型的實例。
operator>>被定義了---在左邊有一個 std::ostream 或者 std::wostream 對象並且在右邊有一個返回結果類型的實例。
.
當轉換需要更高級的控制時,std::stringstream和std::wstringstream提供了更合適的途徑。當需要非基於流的轉換時,lexical_cast不是完成這項工作的合適工具,它不用在這類特殊的類型轉換之列。
bad_lexical_cast用來表示class bad_lexical_cast : public std::bad_cast
{
public:
... // 與 std::exception 相同的成員函數接口
};
lexical_cast 運行時出錯的異常。
請使用其它整數類型,如 int 或 short int. 如果邊界檢查是重要的,你也可以調用 numeric_cast:
numeric_cast<int8_t>(lexical_cast<int>("127"));
Q: 為什麼一個 int8_t 或 uint8_t 的 lexical_cast<std::string> 不是像我想要那樣?
A: 如上,注意 int8_t 和 uint8_t 其實就是 chars 且被按此格式化。為避免這樣,應首先轉型為一個整數類型:
lexical_cast<std::string>(static_cast<int>(n));
Q: 該實現總是重置底層流對象的 ios_base::skipws 標誌。它破壞了要使用這個標誌的 operator>>. 你是否可以去掉重置該標誌的代碼?
A: 以後的版本有可能這樣做。在 [N1973] 中並不要求重置該標誌,但請記住,[N1973] 尚未被委員會所接受。順便說一句,這是一個讓你的 operator>> 符合標準的好機會。請閱讀一本好的C++書,學習一下 std::sentry 和 ios_state_saver.
Source 和 Target
類型提供更好的性能。詳情請參見 [Tuning].
std::numeric_limits保持一致,當前的版本選擇一個精度來匹配。 std::wstring:。lexical_cast<std::string>("Hello,
World")成功返回取代了拋出一個bad_lexical_cast異常。bad_lexical_cast異常:lexical_cast<char *>("Goodbye,
World")現在會拋出一個異常來取代導致未定義的的行為。