??
在本系列的上一篇文章里,我列出了我認(rèn)為最重要的五本
C++
圖書,但大量有關(guān)
C++
的重要文獻(xiàn)并非來(lái)自圖書。比如期刊、雜志、網(wǎng)絡(luò)上的文章;博士論文、會(huì)議紀(jì)要;新聞組帖子;博客;標(biāo)準(zhǔn)化文檔等很多很多。它們對(duì)
C++
的進(jìn)步與繁榮作出了巨大貢獻(xiàn)。我沒(méi)有讀全,甚至談不上讀了大多數(shù),但作為
C++
的長(zhǎng)期關(guān)注者,我還是閱讀了很多這類文獻(xiàn)。在本期里,我將評(píng)選
C++
歷史上最重要的五部非圖書類文獻(xiàn)。和上期評(píng)選圖書一樣,我仍然將數(shù)量限制為五,盡管我沒(méi)有寫出過(guò)重要到能上這個(gè)榜的東西,但仍然將自己列入了候選隊(duì)伍。以下文獻(xiàn)按時(shí)間為序。
一個(gè)讓我無(wú)可回避的邏輯范疇兩難問(wèn)題是:如果文獻(xiàn)
A
的思想對(duì)
C++
直接影響很小,但文獻(xiàn)
B
的作者讀到了
A
,將這個(gè)思想引入了
B
并產(chǎn)生了巨大影響,那么到底哪個(gè)文獻(xiàn)更重要,
A
(“發(fā)明者”)還是
B
(“繁榮者”)?我最終選擇了
B
,并不是因?yàn)檫@種做法天然就正確,而是因?yàn)槲也幌牖馄疵凡橄铝形墨I(xiàn)作者的思想是否從別的文獻(xiàn)繼承而來(lái)
[
注釋
1]
。反過(guò)來(lái),我隨便翻到
C++
語(yǔ)言規(guī)范的某頁(yè)。大家知道,
const member functions
里的
const
是不徹底的:指針數(shù)據(jù)成員自動(dòng)變?yōu)?/span>
const
,但指針?biāo)傅臄?shù)據(jù)本身不會(huì)。借鑒這個(gè)規(guī)定,我假設(shè)公布在下面的名單里的文獻(xiàn)重要,而忽略它們引用的基礎(chǔ)物(以及我所不知的其他文獻(xiàn))。當(dāng)然,從
C++
本身來(lái)說(shuō),這可能不是正確的做法,但易于實(shí)現(xiàn),所以我也這么干了
[
注釋
2]
。
在詳細(xì)解說(shuō)名單之前,我想請(qǐng)各位發(fā)發(fā)善心,允許我為《
C++ Report
》——曾經(jīng)為
C++
作出了最重大貢獻(xiàn)的期刊——說(shuō)幾句悼詞(如果你不那么仁慈,就請(qǐng)直接跳過(guò)去閱讀后面內(nèi)容吧)。在其存在的大部分時(shí)期(
1989-2000
)里,《
C++ Report
》一直是
C++
推動(dòng)者和鼓吹者紙張寫作的樂(lè)園(在此期間,首倡電子寫作的是
Usenet
新聞組
comp.lang.c++
,后來(lái)還有
comp.std.c++
和
comp.lang.c++.moderated
)。在《
C++ Report
》發(fā)表文章的人里,有些名字你可能聽說(shuō)過(guò)(比如我上期列出的“最重要的
C++
圖書”的作者),更多的可能你就不知道了(譬如下面要提到的一些文獻(xiàn)的作者,以及——算了,名單太長(zhǎng),簡(jiǎn)直沒(méi)辦法開始。我知道,如果開了頭列出一些名字,那就暗示著未列出的人沒(méi)列出的那么重要,這樣一來(lái)我的麻煩就大了。所以干脆一個(gè)不提,但請(qǐng)相信我,《
C++ Report
》有生之年一直相當(dāng)興盛,它吸引了這個(gè)領(lǐng)域最好的寫作群體——都是最有興趣,也是最有實(shí)力去寫作的人)。《
C++ Report
》關(guān)門的時(shí)候,很多專欄作家投向了《
C/C++ Users Journal
》,但這個(gè)雜志從來(lái)沒(méi)有像《
C++ Report
》那樣吸引過(guò)我;現(xiàn)在,
CUJ
也停刊了。《
C++ Report
》留給像我這樣整天胡說(shuō)八道的老怪物們的,就只有面對(duì)時(shí)光飛逝的無(wú)奈哀嘆了。
嘮叨這么多,我感覺好點(diǎn)了,還是繼續(xù)說(shuō)我的最重要非圖書類文獻(xiàn)名單吧:
《
Programming in C++, Rules and Recommendations
》,作者是
Ellemtel
電信系統(tǒng)實(shí)驗(yàn)室的
Mats Henricson
和
Erik Nyquist
,
1992
年。在我
90
年代早期前后的一些文章里,我提到過(guò)當(dāng)時(shí)很多程序員渴求如何駕馭
C++
威力方面的指導(dǎo)意見,他們最感興趣的是告訴他們?cè)撟鍪裁础⒉辉撟鍪裁吹木幊桃龑?dǎo)手冊(cè)。幾乎在我的《
Effective C++
》嘗試提供這方面指導(dǎo)的同時(shí),
Mats Henricson
和
Erik Nyquist
在互聯(lián)網(wǎng)上發(fā)布了他們寫的編程手冊(cè)。其實(shí)在此之前,這本手冊(cè)就出來(lái)一段時(shí)間了,但因?yàn)槭侨鸬湮模源蟠笙拗屏怂膫鞑ァ?/span>
Ellemtel
版手冊(cè)以技術(shù)性語(yǔ)言寫成,容易閱讀,因此二位作者聲名遠(yuǎn)播、影響很大。不久,大家得知他們準(zhǔn)備成書出版,此時(shí)我就有不祥預(yù)感(競(jìng)爭(zhēng)于市場(chǎng)可能是件好事,但那時(shí),我是這個(gè)市場(chǎng)上僅有的參與者。我真的很喜歡這本書冊(cè)的風(fēng)格
[
注釋
3]
)。我們對(duì)這本書滿懷期待,轉(zhuǎn)眼間時(shí)間過(guò)去了幾年。
1996
年底,它終于面世了(《
Industrial Strength C++
》,
Mats Henricson
和
Erik Nyquist, Prentice Hall, 1997
),但那個(gè)時(shí)候,這本書的很多指導(dǎo)意見與同時(shí)代的編譯器相比已經(jīng)過(guò)時(shí),它包含的很多信息在
C++
社區(qū)里已經(jīng)廣為人知,與
4
年前第一次的英文版相比,人們感覺它的作用已經(jīng)大打折扣。我閱讀了這本書,先是興趣滿懷,然后就有點(diǎn)傷感,因?yàn)槲腋杏X到花費(fèi)
4
年時(shí)光從互聯(lián)網(wǎng)文檔到成書,不僅它包含的技術(shù)信息失去了當(dāng)年的光芒,寫作本身也喪失了原有的精神。我估計(jì)原稿已經(jīng)被無(wú)數(shù)次修改,以期符合評(píng)審者在各方面的要求。這就解釋了它為什么花費(fèi)了如此長(zhǎng)時(shí)間才得以出版,為什么最后的成書如此平淡。
我想,作者和出版商對(duì)這本書寄予厚望,但事與愿違,不過(guò)這并不能削弱最初互聯(lián)網(wǎng)版本的影響力。它一出來(lái),
C++
程序員就一口咬了上去。它是
C++
最佳實(shí)踐規(guī)范總結(jié)道路上的重要里程碑。
《
Exception Handling: A False Sense of Security
》,作者
Tom Cargill
,
1994
年發(fā)表于《
C++ Report
》
11
、
12
月刊。
1994
年,
C++
社區(qū)矯矜之氣彌漫。當(dāng)時(shí),
C++
是很熱門的語(yǔ)言,工作崗位充足,很多人認(rèn)為
C++
無(wú)所不能。在此前幾年里,這門語(yǔ)言里增加很多重要的特性,比如多繼承、模板,以及稍晚點(diǎn)的異常。因?yàn)楫惓J切率挛铮?/span>
C++ Report
》上就出現(xiàn)了很多討論文章,凡是
C++
程序員出現(xiàn)的場(chǎng)合,大家都是三句話不離異常。很多文章反映了屬于那個(gè)時(shí)代的狂熱:“異常美妙之極,它們讓錯(cuò)誤處理變得簡(jiǎn)單。你需要做的所有事情就是去理解
try
、
throw
和
catch
。看我編寫一個(gè)堆棧類吧,告訴你們
C++
有了異常處理后,將比過(guò)去酷多少。”
Tom Cargill
的文章(是他的長(zhǎng)期專欄
“C++ Gadfly”
——這是多年來(lái)最名副其實(shí)的專欄之一——里的一篇)拂去了我們臉上集體自滿的微笑。僅僅用一句話,
Cargill
就說(shuō)明了
try
、
throw
和
catch
對(duì)這個(gè)問(wèn)題毫無(wú)幫助:
運(yùn)用異常的真正難點(diǎn)在于如何以如下方式編寫所有介于二者(
thow
和
catch
)之間的代碼:任何異常都能從
throw
處安全到達(dá)處理它的地方,且不破壞傳遞路線上的其他程序部分。
這個(gè)專欄繼續(xù)剖析了《
C++ Report
》上我剛才提到過(guò)的“異常美妙之極”系列專欄上的文章
[
注釋
4]
,最后以一個(gè)擂臺(tái)(
Cargill
稱之為“邀請(qǐng)”)結(jié)束:發(fā)布一個(gè)異常安全的堆棧類。這個(gè)挑戰(zhàn)引來(lái)了潮水般的回應(yīng),但我認(rèn)為,直到
1997
年,
Herb Sutter
發(fā)表的一篇文章才算真正有分量(后面會(huì)說(shuō)到這個(gè)事情)。
我認(rèn)為
Tom Cargill
的專欄文章不僅證明了我們對(duì)于異常想法的幼稚,而且也還了
C++
一個(gè)清白。在我們明白如何編寫異常安全的代碼時(shí),
Java
這門可愛的新語(yǔ)言出現(xiàn)了(就我所知,現(xiàn)在是
Ruby on Rails
),曾經(jīng)信誓旦旦的“我們天下第一”狂想再也沒(méi)有回來(lái)過(guò)。
?
《
Curiously Recurring Template Patterns
》,
Jim Coplien
于
1995
年發(fā)表在《
C++ Report
》
2
月刊。這篇文章的意義不在于它的內(nèi)容本身,而在于它給所述內(nèi)容的命名。真是雙重巧合啊,這篇文章來(lái)自于
Coplien
的專欄“
The Column Without a Name
”,而且他給文章起的名字也已經(jīng)直接成了一個(gè)模式名:
The Curiously Recurring Template Pattern (CRTP)[
注釋
5]
。這個(gè)模式本身是指將派生類作為參數(shù)在它自己的模板化基類里使用:
?
template<typename T>
class Base { ... };
?
class Derived: public Base<Derived>
{ ... };
?
很多人對(duì)模板的使用都超出了
T
容器的范圍,最后往往皈依到了
CRTP
的設(shè)計(jì)思想。這時(shí)候,他們通常都會(huì)懷疑這樣的代碼是否可以通過(guò)編譯,當(dāng)發(fā)現(xiàn)可以通過(guò)編譯(可能他們大吃了一驚)后,就很擔(dān)心自己弄出這樣的設(shè)計(jì),是否是頭腦癡呆的早期癥狀。就在這時(shí),
Coplien
投稿了。更多有經(jīng)驗(yàn)的同事會(huì)保證說(shuō):“不是啊,你沒(méi)有精神病。從基類派生一個(gè)類,基類又在派生類的基礎(chǔ)上模板化,不僅是合法的設(shè)計(jì)技術(shù),而且它還有一個(gè)正式的名字呢:
the Curiously Recurring Template Pattern
。”
《
Using C++ Template Metaprograms
》,作者
Todd Veldhuizen
,《
C++ Report
》
1995
年
5
月。此文見證了
template metaprogramming (TMP)
的第一次大規(guī)模出現(xiàn)熱潮。這是一個(gè)重要的時(shí)期,但我完全錯(cuò)過(guò)了這條船。我清楚記得閱讀這篇文章時(shí)我的想法:“好,這樣你就可以用遞歸的實(shí)例化模板去模擬編譯時(shí)的循環(huán)。你能通過(guò)模板特化去實(shí)現(xiàn)編譯時(shí)的
switch
表達(dá)式。太好了!但你為什么要這樣做?”哦,我說(shuō)謊了。我當(dāng)時(shí)真正的想法是:“但你如果這樣做,你就是個(gè)瘋子。”
[
注釋
6]
盡管
C++
社區(qū)并不缺乏追捧,再后來(lái)有關(guān)
TMP
的文章也在各種論壇上陸續(xù)出現(xiàn),不過(guò)這不讓我驚詫。我那時(shí)深信
TMP
是一門概念過(guò)于離奇、語(yǔ)法過(guò)于超前以至于沒(méi)有立足點(diǎn)的技術(shù)。現(xiàn)在,我知道大多數(shù)人似乎也同意它在語(yǔ)法上的確讓人感覺不適,概念上不說(shuō)過(guò)于怪異,至少也偏離了主流思想,這讓我得到了些許安慰。但很清楚,它獲得的支持日益增多,已經(jīng)成為每個(gè)庫(kù)程序員技巧包里的重要工具。為了彌補(bǔ)
Veldhuizen
首次描述它時(shí)我對(duì)其重要性嚴(yán)重低估的過(guò)失,我在《
Effective C++
》第三版的一個(gè)條款里盡我全力總結(jié)了這門技術(shù)及其用途。
《
Exception-Safety in Generic Components
》,作者
David Abrahams
。我能找到的最早的是發(fā)表在德國(guó)《
Dagstuhl Castle
》
1998
年
4
月
27
日到
5
月
1
日的《
Proceedings of the International Seminar on Generic Programming
》。不過(guò)我想在
1997
年中,相關(guān)文獻(xiàn)可能就出現(xiàn)了,因?yàn)?/span>
Herb Sutter
發(fā)表在《
C++ Report
》(也許是別的雜志)
1997
年
9
月刊的一篇文章引用了
David Abrahams
論文里的內(nèi)容。我也發(fā)現(xiàn)有對(duì)
David Abrahams
于
1997
年
4
月發(fā)表在
Usenet
上的文章(
http://tinyurl.com/nk5vn
)里內(nèi)容的引用,不幸的是,這個(gè)鏈接已經(jīng)實(shí)效。
現(xiàn)在,保證函數(shù)提供基本、強(qiáng)健和無(wú)拋出的三個(gè)異常安全辦法已經(jīng)廣為人知。
Herb Sutter
傳播了這些術(shù)語(yǔ),并且寫了很多相關(guān)的文章,但最早提出它們的是
David Abrahams
,我這么說(shuō)的主要理由是
Sutter
已經(jīng)很細(xì)心地承認(rèn)過(guò)這一點(diǎn)
[
注釋
7]
。一些重要文獻(xiàn)初生于相當(dāng)狹小的空間,但讀者中間很多人有條件發(fā)揮廣泛影響力(比如正在定義
C++
標(biāo)準(zhǔn),或者負(fù)責(zé)標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)),因此文獻(xiàn)的影響力將會(huì)被大大提高。我想,這就是一個(gè)例子。
有趣的是,盡管
Abrahams
的文獻(xiàn)啟蒙了我們對(duì)奠定
C++
標(biāo)準(zhǔn)庫(kù)規(guī)范基礎(chǔ)的異常安全的理解,但
C++
標(biāo)準(zhǔn)里卻未提及“
basic guarantee
”、“
strong guarantee
”或是“
nothrow guarantee
”。
??
注釋:
1.
因?yàn)閭鬟f環(huán)路問(wèn)題(比如
B
的想法起源于
A
,但
A
的靈感來(lái)自于
Z
,
Z
又是受
Y
的影響……),實(shí)際情況比這還要糟糕。
??????? 2. const
不徹底的這個(gè)理由可能和簡(jiǎn)化實(shí)現(xiàn)并不相干。其實(shí)考察
const
和指針結(jié)合時(shí)的常見規(guī)則,它就是一個(gè)很自然的結(jié)果。我們定義指針
p
為
const
,但這并不能限定
*p
也是
const
。在
const member function
里,
*this
是
const
,如果
p
是
*this
的一個(gè)指針成員,我們也不能確定
*p
就是
const
。
??????? 3.
稍早一點(diǎn),還有另一本
C++
書冊(cè)類圖書,即
Thomas Plum
與
Dan Saks
合著的《
C++ Programming Guidelines
》,
1991
年由
Plum Hall
出版,但它從未引起過(guò)大量關(guān)注。我很早就讀過(guò)這本書,現(xiàn)在我又快速閱讀了一遍,給它的結(jié)論是:嗯……相當(dāng)無(wú)趣。
???? ?? 4.
我是《
C++ Report
》的專欄作家,我記得那時(shí)候就在想,
Cargill
肯定瞄上了我,要我去寫異常方面的東西。系統(tǒng)且有專業(yè)眼光地挑出同僚作品中的缺點(diǎn),是我曾經(jīng)經(jīng)歷過(guò)的最費(fèi)心勞神的事情。我確信從此以后,自己不是發(fā)表作品前要再三檢查的唯一專欄作家了。
???? ? ?5.
正在布朗大學(xué)計(jì)算機(jī)科學(xué)系攻讀博士學(xué)位的
Andrei Alexandrescu
曾經(jīng)公開指出這個(gè)模式的名字應(yīng)該被還以本色,比如“
F-bounded polymorphism
”,但很不幸,他的意見沒(méi)有引起人們的注意。這件事引起了我的興趣,因?yàn)槲揖驮谀莾韩@得了博士學(xué)位,不過(guò)我從未聽說(shuō)過(guò)“
F-bounded polymorphism
”。
CRTP
盡管是一個(gè)古老的名字,但仍然能打動(dòng)我,因?yàn)樗取?/span>
F-bounded XXX
”顯得更自然。
??????? 6.
它可能對(duì)文獻(xiàn)里第一個(gè)例子實(shí)現(xiàn)編譯時(shí)冒泡排序沒(méi)有什么用處。我對(duì)冒泡排序一直有相當(dāng)病態(tài)的反感。不僅是因?yàn)檫@種排序算法幾乎從來(lái)就不適用于我的工作,而且也幾乎從來(lái)不值得在工作中考慮這種算法。哦,我離題了。
??????? 7.
初時(shí),這點(diǎn)還不完全清楚。
Sutter
在《
C++ Report
》
1997
年
9
月刊上發(fā)表的文章里并沒(méi)有將“
basic guarantee
”和“
strong guarantee
”歸功于
Abrahams
,但他提供并允許放在我的
1999
版《
Effective C++
》光盤的文章提到了
Abrahams
。我有十足把握公開說(shuō)《
C++ Report
》發(fā)表的文章和
Sutter
提供給我的文章是不一樣的。
?