STL之父A.Stepanov專訪

 問:

可以先做個自我簡介嗎?

答:

     1950年11月16日,我出生於蘇聯莫斯科。在莫斯科大學研究數學,但我從未成爲一名數學家。我實在不能對Tamagawa算術感到興奮,儘管別人以爲我擅長Coxeter羣和一些別的東西。Hardy的念頭對我毫無吸引力─他的數學從來都不打算被實用化。我想幹一些哪怕只有那麼一丁點兒實際意義的事。不過,話說回來,我還是幸運的,能夠看到很多偉大的數學家是如何做的,使我能徹底對那些批着數學外衣的所謂嚴謹免疫。不幸的是,這在計算機科學中司空見慣。因此,能成爲一名程序員對我來說真是一件好事。1972年,我作爲一名小組成員,參與開發一個用於控制大型水電站的新的小型機系統。我參與了所有部分的設計,從架構到OS硬件測試(我的第一篇公開發表的論文就是關於實時操作系統的)到編程工具。我學到了關於軟件可靠性和效率的第一手知識─電站系統是不能輕易重新啓動的,水流也總是實時衝泄而下的。

     那時,我還探索了兩位偉大的計算機科學家Donald Knuth和Edsger Dijkstra的著作,從他們那兒,我學到了奠定我職業基礎的科學知識。前者告訴我答案,後者則引我深思。我一次又一次地到他們的著作中尋覓新的見解。我的下一個重要的職業生涯階段是在紐約Schenectady的通用電器研究中心計算機科學分部工作了5年。我致力於一個叫Tecton的非常高級的語言,閱讀了大量的資料,從繁多的程序語言設計論文到William of Occam的邏輯綱要─亞里斯多德和中世紀邏輯學家知道許多出現在自然語言裏的不同種類的邏輯結構以及它們的正式屬性。從那時起直到現在,我和Dave Musser合作,進行了碩果累累的研究。1984年,我成爲一名紐約布魯克林理工大學助理教授。教授計算機科學使我受益非淺,我要對付各種研究生課程。在此過程中,我學到了很多新東西。我還用Scheme語言開發了一個巨大的數據結構和算法庫,這項工作導致了Ada泛型庫的誕生(和Dave Musser合作)。在貝爾實驗室短暫地研究了一段時間C++算法庫後,我便去了位於Palo Alto的惠普實驗室(1988年)。在這兒,我花了四年時間研究存儲系統─我不得不學習磁盤控制器程序設計。1993年,我得到了一個短暫的回頭研究泛型編程的機會。STL就是這次研究的結果。1995年我又到了Silicon Graphics,在此,我正試圖組建一個小組進行進一步的STL開發工作。

問:

你剛纔提到了William of Occam。William of Occam曾說過“Entia non sunt multiplicanda”─我把它譯爲“[抽象]對象是不必要的”。好象你已經對OOP舉起了Occam的剃刀。以算法而不是對象爲起點之類的東西使我想起了中世紀關於宇宙的爭論,是這樣嗎?

答:

這個比方很妙,但我並不認爲它是對的。我從來都不認爲OO和現實主義者的哲學有什麼聯繫,我也壓根不是一個唯名論者。一個不容否認的事實是,Franciscan學派的Alexander of Hales、Bonaventure和Scotus都非常親近奧古斯丁教義/柏拉圖式的傳統。Occam是不折不扣的個異端分子。作爲他的Opera Omnia的編輯, Gideon Gal曾說過:“但是這傢伙真的瘋了!”
問:

     對於絕大多數意大利讀者來說,Stepanov”的名字和STL是不可分割的。STL究竟是指Standard Template Library標準模板庫)還是 Stepanov and Lee?另外,在STL的歷史裏,D.Musser和A.Koenig扮演了什麼樣的角色?

答:

     哦,它真的是指Standard Template Library。我曾經在Dr. Dobb的雜誌做的那個專訪裏開玩笑說,STL是指“Stepanov and Lee”,但它只是個玩笑而已。我已經和Dave Musser合作近20年了,我們之間的合作是如此緊密,以致於很難說清到底誰貢獻了什麼。他之所以沒有出現在官方的STL作者的名單裏,僅僅因爲在撰寫標準提議的那一小段時間裏,他在忙些別的。Andy Koenig負責向我解釋抽象C機(abstract C machine)的結構。STL,從某種意義上說,是Dave Musser和我一直進行C機模型開發的泛型編程技術的一個應用。如果不是Andy,我可能還在處理裝箱、堆分配對象問題併爲垃圾收集而憔悴。當然,Andy還和Bjarne Stroustrup負責把STL弄到標準裏去了。當要把美妙的想法變成完整的實現時,Meng Lee是一位無可挑剔的合作伙伴。她使我專注─我經常會在問題得到解決之後失去興趣─我知道解決辦法就夠了,幹嗎還要費神讓世界上其他人也知道呢?她在代碼和文檔上花了大量的令人筋疲力盡的時間。從某種意義上說,她是唯一堅信能從那些原材料中加工出實際東西的人。我想,在這一點上,對於能向任何人解釋清楚我們搞了許久的究竟是啥玩意,Dave Musser和我都早已不抱任何希望。

問:

STL起源於什麼?STL一開始就被設想爲今天這個樣子嗎?即所謂的C++標準庫,或者,它來自於別的什麼項目?告訴我們一些關於STL的歷史好嗎?

答:

1976年,又要說回到蘇聯了,我因爲吃生魚片得了嚴重的食物中毒。當住在院的時候,在精神錯亂的狀態下,我忽然意識到,並行的加法計算能力依賴於加法具有結合性的事實。(因此,簡單地說,STL是細菌感染的結果。)換句話說,我意識到並行的減法運算是和半羣結構類型有關聯的。這就是基本點:算法是定義於代數結構基礎之上的。意識到必須對正規公理加入複雜性必要條件以擴展結構的概念,又花了我另外一些年頭,接着我又花了15年使之行得通。(我直到現在都不能確定我已經成功地使我朋友小圈子之外的任何人理解了這一點)我相信迭代器理論是計算科學的中心,就象環或Banach空間理論是數學的中心一樣。每當我找到一個算法時,我都要努力去尋求它所定義的結構基礎。我想做的就是泛化地描述算法,並樂此不疲。我願意花一個月時間去發現某個著名算法的泛化表示。迄今爲止,在向人們解釋我這種行爲的重要性方面,我是異乎尋常的失敗。但是,不知何故,這種行爲的結果─STL卻是如此成功。

問:

     我曾認爲STL的複雜性純粹是由於實現的效率而不得不如此,而你好象暗示複雜性的確是功能上的需要?果真如此嗎?

答:

     選擇不同的算法依賴於數據結構提供的基本運算的複雜性。對於SCSI存儲設備來說,磁盤和磁帶在功能是等效的,但對於一個想把磁帶當成磁盤使用的軟件設計人員來說無疑是苦惱的。再看看STL你總可以爲前向迭代器實現p+n,爲什麼還要費心提供隨機存取迭代器呢?

問:

     何謂泛型編程?我只在JOOP上看到A.Koenig寫的一些“泛型編程”專欄。在大多數C++語言書籍裏,包括Coplien Meyer、Stroustrup、Lippman等人的,都很難看到泛型編程。我想,STL應該描述爲“用你從未認爲可能的方式編寫C++程序”你贊同這個說法嗎?

答:

STL,至少對我來說,代表用一致的方式編程是可能的。實際上,它完全不同於我們過去看到的C++編程,也完全不同於大多數教科書裏所描述的方式。但是,你知道,我並不是試圖用C++編程,我只是試圖找到一種正確的方式,來處理軟件。我已經爲尋找一個可以表達我的想法的語言好長時間了。換句話說,我知道我想說什麼。我能用C++說,我能用Ada說,我能用Scheme說。我可以讓自己去適應語言,但本質上,我試圖要說的,和語言無關。迄今爲止,C++是我發現可以表達我想說的最好的語言。它雖不是理想的媒介,但用它我可以比用別的語言表達得更多。實際上,我的夢想是哪天會出現一種專爲泛型編程而設計的語言。

問:

你可以爲普通C++程序員解釋一下什麼是泛型編程、泛型編程和C++以及STL的關係嗎?並且,你是怎麼想到在C++環境裏進行泛型編程的?

答:

泛型編程是一種基於發現高效算法的最抽象表示的編程方法。也就是說,以算法爲起點並尋找能使其工作且有效率工作的最一般的必要條件集。令人驚訝的是,很多不同的算法都需要相同的必要條件集,並且這些必要條件有多種不同的實現方式。類似的事實在數學裏也可以看到。大多數不同的定理都依賴於同一套公理,並且對於同樣的公理存在多種不同的模型。抽象機制!泛型編程假定有某些基本的法則在支配軟件組件的行爲,並且基於這些法則有可能設計可互操作的模塊。甚至還有可以使用此法則去指導我們的軟件設計。STL就是一個泛型編程的例子。C++是我可以實現出令人信服的例子的語言。

問:

我認爲STL和泛型編程標誌着一個不同於一般C++編程風格(我發現這種風格基本上是從SmallTalk繼承過來的)的新起點。你贊成這個說法嗎?

答:

是的。STL不是面向對象的。我認爲面向對象和人工智能差不多,都是個騙局。我已經看到了來自那些OO的人們寫的“有趣的”代碼。從某種程度上說,我對人工智能(AI)有偏見。我聽說好多關於MIT AI實驗室的一幫人的東西了,他們真正幹了一些基礎性的工作:Bill Gosper的Hakmem是程序員最好的讀物之一。AI或許沒有一個嚴肅的基礎,但它製造出了Gosper和Stallman(Emacs), Moses(Macsyma)和Sussman(Scheme, 連同Guy Steele)。我發現OOP在技術上是荒謬的,它妄圖依照因單個類型而異的接口來分解世界,爲了處理實際問題你需要多種代數方法─橫跨多種類型的接口族;我發現OOP在哲學上是荒謬的,它聲稱一切都是對象。即使真的是這樣這也不是很有趣,說一切都是對象跟什麼都沒說一樣;我發現OOP的方法論是錯誤的,它從類開始,就好像數學要從公理開始一樣。你不是從公理開始,你是從證明開始。直到你找到了一大堆相關證據後你才能歸納出公理,你是以公理結束。在程序設計方面存在着同樣的事實:你要從有趣的算法開始。只有很好地理解了算法,你纔有可能提出接口以讓其工作。

問:

我可以總結你的思想爲“發現隱藏在算法之中的[泛型]數據結構”,而不是“發現隱藏在對象之中的[虛]算法”嗎?

答:

沒錯。總是開始於算法。

問:

這需要從思想上做一個激進的改變,無論在命令式(imperative)還是OO思想方面。相比“標準”OO程序設計,比如SmallTalk或Java,這種方式利弊在於?

答:

我的方式行得通,他們的行不通。試試用OO方式來實現一個簡單的東西,比如說max,我不知道OO怎麼能辦得到。使用泛型編程,我可以這麼寫:

template <class StrictWeakOrdered>

inline StrictWeakOrdered& max(StrictWeakOrdered& x,StrictWeakOrdered& y)

{return x < y ? y : x;}

template <class StrictWeakOrdered>

inline const StrictWeakOrdered& max(const StrictWeakOrdered& x,const StrictWeakOrdered& y)

{return x < y ? y : x;}

&和const &兩個都要)。然後,我可以定義strict weak ordered的含義。用Java試試。你不能用Java寫一個泛型的max(),傳入兩個某種類型的參數並返回一個同類型的結果。繼承和接口在這兒無濟於事。假如連max或swap或linerar search都不能實現,那它們還有多大的把握去實現真正複雜的東西呢?這些就是我的石蕊試驗法:如果一種語言能讓我實現泛型的max、swap和linear search,那它還是有那麼一些潛力的(譯註:指泛型編程)。

問:

Java是一門非常新的語言,它還沒有模板,因此禁用泛型編程,一切都必須是類。你對Java怎麼看?

答:

我花了幾個月用Java來寫程序。跟它的作者預言的相反,它並沒有勾起我的興趣。我沒有從中發現任何新的見解有生以來,我第一次在一種新語言裏編程而沒有發現新見解。它保留了所有我在C++裏從來都不使用的東西繼承、虛機制OO垃圾),並且拿掉了我認爲有用的東西。它可能會成功畢竟,MS DOS就成功過,而且對於你們學習Java的讀者來說可能有利可圖,但它毫無任何知識價值。看看他們對散列表的實現,瞧瞧那些“酷”的sorting applet所使用的排序例程,再試試AWT。評判一門語言的最好的辦法是看看它的鼓吹者們寫的代碼。“!@#$%^&%$!×¥#”,(譯註:原文是“Radix enim omnium malorum est cupiditas”),Java顯然是一個面向金錢編程(MOP)的例子。SGI的Java首要倡導者曾對我說:“Alex,你必須去有錢的地方。”但我並不太想去有錢的地方,那種地方,味道通常都好不到哪裏去。

問:

你認爲基於模板的編程和泛型編程會被大多數C++程序員採用嗎?或者,它們僅僅侷限於使用在STL內,有點象操縱器(manipulators),它從不在iostream庫以外使用。

答:

我不知道。STL背後蘊藏的思想需要一段很長的時間纔會成爲主流。10到15年後,一切都會真相大白。

問:

有一件事情我一直都很驚奇,C++標準委員會那麼快就採納了STL。我的意思是,這些委員會可都是以謹慎和保守而出名的。對此,你怎麼解釋?

答:

Bjarne Stroustrup的支持是至關重要的。如果說Bjarne想要什麼東西的話,那就是他真的想把STL弄到標準裏。他辦到了。他象騾子一樣固執。甚至逼着我去改STL我從來都不會爲第二個人這麼做我也是個頑固分子,但他是我所認識的最有主見的人。他成功了。理解STL是幹啥的花了他一些時間當他明白之後,他決定使其更進一步。他對STL的貢獻還在於他支持這個觀點不止一種編程方法是“合法的”反對了十來年的無休止的爭吵和謊言,並堅持把彈性、效率、重載、類型安全結合在模板裏,以使得STL成爲可能。我很樂意明明白白地聲明,Bjarne是我們這一代卓越的語言設計者。

問:

STL完全是對模板的創造性使用,比如從類中導出符號類型,或是對迭代器標記的一系列重載算法的模式匹配,當然足夠了,沒有任何標準C++書籍提到這些術語,你是怎麼想出這些C++代碼習語的?

答:

我清楚地知道我要努力達到的目標,於是我“擰”這個語言直到我能夠過得去,但這花了我好多年去探索所有的技術。我有很多錯誤的開始。比方說,在我意識到爲什麼那種機制從根本上具有缺陷而不應該使用它之前,我浪費了好多年試圖從繼承和虛機制裏找到一些有用的東西。我非常高興沒有人能看到任何中間步驟,它們大都是愚蠢可笑的。我花了好長時間才弄出一些象點樣子的東西。這也對Bjarne願意往語言里加入某些能使我的術語工作的特性起到了推動作用。有一次,他把這說成是“即時語言設計”。

問:

你認爲向C++程序員教授泛型編程和STL的最佳方式是?你認爲在學習STL之前、期間或之後,應該學習繼承以及其他OO技術嗎?

答:

我計劃在SGI教授一門關於泛型編程的課,我非常希望這也能促使我出一本書,但我是一個聲名狼藉的懶惰作者,我從來都沒有完成論文過,除非我有一個合作伙伴來幹這個事。

問:

我已經使用Lycos(譯註:一種WWW搜索引擎)搜索過你的論文,我只找到兩條,是你提供給標準委員會的關於STL的指南和摘要。

答:

是嗎,我是懶,但我還沒懶到那個份上。我大概發表了20來篇的論文並出了一本書。它們大都在不同的STL站點上。(Dave Musser的站點上可能有幾篇。)

問:

那本書是?

答:

那本書叫《The Ada Generic Library: Linear List Processing Packages》,作者David R. Musser/Alexander A. Stepanov, 指南針系列,Springer-Verlag,1989。它並不值得一讀。

問:

STL使C++編譯器達到了它們的極限,同時代的C++編譯器還不能正確地編譯某些STL代碼,你是怎麼開發和測試STL的?

答:

爲了試圖編譯STL我都白了不少頭髮了。不幸的現實是,當我開發STL時,因爲編譯器的限制和編譯器裏的bug,許多代碼在當時的STL的實現中是不夠理想的。幸運的是,我從Bjarne那兒得到了不少幫助,他指出某種尚未實現的特性假定會被實現。如果能有一位語言設計者告訴你,已經給出的設施究竟幹了些什麼,那是大有幫助的。

問:

配置器(allocators)是怎麼到STL裏的?你對它們怎麼看?

答:

我發明了配置器去處理英特爾內存架構問題。理論上它們並不壞—添一層封裝所有內存有關的東西:pointers、references、 ptrdiff_t、size_t。不幸的是,它們實際上不能工作。例如:

vector<int, alloc1> a(...);
vector<int, alloc2> b(...);

你現在不能說:

find(a.begin(), a.end(), b[1]);

b[1] 返回一個alloc2::reference並不是int&。它可能會導致類型不匹配。有必要改變實現方式該讓語言核心去處理引用從而使配置器真正有用。

問:

這是不是指出了C++模板的一個嚴重的缺點?我可以使用模板引數(template argument)定製一個類,但不同的特化實現並非類型兼容,但一個類不同的子類(在OO意義上)和其根類是類型兼容的。

答:

我認爲問題比“T* 是被hardwired在語言裏”來得深。一般而言,我相信需要從頭開始設計一種程序語言,可以一致方式進行泛型編程。我希望能有人僱我去幹這個事。

問:

我在D.Musser站點上看到了兩個散列表的實現,它們都可以工作並且十分靈巧比一般類庫裏的要靈巧得多。爲什麼散列表沒有納入STL呢?

答:

“政治原因”(譯註:意思是“有關公衆的意願”,下文皆然。)。它們應該包括進來。我們新的STL實現包括它們。大體上說,我們需要發展一個往STL裏添東西的機制。畢竟,STL是個可擴展的框架,它也被請求擴展。有很多數據結構都還沒加進來,比如,單向鏈接表、矩陣和圖。SGI樂意在擴展STL方面起到領導作用。

問:

你還搞STL嗎?具體搞什麼?

答:

我在SGI的團隊—Matt Austern、Hans Boehm和我自己,剛剛完成一個STL的新版本。它包括散列容器、線程安全內存配置以及壯觀的WEB文檔。SGI把它發佈在http://www.sgi.com/Technology/STL,我們希望我們能保持STL不斷成長。多維數據結構、持久化、多線程都是我們計劃要加入的東西。唔,我不清楚我們還能搞這個東西多長時間。我的管理者們對STL/泛型編程活動沒提供任何支持。向他們解釋爲什麼SGI有責任擴展STL非常困難。(同樣困難的是向惠普的管理層解釋。在STL被接納爲標準之後,他們取消了我5個月的項目)。

問:

好像STL依然還存在某些不足之處。首先HP STL不是線程安全的。而且模板導致了要把大量的代碼放到頭文件中。你無法擁有真正的模板庫,不管是DLL形式還是共享庫(未具現化的)形式的模板—STL通常是編譯時庫。最後一點是幾乎沒有任何CASE工具和OOD方法學有效地支持泛型編程。比如,沒有CASE工具能讓你定義泛型函數,也只有Booch符號能在某種程度上表達模板,但它產生的圖表並不直觀(至少對我來說)。

答:

SGI STL是線程安全的。“單獨編譯”(separate compilation)已經被標準採納,它是由我的SGI同事John Wilkinson、Jim Dehnert和Matt Austern設計的,它解決了你的第二個問題。它已經經投票納入標準,但還需要一段時間纔能有支持“單獨編譯”的編譯器。我堅信“單獨編譯”最終需要交付共享模板庫。這也是我在SGI發起單獨編譯工作的主要原因。設計處理泛型編程的工具並不困難,我敢肯定,只要市場需要,Grady Booch會改進他的符號來處理泛型編程的。

問:

C++程序員感到痛苦的一件事是,那些標準委員會們好像彼此都無動於衷。OMG剛剛定義了一套分佈式編程(CORBA)標準,但STL裏並沒有從CORBA到C++的映射。他們各自定義了自己的一套類,比如Sequence<T> 和 CORBA::String。同樣的問題也出現在ODMG和ODMG-93對象數據庫標準上。怎麼會發生這種事?這種狀況能得到改變嗎?

答:

我老得都記不得70年代提出的所有網絡標準了。誰現在還能記得它們?

問:

泛型編程在分佈式環境裏會是什麼樣子?泛型編程是基於這樣的思想的:編譯器在編譯時知道所有可能的類型。這在分佈式環境裏是不現實的。我們是不是應該考慮在編譯器中集成某種ORB?或者泛型編程壓根就不適合分佈式編程?在這個意義上,是不是Java更合適?

答:

泛型編程和“運行時”、“編譯時”之類的東西沒有任何關係。問題是我發現OOP不單是慢,它還不允許我表達可能是最簡單的算法。再提一遍,max的記號爲:

max: T x T -> T

Java無法表達,因爲從某個類或接口T繼承導致它變爲:

max: T' x T -> T

你需要協變記號轉換(covariant signature transformation),並且要能夠從類型取得類型信息,如果你喜歡,虛類型的概念—v-table包含了類型描述符。

問:

什麼是迭代器(iterator)?

答:

迭代器是兩個理論的聯合體。第一個理論是命名理論(例如handle、cookie、address等)。一個命名實際上是指向另外一個東西的東西。(operator*)。我們稱之爲Trivial Iterator理論。再加上解引用dereferencing),它同樣被定義從而滿足以下公理:

i == j iff &*i == &*j

也就是說,兩個迭代器是完全相等的,當且僅當它們指向同一個對象時。(“相等”當然要滿足所有標準公理)。第二個理論是關於精緻的後繼操作(++i):後繼-前繼(++和--)以及(++、--、+和-),滿足標準公理當然,指針只是一個隨機存取迭代器模型。

問:

有些人爭論說指針會以任何能夠想到的可怕的方式和不可思議的方式破壞內存。Java和Delphi就沒這個問題,因爲它們不允許指針。 (譯註:作者只是爲了強調,不必深究此句話。)

答:

不允許指針還能讓你做指針算法是件好事。在C和C++中,指針算法只應該允許用在它真正被允許的地方,換而言之,比如數組裏的指針。但泛泛地不接受指針是非常愚蠢的做法。你不能做泛型交換(swap)除非你的語言裏有指針或引用。

問:

category”範疇)是一個被C++社團濫用的詞。你怎麼稱呼iterator categories(迭代器範疇)?

答:

我常常稱之爲concepts(概念)。

問:

我試圖開發一個STL風格的單向鏈接表。但是我決定不實現size()成員函數,因爲我不想僅僅爲了以常數時間實現size()而保持一個計數的負擔,就象C++ CD所聲稱的那樣。這個決定正確嗎?

答:

STL列表的size()曾以線性時間方式實現的,那一個正確的決定,因爲假如用戶想保持一個計數的話也容易做到。但通常來說,你不需要那麼做,並且它造成了銜接的線性時間(splice linear time)。但標準委員會堅持讓我改成常數時間。我別無選擇。我們最終將不得不改變這個要求。

問:

我正在研究怎樣在STL裏表達一個樹,我碰到了一些問題:每一個節點都有一個父親和兩個兒子。移動到父親可以描述爲operator--,但我需要兩個不同的operator++以移動到它的兒子們。迭代器怎樣來處理非線性結構,比如樹或圖?

答:

即使在序列(sequence)上你也有不同的迭代器。反向迭代器(Reverse iterators)就是一個例子。步幅迭代器Stride iterators)非常重要,最終將被加入到STL。

問:

我必須得承認我的無知。什麼是步幅迭代器?

答:

i到i+5再到i+10。

問:

它和隨機迭代器的不同之處在於?

答:

步幅迭代器是這樣的一種迭代器適配器(iterator adaptor),它帶有一個隨機存取迭代器範圍並提供一個隨機存取迭代器,在其上++就可以通過一個步幅(一個迭代器序列, n步間隔。)

問:

這和樹的遍歷有什麼關係?

答:

我並沒有說步幅迭代器或反向迭代器跟樹的遍歷有什麼關係,但是,對於一種數據結構來說,可以有多種迭代器類型以滿足不同迭代順序例如樹的前序、中序和後序遍歷。

問:

我常常會碰到一個棘手的決定:我應該把一個函數設計成成員函數還是泛型(全局)函數?在STL中做出這種決定的基本原則是什麼?

答:

只要有可能就把它設計成全局的。如果從頭到尾都是全局的話會更好。那就允許我們用C數組來定義它們。如果operator*具有全局缺省定義,那會更好:

template <class T> T& operator*(T& x) { return x;}  

template <class T> const T& operator*(const T& x) { return x;}

它將允許我們這麼寫:

     copy(0, 25, ostream_iterator<int>("/n"));

一般而言,對於非迭代器對象來說,operator*應該返回對象自己,未命名的東西是指那個東西自己。我甚至想把構造器和析構器都寫成全局函數。如果語言允許這麼做的話,你會可以做一些令人驚奇的事情。

問:

如果我按你的方式定義一個泛型operator*,並且,在我的程序裏我這麼定義:

template <class T> class SmartPtr 

{

  T* ptr;

 public:

   SmartPtr(T* _ptr = 0) : ptr(_ptr){}

  T* operator*() const {return ptr;}

  // ...

};

那麼,下面的代碼裏會不會導致模棱兩可:

int i=0;

SmartPtr<int> sp(&i);

int j= *i; // 使用 SmartPtr<int>::operator* 還是operator(SmartPtr<int>),用戶都定義了?

答:

不,不會的。你的定義比全局的匹配得更好(深層次的一致)。那正是局部特化(partial specialization)所講的東西。

問:

現在,我有一些好奇:爲什麼STL沒有“排序容器”(sorted container)適配器之類的東西?

答:

set就是一個排序容器。

問:

set並不是一種適配器。爲什麼能去寫一個堆(heap),卻沒有寫一個獨立於任何支持隨機存取迭代器的容器的排序容器?

答:

記住,因爲STL的尺寸問題導致它很難通過標準委員會的審覈。我已經扔掉了好多有用的東西了。(想想在散列表身上都發生了些什麼吧)

問:

爲什麼<heap.h>裏的__adjust_heap函數沒有被歸檔?在Dijkstra算法裏,這個函數對使用堆來說是必不可少的。

答:

我費了很大的勁才把堆函數弄到標準裏。本來我是想把STL中所有輔助函數都公開出來的,但存在政治上”的可能性。

問:

對我來說,很難想像關於堆函數的“政治因素”。

答:

倒不是函數有什麼特別,而是因爲它們的數量。Bjarne親自負責減少STL裏組件的數目有個一分爲二的原因。他試圖使其儘可能的小以安撫反對者。

問:

你到過意大利嗎,商務還是休閒?

答:

我在比薩逗留了十天,遊覽了佛羅倫薩和魯卡。我夢想去安西斯,在內心,我是一個方濟各會(譯註:天主教的一個分支)信徒。在Tosca的第二幕和La Traviata的第三幕裏我哭了。我把但丁(意大利人!)擺在牀頭。我喜歡意大利麪點、薰火腿和基蒂安葡萄酒,我是一個傳統主義者,我看起來更象John XXIII而不是 Pius XII。

問:

你的意大利語肯定很好,如果你能閱讀但丁的原版作品的話。很少有意大利人能夠讀懂。

答:

唔,我的意大利語是很差的。我能讀懂但丁的作品是因爲我有英譯本。我用意大利語高聲朗誦然後再讀英譯本

Graziano:

非常感謝,Alex,希望你能夠早日來意大利並去安西斯看看,在安西斯的古鎮閱讀但丁,它可能是意大利最迷人的中世紀小鎮。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章