boost庫的介紹

pamxy發表於2013-06-04

轉自:http://wenku.baidu.com/view/0df274d028ea81c758f57879.html


Boost是什麼?一套開放原始碼、高度可移植的C++庫。

誰發起的?C++標準委員會庫工作組。所以,質量保證,不怕遇到假冒偽劣產品。


Boost內容廣泛,數值計算、泛型程式設計、超程式設計、平臺API……不妨從容選擇自己感興趣的部分,細細品味。


有些什麼呢?瞧瞧:


字串及文字處理

Boost.Regex
正規表示式是解決大量模式匹配問題的基礎。它們常用於處理大的字串,子串模糊查詢,按某種格式tokenize字串,或者是基於某種規則修改字串。由於C++沒有提供正規表示式支援,使得有些使用者被迫轉向其它支援正規表示式的語言,如Perl, awk, 和 sed。Regex提供了高效和強大的正規表示式支援,基於與STL同樣的前提而設計,這使得它很容易使用。Regex已被即將釋出的Library Technical Report接受。更多的資訊,請見"Library 5: Regex.".

Boost.Spirit
Spirit庫是一個多用途的、遞迴的語法分析器生成框架。有了它,你可以建立命令列分析器,甚至是語言前處理器[1]。它允許程式設計師直接在C++程式碼裡使用(近似於)EBNF的語法來指定語法規則。分析器非常難寫,對於一個特定的問題,它們很快就變得難於維護和看懂。而Spirit解決了這些問題,而且達到了與手工製作的分析器一樣或幾乎一樣的效能。


Boost.String_algo
這是一組與字串相關的演算法。包括很多有用的演算法,用於大小寫轉換,空格清除,字串分割,查詢及替換,等等。這組演算法是目前C++標準庫裡已有功能的擴充套件。

Boost.Tokenizer
這個庫提供了把字元序列分割成記號(token)的方法。通用的語法分析任務包括了在已分割的文字流裡查詢資料。如果可以把字元序列視為多個元素的容器將很有幫助,容器中的元素被執照使用者定義的規則所分割。語法分析就成為了在這些元素上進行操作的單個任務,Tokenizer正好提供了這種功能。使用者可以決定字元序列如何被分割,在使用者請求新的元素時,庫將找出相應的記號。


資料結構, 容器, 迭代器, 和演算法
Boost.Any
Any
庫支援型別安全地儲存和獲取任意型別的值。當你需要一個可變的型別時,有三種可能的解決方案:

無限制的型別,如 void*. 這種方法不可能是型別安全的,應該象逃避災難一樣避免它。

可變的型別,即支援多種型別的儲存和獲取的型別。

支援轉換的型別,如字串型別與整數型別之間的轉換。

Any實現了第二種方案,一個基於值的可變化的型別,無限可能的型別。這個庫通常用於把不同型別的東西儲存到標準庫的容器中。更多的說明請見 "Library 6: Any."



Boost.Array
這個庫包裝了普通的C風格陣列,給它們增加了一些來自於標準庫容器的函式和typedef 。其結果就是可以把普通的陣列視為標準庫的容器。這非常有用,因為它增加了型別安全性而沒有降低效率,而且它使得標準庫容器和普通陣列擁有統一的語法。後一點意味著可以把普通陣列用於大多數的要求容器類來操作的函式。當要求軟體要達到普通陣列的效能時,可以用Array來替代
std::vector.

Array 的作者是 Nicolai Josuttis, 它在Matt Austern 和 Bjarne Stroustrup早期提出的思想之上建立了這個庫。


Boost.Compressed_pair
這個庫包括一個引數化的型別, compressed_pair, 它非常象標準庫中的 std::pair. 與std::pair不同之處在於, boost::compressed_pair 對模板引數進行評估,看其中有沒有空的引數,如果有,使用空類優化技術來壓縮pair的大小。
Boost.Compressed_pair 常用於存放一對物件,其中之一或兩個都可能是空的。


Boost.Dynamic_bitset
Dynamic_bitset
庫非常象std::bitset, 除了std::bitset 是用引數來指定位數(即容器的大小), 而boost::dynamic_bitset 則支援在執行期指定大小。dynamic_bitset 支援與std::bitset一樣的介面,還增加了支援執行期特定功能的函式和一些std::bitset中沒有的功能。在bitset的大小無法在編譯期確定或在程式執行時可能變化的情況下,這個庫通常用於替換std::bitset。

Boost.Graph
Graph
是一個處理圖結構的庫,它的設計受到STL的重要影響。它是泛型的,高度可配置,並且包括多個不同的資料結構:鄰接連結串列, 鄰接矩陣, 和邊列表。Graph還提供了大量的圖演算法,如Dijsktra最短路徑演算法,Kruskal最小生成樹演算法,拓樸邏輯排序,等等。


Boost.Iterator
這個庫提供一個建立新的迭代器型別的框架,還提供了許多有用的迭代器介面卡,比C++標準中定義的更多。建立遵循標準的新迭代器型別是一件困難且乏味的工作。Iterator通過自動完成大多數細節,如提供所需的 typedef,簡化了這件工作。Iterator還可以改編已有的迭代器型別以賦於它新的行為。例如,間接迭代器介面卡增加了一個額外的解引用操作,可以把一個包含某種物件的指標(或智慧指標)的容器變成象一個包含該物件的容器。


Boost.MultiArray
MultiArray
提供了一個多維容器,它很象標準庫的容器,但比向量的向量更有效、更高效,更直接。容器的維數在宣告時指定,但它支援限制(slicing)和映身(projecting)不同的檢視(view),也可以在執行期改變維數。


Boost.Multi-index
Multi-index
為底層的容器提供多個索引。這意味著一個底層的容器可以有不同的排序方法和不同的訪問語義。當std::set 和 std::map不夠用時,就可以用Boost.Multi-index,通常是在需要為查詢元素而維護多個索引時。

Multi-index 的作者是 Joaquín M López Muñoz.

Boost.Range
這個庫是一組關於範圍的概念和工具。比起在演算法中使用一對迭代器來指定範圍,使用ranges更簡單,並提升了使用者程式碼的抽象水平。


Boost.Tuple
在標準C++中有Pairs(類别範本 std::pair), 但它不支援n-tuples。用Tuple.不象用structs 或 classes 來定義n-tuples, 這個類别範本支援直接宣告和使用,如函式返回型別或引數,並提供一個泛型的方法來訪問tuple的元素。關於這個庫的詳細資訊,請見"Library 8: Tuple 8"。Tuple已經被即將釋出的Library Technical Report所接受。


Boost.Variant
Variant
庫包含一個不同於union的泛型類,用於在儲存和操作來自於不同型別的物件。這個庫的一個特點是支援型別安全的訪問,減少了不同資料型別的型別轉換程式碼的共同問題。


函式物件及高階程式設計
Boost.Bind
Bind
是對標準庫的繫結器bind1st 和 bind2nd的泛化。這個庫支援使用統一的語法將引數繫結到任何類似於函式行為的東西,如函式指標、函式物件,以及成員函式指標。它還可以通過巢狀繫結器實現函式組合。這個庫不要求那些對標準庫繫結器的強制約束,最顯著的就是不要求你的類提供typedefs result_type, first_argument_type, 和 second_argument_type 等。這個庫也使得我們不再需要用 ptr_fun, mem_fun, 和 mem_fun_ref 等介面卡。Bind庫的說明在"Library 9: Bind 9."。它是對C++標準庫的一個重要且很有用的擴充。Bind可以被標準庫的演算法使用,也經常用於Boost的函式,它提供了一個強大的工具,用於存放後續呼叫的函式和函式物件。Bind 已被即將釋出的Library Technical Report所接受。


Boost.Function
Function
庫實現了一個泛型的回撥機制。它提供了函式指標、函式物件和成員函式指標的儲存和後續的呼叫。當然,它與binder庫,如Boost.Bind 和 Boost.Lambda一起工作,大大提高了回撥(包括帶態度的回撥函式)的使用機會。這個庫的詳細介紹請見"Library 11: Function 11."。Function常用於需要把函式指標用於回撥的地方。例如:訊號/接收者的實現,GUI與業務邏輯的分離,以及在標準庫容器中儲存不同的類函式型別。Function已被即將釋出的Library Technical Report所接受。



Boost.Functional
Functional
庫提供C++標準庫的介面卡的加強版。主要的優勢是它有助於解決引用到引用(這是非法的)的問題,這個問題是由對帶有一個或多個引用引數的函式使用標準庫的繫結器所引起的。Functional同時消除了在標準庫演算法中使用函式指標時必須用ptr_fun的問題。



Boost.Lambda
Lambda
為C++提供lambda表示式及無名函式。在使用標準庫演算法時特別好用,Lambda允許函式在呼叫點建立,避免了建立多個小的函式物件。使用lambdas意味著更少的程式碼,在哪需要就在哪寫,這比分散在程式碼各處的函式物件更清晰、更好維護。"Library 10: Lambda 10" 詳細討論了這個庫。


Boost.Ref
許多函式模板,包括大量標準C++庫裡的函式模板,它們的引數採用傳值的方式傳遞,有時候會有問題。複製一個物件可能很昂貴或者甚至不可能,或者狀態可能取決於特寫的例項,因此這時複製是不希望的。在這些情況下,可用的辦法是用引用傳遞取代值傳遞。 Ref包裝了一個物件的引用,並把它放入一個物件以便被複制。這就允許了通過引用去呼叫那些採用傳值引數的函式。Ref 已被即將釋出的Library Technical Report所接受。

Ref 的作者是 Jaakko Järvi, Peter Dimov, Douglas Gregor, 和 David Abrahams.

Boost.Signals
訊號和接收系統,基於稱為publisher-subscriber 和 observer的模式,它是在一個最小相關性系統中管理事件的重要工具。很少有大型應用軟體不採用這種強大設計模式的某種變形,儘管他們有各自的實現方式。Signals提供了一個已驗證的、高效的手段,將訊號(events/subjects)的發生和這些訊號要通知的接收者(subscribers/observers)進行了分離。



泛型程式設計與模板超程式設計
Boost.Call_traits
這個庫提供了傳遞引數給函式的最好方法的自動演繹,依據引數的型別。例如,當傳遞的是如int 和 double這樣的內建型別,最高效的方式是傳值。對於使用者自定義型別,則傳送const引用通常更好。Call_traits為你自動選擇正確的引數型別。這個庫還有助於宣告引數為引用,而不用冒引用到引用的風險(在C++這是非法的)。Call_traits常用於要求以最高效方式傳遞引數而又不知道引數型別的泛型函式,並避免引用到引用的問題。

Call_traits 的作者是 Steve Cleary, Beman Dawes, Howard Hinnant, 和 John Maddock.

Boost.Concept_check
Concept_check提供一些類别範本,用於測試特定的概念(需求的集合)。泛型(引數化的)程式碼要求例項化時的型別必須符合某些抽象概念,如LessThanComparable. 這個庫提供了一些方法來明確地宣告模板的引數化型別的特定需求。程式碼的使用者可以獲益,由於需求的文件化以及編譯器可以產生錯誤資訊以明確指出型別不符合這些概念的地方。Boost.Concept_check提供了超過30個可用於泛型程式碼的概念,其中一些原型可用於校驗包括所有相關概念的元件的實現。它用於在泛型程式碼中宣告和證明概念的需求。


Concept_check 的作者是 Jeremy Siek, 他從Alexander Stepanov and Matt Austern的前期工作中得到靈感。

Boost.Enable_if
Enable_if
允許函式模板或類别範本的特化體包括/排除在一組匹配的函式或特化體之中/之外。主要的用例是包括/排除基於某些特性的特化體。例如,僅當採用一個整數型別例項化時使能一個函式模板。這個庫還為SFINAE(substitution failure is not an error)提供了一個非常有用的研究機會。

Enable_if 的作者是 Jaakko Järvi, Jeremiah Willcock, 和 Andrew Lumsdaine.

Boost.In_place_factory
In_place_factory庫是一個直接構造所含物件的框架,包括用於初始化的可變引數列表。它可以消除對所含型別必須是CopyConstructible的要求,並減少了建立不必要的臨時物件的需要,該臨時物件僅用於提供複製所需的源物件。這個庫有助於減少傳送用於物件初始化的引數所需的工作量。


In_place_factory 的作者是 Fernando Cacciola.

Boost.Mpl
Mpl是一個模板超程式設計庫。它包含了與C++標準庫十分相象的資料結構和演算法,但它們是在編譯期使用的。甚至有編譯期的lambda表示式支援!提供編譯期的操作,如產生型別或操作型別序列,在現代C++中越來越普遍,而提供這些功能的庫是非常重要的工具。就我所知,還沒有其它象Mpl這樣的庫。它填充了C++超程式設計世界的空白。我可以告訴你在你讀本書時有一本關於Boost.Mpl的書正在創作,它就快要面世了,它就是Aleksey Gurtovoy 和 David Abrahams所著的C++ Template Metaprogramming。你應該儘快獲得一本。


Mpl 的作者是 Aleksey Gurtovoy, 並有許多其它人的重要貢獻。

Boost.Property_map
Property_map
是一個概念庫而不是一個真正的實現。它引入了 property_map 概念以及property_map型別的一組要求,從而給出了對一個key和一個value的對映的語法和語義要求。這在需要宣告必須支援的型別的泛型程式碼中很有用。C++陣列是一個property_map的例子。這個庫包含了Boost.Concept_check可以測試的概念的定義。


Boost.Static_assert
進行編譯期程式設計的一個公共的需求是提供靜態斷言,即編譯期斷言。另外,獲得一致的錯誤提示不是必然的,由於靜態斷言必須會產生失敗斷言的訊號,跨不同的編譯器。Static_assert提供對名字空間、類、函式作用域的靜態斷言的支援。詳細資訊見"Library 3: Utility."


Boost.Type_traits
成功的泛型程式設計通常需要根據引數化型別進行決策或調整這些型別的屬性(如cv-qualification[2])。Type_traits提供關於型別的編譯期資訊,如某個型別是否指標或引用,以及增加或去除型別基本屬性。Type_traits已被加入即將釋出的Library Technical Report。


[2] 一個型別可以是cv-unqualified (非 const 或 volatile), const-qualified (const), volatile-qualified (宣告為 volatile), or volatile-const-qualified (既 const 並 volatile); 型別的這些版本都是獨特的。

Type_traits 的作者是 Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat Marcus, John Maddock, 和 Jeremy Siek, 以及其它許多人的貢獻。

數學及數字處理
Boost.Integer
這個庫提供了對整數型別的有用功能,如編譯期的最小、最大值常數[3],基於給定位長的合適大小的型別,靜態二進位制對數計算等等。還包括從1999年C標準標頭檔案<stdint.h>中的typedef。

int32 int64

[3] std::numeric_limits 僅能以函式方式提供這些值。


Integer 的作者是 Beman Dawes 和 Daryle Walker.

Boost.Interval
Interval庫幫助你使用數學區間。它提供類别範本interval及相關運算元。區間的常見用法(除了明顯的進行區間計算的情況)是提供模糊結果的計算;區間的使用可以量化舍入誤差的傳播情況。


Interval 的作者是 Guillaume Melquiond, Sylvain Pion, 和 Hervé Brönniman, 該庫從 Jens Maurer的前期工作獲得靈感。

Boost.Math
Math
是一組數學模板:quaternions 和 octonions (複數的特化);數學函式如acosh, asinh, 和 sinhc;計算最大公約數(GCD)和最小公倍數(LCM)的函式等等。

Boost.Minmax
Minmax
可以同時計算最小和最大值,而使用std::min 和 std::max則要兩次比較。對於n個元素的情況,只要3n/2+1次比較,而使用std::min_element 和 std::max_element則需要2n次比較。

Boost.Numeric Conversion
Numeric Conversion
庫是一組用於在不同數字型別的值之間進行安全及可預言的轉換的工具。例如,有一個名為numeric_cast (最早來自於Boost.Conversion)的工具,提供了範圍檢測的轉換以確定數值可被目標型別所表示,否則它會丟擲異常。

Numeric Conversion 的作者是 Fernando Cacciola.

Boost.Operators
Operators庫提供了相關操作符及概念(LessThanComparable, Arithmetic,等等)的實現。定義一個型別的操作符時,保證所有操作符都有定義是一件乏味並容易出錯的工作。例如,你提供了operator< (LessThanComparable),通常都要同時提供operator<=, operator>, 和 operator>= 。Operators可以根據給定型別的最小的使用者自定義操作符集合,自動宣告並定義其它所有的相關操作符。詳細討論見
"Library 4: Operators 4."


Boost.Random
這是一個對隨機數的專業使用的庫,包括大量的生成器和分配器,可適用於多個不同的領域,如模擬和加密。Random已被收入即將釋出的Library Technical Report.可以實現真隨機數



Boost.Rational
整數型別和浮點數型別都內建成於C++語言,複數型別也是C++標準庫的一部分,但有理數型別呢?有理數可以避免浮點數的精度損失問題,因此它們常被用於計算金錢等。Rational提供的有理數型別可以基於任意整數型別,包括使用者自定義的整數型別(具有無限精度的型別顯然是很有用的).


Boost.uBLAS
uBLAS庫使用數學符號提供對向量和矩陣的基本線性代數操作,採用操作符過載,它可以生成緊湊的程式碼(使用表示式模板)。


uBLAS 的作者是 Joerg Walter 和 Mathias Koch.

輸入/輸出

Boost.Assign
Assign
幫助你把一系列的值賦給容器。它通過對operator, (逗號操作符) and operator()() (函式呼叫操作符)的過載,帶給使用者一種資料賦值的很容易的方法。除了對原型風格的程式碼特別有用,這個庫的功能在其它時候也很有用,使用這個庫有助於提高程式碼的可讀性。使用本庫中的list_of還可以就地生成無名陣列。


Boost.Filesystem
Filesystem
庫提供對路徑、目錄和檔案操作的可移植性。這種高階抽象使C++程式設計師可以寫出類似於其它程式語言指令碼的程式碼。它提供了便於操作目錄和檔案的演算法。編寫要在不同檔案系統平臺間移植程式碼的困難工作由於這個庫的幫助變得容易了。

Boost.Format
這個library加入了按格式化串進行格式化的功能,類似於printf, 但增加了型別安全性。相反使用具有相同便利性的printf的最主要問題是引數型別的危險;它不保證格式化串中指定的型別與實際的引數型別是匹配的。除了消除了這種不匹配性的危險以外,Format還可以用於格式化使用者自定義的型別。[4]

[4] 格式化函式用省略號表示可變數量的引數是不可以的。


Format 的作者是 Samuel Krempp.

Boost.Io_state_savers
Io_state_savers庫允許儲存IOStream物件的狀態,用於以後的恢復,以取消可能發生的任何狀態的變化。許多操縱器會永久改變它們操作的流的狀態,這可能是你不想要的,而手工重置狀態又容易出錯。這個狀態儲存器可以儲存控制標誌、精度、寬度、異常掩碼、流的locale等等。


Io_state_savers 的作者是 Daryle Walker.

Boost.Serialization  序列化

這個庫允許任意的C++資料結構存進來,再取出去,以及存檔。例如,存檔可以是文字或XML檔案或者二進位制格式。Boost.Serialization是高度可移植的,並提供了非常成熟的特性,如類的版本、C++標準庫中的通用類的序列化、共享資料的序列化,等等。



雜項
Boost.Conversion
Conversion
庫包含有一些函式,它們是現有的強制型別轉換操作符(static_cast, const_cast, 和 dynamic_cast)的增強。Conversion為安全的多型轉換增加了 polymorphic_cast 和 polymorphic_downcast,為安全的數字型別轉換增加了 numeric_cast,為文字轉換(如string 和 double間的轉換)增加 lexical_cast。你可為了你自己的型別更好地工作而定製這些型別轉換,可能這些型別並不可以使用語言本身所提供的型別轉換。這個庫的詳細討論在"Library 2: Conversion."


Boost.Crc
Crc庫提供了迴圈冗餘碼(CRC)的計算,常有於校驗和型別。CRC被加到一個資料流中(它就是從這些資料中計算得來的),用來對這些資料進行校驗,例如PKZip就使用了CRC32。這個庫包含了四個CRC型別:crc_16_type, crc_ccitt_type, crc_xmodem_type, 和
crc_32_type5.


Boost.Date_time
Date_time庫提供了對日期和時間型別及對它們的操作的廣泛支援。如果沒有對日期和時間的支援,程式開發任務會變得複雜並容易出錯。使用Date_time,你想要的所有自然概念都被支援:日、周、月、持續時間(及時間間隔)、加、減等等。這個庫還提供了其它日期/時間庫所忽略的東西,如閏秒處理以及高精度時間源的支援。這個庫的設計是可擴充套件的,允許客戶化定製行為或新增功能。



Boost.Optional
要求函式可以指出它的返回值無效是一個很普通的要求,但通常返回型別並不存在某個狀態來表示其無效。Optional提供了類别範本optional, 它是一個在語義上有額外狀態的型別,它可以有效地表明optional的例項是否包含被封裝物件例項。

Optional 的作者是 Fernando Cacciola.

Boost.Pool
Pool庫提供了一個記憶體池分配器,它是一個工具,用於管理在一個獨立的、大的分配空間裡的動態記憶體。當你需要分配和回收許多不的物件或需要更高效的記憶體控制時,使用記憶體池是一個好的解決方案。




Boost.Preprocessor
當你要表示象迴圈這樣的結構時,很難使用前處理器,它沒有容器,不提供迭代器,等等。然而前處理器仍是一個強大的可移植的工具。Preprocessor庫提供了在前處理器之上的抽象。它包括lists, tuples, 和 arrays, 還有操作這些型別的algorithms。這個庫有助於減少重複的程式碼,減輕你的負擔,也使得程式碼更易讀、更清晰、更具可維護性。


Boost.Program_options
Program_options
庫提供了程式選項配置(名字/值對), 程式選項通常是通過命令列引數或配置檔案提供。這個庫減輕了程式設計師手工分析這些資料的負擔。
<unistd.h>>getopt  getoptlong
很容易實現 unix風格的程式  ./a.out  -a -n3 --prefix

 



Boost.Python
Python
庫提供了C++與Python[6]的互操作性。它用於將C++類及函式提供給Python,同樣把Python物件給C++。它是非插入式的,也就是說已有程式碼無需修改即可用於Python。


Boost.Smart_ptr
智慧指標是任何一個程式設計師工具包中的重要部分。它們用於防止資源洩漏、共享資源、物件生存期管理。有很多好的智慧指標庫可用,有些是免費的,而有些是商業軟體包的組成部分。Smart_ptr是其中的佼佼者,已被成千上萬的使用者所證實,並被該領域的專家所推薦。 Smart_ptr包括了非插入的智慧指標用於限制範圍(scoped_ptr 和 scoped_array),用於共享資源(shared_ptr 和 shared_array), 一個配合shared_ptr使用的智慧指標(weak_ptr), 還有一個插入式的智慧指標類(intrusive_ptr). Smart_ptr的shared_ptr (包括它的助手enable_shared_from_this) 以及 weak_ptr 已被收入即將釋出的Library Technical Report。關於智慧指標更詳細的說明請見"Library 1: Smart_ptr 1."

Smart_ptr 的作者是 Greg Colvin, Beman Dawes, Peter Dimov, 和
Darin Adler.

Boost.Test
Test庫提供了一整組用於編寫測試程式的元件,可以把測試組織成簡單的測試用例及測試套裝,並控制它們的執行。作為這個庫的一個元件,程式執行監視器在某些生產(非測試)環境下也很有用。

google test framework


Boost.Thread
可移植的執行緒是很難處理的業務,也無法從C++本身獲取幫助,因為語言本身不包括執行緒支援。當然,我們有POSIX, 它在許多平臺上可用,但POSIX使用的是C API。Thread是一個提供可移植執行緒的庫,它包含大量執行緒的原始概念和高度抽象。


Boost.Timer
Timer
庫包含計時所需的特性,它的目標是儘可能做到跨平臺的一致性。雖然每個平臺都有特定的 API可以讓程式設計師用於計時,但對於高精度計時還沒有可移植的方案。Boost.Timer通過提供最大可能的精度並同時保留可移植性解決了這個問題,從而可以讓你自由地確定精度。


Boost.Tribool
這個庫包含一個 tribool 庫,它實現了三狀態布林邏輯。三狀態布林型別除了true 和 false以外還有一個額外的狀態:indeterminate (這個狀態也被稱為maybe; 這個名字是可配置的).

Tribool 的作者是
Douglas Gregor.

Boost.Utility
一些本不應在一個庫裡出現的有用的東西,只是因為它們每個都不太複雜和廣泛,不足夠形成一個單獨的庫。但不是說它們沒有什麼用外;事實上小的工具通常都有最廣泛的用處。在Boost, 這些小工具被集中起來,形成一個稱為Utility的庫。你可以在這找到checked_delete, 一個函式,用於確認在刪除點的型別是完整的;還有類noncopyable,用於確保類不能被複制;還有enable_if,用於對函式過載的完全控制。還有其它很多工具,詳細請見"Library 3: Utility"。



Boost.Value_initialized
Value_initialized
庫幫助你用泛型的方法構造和初始化物件。在C++裡,一個新構造的物件可以是零初始化的、預設構造的,或是不確定的,這依賴於物件的型別。有了Boost.Value_initialized, 這種不一致的問題就沒有了。

Value_initialized 的作者是 Fernando Cacciola.

  • 正規表示式,可以與POSIX APIPerl語言處理正規表示式的功能相媲美,而且還能支援各種字元型別(如charwchar_t,甚至還可以是自定義字元型別);
  • 多執行緒,想了很久的跨平臺多執行緒庫了;
  • 資料結構,再加上即將加入標準的hash_sethash_maphash_multisethash_multimap等等(事實上不少STL實作,如SGI STL,已經支援以上資料結構),C++對資料結構的支援已近完備;
  • python,沒錯,對Python語言的支援;
  • 智慧指標,與std::auto_ptr一起善加使用,可杜絕記憶體洩露,效率更不可和垃圾收集機制GC同日而語;
  • 更有迴圈冗餘的CRC、可輕鬆定義返回多個值函式的元組tuple、可容納不同型別值的any、對標準庫各方面的補充……
  • 還在迅速擴大中,部分內容有望進入C++標準庫……

2 Boost下載和Boost安裝


去哪下載Boost呢?英文http://www.boost.org (1),中文http://boost.c-view.org,可以找到一個.zip或.tar.gz格式的壓縮包。下載完畢後,解壓到某個目錄,比如boost_1_26_0,裡面一般有這麼幾個子目錄:boost、libs、more、people、status、tools,看看沒問題就行了。

如果Boost更新時您懶得去下載整個壓縮包,只希望更新發生變動的檔案;或者您是一位跟我一樣的Boost Fans,希望跟蹤Boost的最新變化,不妨使用CVS方式。首先得有一個CVS客戶端軟體,比如CvsGuihttp://sourceforge.net/projects/cvsgui/提供的WinCVS、gCVS和MacCVS,分別適用於Windows、Linux和MacOS平臺。下載、安裝、啟動三步曲。

如果您習慣於傳統CVS的命令列模式,那麼可在Admin→Command Line...→Command line settings中輸入下面一行2

cvs -z3 -d:pserver:anonymous@cvs.boost.sourceforge.net:/cvsroot/boost checkout boost
 

勾上下面的核取方塊,選擇本地目標目錄(比如可以新建一個C:\Boost,這憑個人愛好),再點選確定即可開始更新。如果是第一次執行,則可能需要一段時間下載所有檔案。當然以後更新就只需要很短的時間了。

如果您偏好GUI模式,請選擇Admin→Preferences...,在General的Enter CVS ROOT中填寫:

anonymous@cvs.boost.sourceforge.net:/cvsroot/boost
 

Authentication 選擇"passwd" file on the cvs server,同時Use version選擇cvs 1.10 (standard)。然後在WinCvs的HOME folder中填寫或選擇一個本地目標目錄,點選確定。選擇View→Browse Location→Change...換到本地目標目錄後,在Create→Check Module...→Checkout Settings的Enter the module name and path on the server中填寫boost,單擊確定即可。如果這一過程中要求輸入密碼,不必理會,直接回車就行。這是WinCVS 1.2的情況。如果您下載的是新的版本,請注意各項設定大同小異,如前面的Authentication選擇pserver、不需要設定Use version等。

然後設定編譯器。以Windows常用整合環境為例。Microsoft Visual C++ 6.0,可在工具→選擇→目錄處把Boost的路徑(如前面的boost_1_26_0)新增到Include Files搜尋路徑中。而對於Borland C++ Builder 5.0,則是在Project→Options→Directories/Conditionals→Include Path中新增Boost的路徑。還有一種比較常用的Dev-C++ 4.0(內建GNU C++,可從http://www.bloodshed.net處免費下載),可在Options→Compile Options→Directories→C++ include files處新增Boost的路徑即可。其他IDE類似。至於命令列方式,則需在編譯時對相應的標頭檔案路徑引數(Borland C++ Compiler、GNU C++是-I,VC++的cl是/I)給出Boost路徑。

做到這一步,恭喜您,大部分Boost庫就可以用了。

為什麼不是全部?首先,目前還沒有一個能完全符合C++標準的編譯器,所以Boost庫中的元件或多或少不可用,詳細資訊請看Boost網站上“編譯器支援情況(Compiler Status)”一文。另外,有些庫需要Build相應的lib或dll檔案。不過這樣的庫很少,主要是由於平臺相關性的原因,如處理正規表示式的 regex庫、支援python語言的python庫等,而建構庫的過程相當煩瑣,需要使用Jam工具(可以簡單提一下:在 tools/build/jam_src/builds目錄下有三個檔案win32-borlandc.mk、win32-gcc.mk、win32- visualc.mk,分別是適用於Windows平臺下的Borland C++ Compiler、GNU C++和Visual C++的mak檔案。如果在Unix平臺,則應使用tools/build/Makefile。用命令列工具make或nmake來做出Jam執行檔案,然後再用Jam來建構庫,詳細內容可見Boost.Build文件)。我個人的建議是,不用急著去建構lib或dll。真的需要使用這些庫時,再make 隨庫提供的mak檔案即可。雖然Boost.Jam也許是Boost庫未來發展的方向,不過畢竟絕大部分庫都無須建構,可以直接使用。

3 Boost元件lexical_cast


這次我們先挑個簡單實用的Boost元件,看看Boost能給我們帶來怎樣的便利。

3.1 字串→數值

在CSDN論壇上經常看到詢問如何在字串型別和數值型別間進行轉換的問題,也看到了許多不同的答案。下面先討論一下從字串型別到數值型別的轉換。

  1. 如何將字串"123"轉換為int型別整數123?答案是,用標準C的庫函式atoi
  2. 如果要轉換為long型別呢?標準C的庫函式atol
  3. 如何將"123.12"轉換為double型別呢?標準C的庫函式atod
  4. 如果要轉換為long double型別呢?標準C的庫函式atold
  5. ……

後來有朋友開始使用標準庫中的string類,問這個如何轉換為數值?有朋友答曰,請先轉換為const char*。我很佩服作答者有數學家的思維:把陌生的問題轉化成熟悉的問題。(曾經有一則笑話,好事者問數學家:知道如何燒水嗎?答:知道。把水壺加滿水,點火燒。又問:如果水壺裡已經有水了呢?答:先倒掉,就轉化為我熟悉的問題了……)

不,不,這樣是C的做法,不是C++。那麼,C++該怎麼做呢?使用Boost Conversion Library所提供的函式lexical_cast(需要引入標頭檔案boost/lexical_cast.hpp)無疑是最簡單方便的。如:

#include <boost/lexical_cast.hpp>
#include <iostream>
int main()
{
        using boost::lexical_cast;
        int a = lexical_cast<int>("123");
        double b = lexical_cast<double>("123.12");
        std::cout<<a<<std::endl
        std::cout<<b<<std::endl;
        return 0;
}
 

一個函式就簡潔地解決了所有的問題。

3.2 數值→字串

那麼從數值型別到字串型別呢?

用itoa?不對吧,標準C/C++里根本沒有這個函式。即使在Windows平臺下某些編譯器提供了該函式3,沒有任何移植性不說,還只能解決int型別(也許其他函式還可以解決long、unsigned long等型別),浮點型別又怎麼辦?當然,辦法還是有,那就是:sprintf。

char s[100];
sprintf(s, "%f", 123.123456);
 

不知道諸位對C裡的scanf/printf系列印象如何,總之阿炯我肯定記不住那些稀奇古怪的引數,而且如果寫錯了引數,就會得到莫名其妙的輸出結果,除錯起來可就要命了(我更討厭的是字元陣列,空間開100呢,又怕太小裝不下;開100000呢,總覺得太浪費,心裡憋氣,好在C++標準為我們提供了string這樣的字串類)。這時候,lexical_cast就出來幫忙啦。

#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
int main()
{
        using std::string;
        const double d = 123.12;
        string s = boost::lexical_cast<string>(d);
        std::cout<<s<<std::endl;
        return 0;
}
 

跟前面一樣簡單。

3.3 異常

如果轉換失敗,則會有異常bad_lexical_cast丟擲。該異常類是標準異常類bad_cast的子類。

#include <boost/lexical_cast.hpp>
#include <iostream>
int main()
{
        using std::cout;
        using std::endl;
        int i;
        try{
                i = boost::lexical_cast<int>("abcd");
        }
        catch(boost::bad_lexical_cast& e)
        {
                cout<<e.what()<<endl;
                return 1;
        }
        cout<<i<<endl;
        return 0;
}
 

顯然“abcd”並不能轉換為一個int型別的數值,於是丟擲異常,捕捉後輸出“bad lexical cast: source type value could not be interpreted as target”這樣的資訊。

3.4 注意事項

lexical_cast依賴於字元流std::stringstream(會自動引入標頭檔案4),其原理相當簡單:把源型別讀入到字元流中,再寫到目標型別中,就大功告成。例如

int d = boost::lexical_cast<int>("123");
 

就相當於

int d;
std::stringstream s;
s<<"123";
s>>d;
 

既然是使用了字元流,當然就有些隨之而來的問題,需要特別指出5

  • 由於Visual C++ 6的本地化(locale)部分實現有問題,因此如果使用了非預設的locale,可能會莫名其妙地丟擲異常。當然,一般情況下我們並不需要去改變預設的locale,所以問題不是很大。
  • 輸入資料必須完整地轉換,否則丟擲bad_lexical_cast異常。例如
int i = boost::lexical_cast<int>("123.123"); // this will throw 
 

便會丟擲異常。因為“123.123”只能“部分”地轉換為123,不能“完整”地轉換為123.123。

  • 浮點數的精度問題。
std::string s = boost::lexical_cast<std::string>(123.1234567);
 

以上語句預想的結果是得到“123.1234567”,但是實際上我們只會得到“123.123”,因為預設情況下std::stringstream的精度是6(這是C語言程式庫中的“前輩”printf留下的傳統)。這可以說是boost::lexical_cast的一個bug。怎麼辦呢?權宜之計,可以這麼做:開啟標頭檔案<boost/lexical_cast.hpp>,注意對照修改6

#include <boost/limits.hpp>
//...
template<typename Target, typename Source>
Target lexical_cast(Source arg) {
        //...
        Target result; 
        interpreter.precision(std::numeric_limits<Source>::digits10);
        if( !(interpreter << arg) ||
        !(interpreter >> result) ||
        !(interpreter >> std::ws).eof())
        //...
}
 

即可得到正確結果。當然,理論上效率會有一點點損失,不過幾乎可以忽略不計。

4 小結


我們已經體驗了boost::lexcial_cast。當然,lexical_cast不僅僅侷限於字串型別與數值型別之間的轉換:可在任意可輸出到stringstream的型別和任意可從stringstream輸入的型別間轉換。這次的瞭解儘管很粗略,不過畢竟我們已經“走進Boost”,而不僅僅是“走近”。以後,我們可以自行領略Boost的動人之處啦。


 

 

相關文章