1. 程式人生 > >STL庫和Boost庫

STL庫和Boost庫

 在設計原則上,STL和Boost大體統一
因為STL和Boost基本上都是標準委員會那批人在策劃、稽核和維護,所以口味上是相對接近的。
但是因為Boost並不在標準中,或者說是下一代標準的試驗場,所以庫的種類要更多一些,手法也更加豐富一些。

2. STL/Boost 針對 Developer 和 User 的要求不同
對於Boost開發者而言,強調的是程式碼可讀、高效、強調超程式設計和程式設計技巧。

補註:評論裡面果然有人提到說可讀性和超程式設計有矛盾。這種說法大概類似於“這段程式碼可讀性差是因為業務太複雜”。這是不對的。可讀性是要建立在正確的滿足功能和效能的基礎上的。這也是為什麼我要特別為後兩點解(Jiao)釋(Bian)一下。


這裡要解釋一下後兩點:

  • 程式設計技巧主要是為了實現一些看起來有點像天方夜譚的功能,例如C++11之前的Boost.Auto(利用了編譯器的Bug或者特性);以及1.56才加入的TypeIndex,該巨集利用了編譯器能產生Mangled/Demangled函式簽名的能力。
  • 超程式設計主要是為了解決三個問題:
    • 增加巨集/模板演算的能力,為圖靈完備的模板程式設計提供型別/常量運算的庫,方便開發者。例如Boost.MPL和Boost.PP;
    • 增加C++的語言內描述能力,也就是Embedded DSL。例如Spirit和Proto,都是很好的例子;
    • 做盡可能多的靜態檢查。比如Boost.Chrono將單位繫結到型別中,解決了單位轉換容易出錯的問題。

而STL因為處於標準中,所以會對不同平臺的編譯器都做出了統一要求,需要編譯器配合的地方,也不會用語言機制或者奇技淫巧來遷就,例如Static Assertion、Auto、decltype,在Boost當中是以一定的技巧實現的(因為編譯器不能直接支援),而在C++11種就變成了一個內建的語言特性。與此類似的還有很多的Type Traits。

對於User而言,Boost/STL的庫可以分為四種風格。

  • 第一種風格為Lib風格,以提供功能為主,使用方法一般也就是as-is。例如Pool,Graph,Interval,Chrono,ASIO等。它們的介面使用也可以分為兩個部分,第一階段是型別特化,第二階段是基於執行時介面。STL和Boost裡,大部分庫都是這樣的風格。這也是最容易使用和使用頻率最高的風格。
  • 第二種風格是語法糖類。Boost.Foreach等都屬於這一類。但是在STL中就非常罕見,因為語言已經得到了充分升級。
  • 第三種風格是正規化和方法論的拓展,即在C++中模擬其他程式設計正規化和方法論。例如spirit,lambda,proto。嚴格的說,boost.mpl也可以歸屬此類。這一類庫的使用方式分為兩步,第一步是定製方言,第二步是使用方言。這類應用因為面向庫的開發者,所以STL中很難見。
  • 第四類風格,是超程式設計。利用模板和巨集進行編譯器推導,以實現程式碼展開、選擇編譯等工作。典型的例子有Boost.PP,STL/Boost.TypeTraits,enable_if等,這一部分對於一般使用者是可以不用的。STL中有部分基礎的超程式設計支援(例如Traits)。

因為STL多數是面向一般程式設計師,所以以第一種庫居多,而Boost包含了全部四類的庫的風格。

3. 文件
Boost的文件基本上是tutorial風格的,Reference做的並不好。而被標準化的STL通常會有更加清晰易讀的Reference。

4. 平臺特定性
Boost有很多支援不同平臺、或者IO相關的玩意兒,比如Boost.Process,GIL,ASIO,Context,哪個都不是平臺無關的省油燈。反觀STL對這方面一直都很保守,之前一直就只有容器這類東西,C++11之後才把Thread、File System這種和平臺有些關係的內容陸續給弄進來,IO和網路到現在都是一塊一毛不拔的荒地。

5. 問題
Boost和STL的問題幾乎是相通的,就是因為模板使用多,編譯時間較長,二進位制也相對較大。編譯錯誤也不是非常明確。Boost中一些超程式設計分量更多的庫,例如MSM和Spirit的問題要更加嚴重。
此外,因為Boost是試驗性質的庫,所以介面可能不是非常穩定。而一旦庫進入STL之後,就幾乎不可能有變化了。比如Boost.Filesystem在進入TR2之前,先後有三個比較大版本的API變動;Spirit也做出了一次比較大的調整。
還有就是,Boost的庫和其它語言的標準庫相比,零散雜亂,我經常也忘記Boost/STL中的某些庫,自己去發明了一個一點都不好用的輪子。

6. 乾兒子
最後就是,雖然Boost是標準委員會的乾兒子,但是也不保證它的實現就一定是進入STL。比如網路庫,最後進標準的,應該是CppNetlib,而不是ASIO。