Modern C++ Design Loki 庫源碼讀解隨想

大牛 Andrei Alexandrescu 的《 Modern C++ Design 》討論的是 C++ 語言的最前沿研究: generative programming 。本書中譯版估計得要半年以后才能出來,所以只能靠其所附源碼來窺測generative programming了。

目前,我剛將源碼讀解了約一半,等全部讀完,我會將我的讀解注釋放出來的?,F在,現談一下我的感想。

??? 先扯得遠一點。C++有兩個巨大優點:和C兼容,自由;有兩個巨大缺點:和C兼容,復雜。C++極其復雜,很難掌握,而這正是“自由”的代價。C++語言是個多編程風格的語言,它同時支持 過程化、基于對象、面向對象、泛型、生成性 5種編程思想,具有極其強大的表達能力,可以方便地將各種設計轉化為實現。

generic Programming 的思想精髓是基于接口編程(相對于OOP,連多態所需的基類都不要了),它的技術出發點是選擇子,核心技術是:類型推導、類型萃取、特化/偏特化,其成果是STL庫:一組通用容器和一組操作于通用容器上的通用算法。

generative programming 的思想精髓是基于策略編程(編譯器根據策略自動生成所需代碼,由于具有更高的抽象性,所以代碼復用度也更高),在Loki庫的實現中,目前只使用了遞歸策略,它的技術出發點是Typelist,核心技術是:類型推導、類型萃取、特化/偏特化、多重繼承、類型間去耦合,其成果是Loki庫:對設計模式的封裝。

Typelist 是一種對類型本身進行存儲和管理的技巧,它的源碼已經貼過了,我也作了注解,此處不再談論。

這是多重繼承COM之后的又一大型運用。多重繼承極易發生菱型缺陷,所以Loki庫使用了類型間去耦合技術來避免:

??? template <typename T>

??? struct Type2Type

??? {

??????? typedef T OriginalType;

??? };

經過這樣一層轉換后,原類型 T 間的各種轉換關系(尤其是繼承 / 派生關系)已不復存在, 菱型缺陷 不會再發生了。

Loki庫的具體實現相當講究技巧,設計它非常困難(難度遠大于STL庫,和Boost庫有得一拼啊)。但使用它卻非常容易,而且便利顯著。由于Loki庫提供了對設計模式的封裝,所以極大量地豐富了C++語言的表達能力,使的你的設計更容易地轉化為實現。

目前,Loki庫只提供了對廠模式和visitor模式的封裝,它還處于發展初期。

我以visitor模式為例,講解Loki庫提供的便利。

Visitor 模式有四種實現方式:1一串RTTI的類型判斷;2二次調度(double dispatch);3建立類型與處理函數的對應表;4非循環visitor(Acyclic Visitor)。在《More Effective C++》 Item 31中討論了前3種實現(雖然它的例子本身不太算visitor模式的)。第四種方式在《使用設計模式改善程序結構》(二)( http://www-900.ibm.com/developerWorks/cn/java/l-dpstruct/part2/index.shtml )中有詳細講解。

?

原型圖

以這張原型圖而言,用戶需要自己實現大量的代碼,而且,由于使用多重繼承技術,在具體 Host 類間有繼承關系時,它一定會發生問題。

?Loki 庫實現圖

?

使用 Loki 庫,用戶實現 visitor 模式時只需:讓 Host 類從 BaseVisitable 繼承,并在所有派生類中加上 DEFINE_VISITABLE() 宏,讓所有 Visitor 類從 BaseVisitor 類和 VisitorImpl 類進行二重繼承(并且可以只提供對自己感興趣的 Host 類的處理函數,不感興趣的不提供處理函數)。用戶的工作量非常小、非常簡單,設計人員可以不用為實現而分心了。

更重要的是,由于采用了類型間去耦合技術,多個 Host 之間存在繼承關系時,不會發生問題(其具體實現較復雜,于是我在 UML 圖上作了模糊處理,沒有展示出來,留在以后 Loki 庫源碼讀解時講述)。