The C++0x "Remove Concepts" Decision

正如 COdEfr3@K 所說:大件事!花了點時間 survey 一些網站~

  1. 大師說話了
    1. Bjarne Stroustrup: The C++0x “Remove Concepts” Decision
    2. Doug Gregor: What Happened in Frankfurt? (由 COdEfr3@K 補充)
    3. Herb Sutter: Trip Report: Exit Concepts, Final ISO C++ Draft C++ Draft in ~18 Months
    4. Bjarne Stroustrup Expounds on Concepts and the Future of C++ 
    5. Danny Kalev:
      1. The Removal of Concepts From C++0x
      2. The Rise and Fall of C++0x Concepts
      3. The Future of C++ 0x, Part 1
    6. The View (or trip report) from the July 2009 C++ Standard meeting
    7. The View (or trip report) from the July 2009 C++ Standard meeting (Part 2)
    8. Concepts Removed from C++0x
  2. 鄉民的討論
    1. Concepts Get Voted Off The C++ 0x Island
    2. The Removal of Concepts From C++0x
    3. TopLanguage: {C++} concept给毙了:(
  3. 翻譯~ 
    1. Concept 的道路
    2. Concept 失敗的原因

下面是從 DDJ 翻譯的,讓 Bjarne 說說看整個事件吧 : )

The C++0x "Remove Concepts" Decision

在 2009 七月的德國法蘭克福會議上, C++ Standards Committee 決定將 concepts 移出 C++0x。雖然這對那些致力於 concepts 多年以及熟知 Concepts 潛力的人們來說是個沈重的打擊,但幸運地,移除 concepts 對大多數的程式設計師並不太有直接的影響。對於現實世界的軟體開發, C++0x 和 C++98 相比,仍舊是個更極具表達力(expressive)和更有效用的(effective)語言。 Committee 對於 remove concepts 的用意:在於希望能限制它帶能的風險與確保整個時程(The committee acted with the intent to limit risk and preserve schedule),或許更好的 concepts 會在未來五年後出現。這篇文章將簡述移除 concepts 的理由以及 committee 做出此決定背後的的考量,此外也讓大家知道 C++ 的天還沒有塌下來啊~(儘管大把大把的謠言剛好說得相反!)

No "Concepts" in C++0x

2009 七月 ISO C++ Standards Committee (WG21) 的法蘭克福會議上,在討論 concepts 應用在 specifying requirements for template arguments 時被"脫鉤(decoupled)"了,對於我來說,一個比較不那麼外交的用語是被"猛烈扯開(yanked out)"了,這代表 concepts 不會出現 C++0x 或是它的 library 裡頭,在我看來,這是 C++ 的一大挫敗,但不是災難一場(disaster);一些替代方法都只會更糟。(That -- in my opinion -- is a major setback for C++, but not a disaster; and some alternatives were even worse)

我在 concepts 已經努力超過七年了,而花了更甚於此的時間在解決這類問題。許多對於 concepts 的工作已經非常久了,舉例來說(按年代排序):

唉,這不用說,我跟其他人對於這件事感到相當失望,而事實上,一些替代方案都只是更糟、於事無補的,而我也無法提供快速、便利的解法。

請注意到 C++0x 對於 C++ features 的改善與進步對大多數程式設計師看到和使用到的是沒有影響的。C++0x 與 C++98 相比,將仍舊是更具表達力的(expressive),它支援了:

  • Concurrent programming
  • A better standard library
  • 許多的改善使得寫出好程式碼更加容易、簡單(像是更有效率、更好維護)

尤其,對於那些我給的 C++0x 範例,要是沒用到 concepts 或是 requires 的更是不受影響(像是在 Evolving a language in and for the real world: C++ 1991-2006 at ACM HOPL-III )。請參考我寫的 C++0x FAQ,一些人們甚至對於 C++0x 比他們想像中的還簡單而感到歡欣。

Concepts 曾經是 C++0x 對於 template 有更好的理論基礎的重要核心 feature,像是說:

  • 提供更加穩固的 standard library specification
  • 扮演讓泛型程式設計(generic programming)成為主流使用的核心角色

現在,人們將在沒有語言的直接支援下使用 concepts。我對於未來最好的想像(scenario)是:我們在五年後的 C++ 裡頭得到了比現有 concepts 更好的 concepts。要能得到這樣的成果將會需要許多人非常專注的研究(但可不是"design by committee"喔!)。

What Happened?

Concepts 在過去幾年被發展出來,並在 2008 年,經過某些技術上的妥協後,進入到了 C++0x working paper 裡頭(妥協是自然而且必須的)。在實驗性的實作中已經足以應付"conceptualized" standard library,但還不到產品品質(but was not production quality),但我個人認為已經足夠稱為 proof of concept (POC)了!

(此段怕誤導、失真,段落後附有原文節錄)

我跟幾位 members 對於 concepts 有著同樣的考量:

Concepts 的設計,尤其是可用性(usability)這點,是否可為一般普通的程式設計師所掌握

會這麼說,是因為這決定了 concepts 設計的目標:

使 generic progarmming 可被大多數的程式設計師接受[BS&GDR2003]

但這目標在我現在看來已經做了極大的妥協:

Concepts 已經變成了(只存在)專家手上的工具,而不是一個讓 generic programming 更加可被接受的工具了。

過去一年半裡,我試著從使用者的角度去檢驗 C++0x,我擔心即用了 concepts 加持的 libraries 仍然對於程式設計師設下了一道新門檻。我覺得 concepts 的設計和它在 standard library 的使用並沒有充分反應我們過去幾年對於 concepts 的經驗。

「原文節錄」:My concern was with the design of "concepts" and in particular with the usability of "concepts" in the hands of "average programmers." That concern was shared by several members. The stated aim of "concepts" was to make generic programming more accessible to most programmers [BS&GDR2003], but that aim seemed to me to have been seriously compromised: Rather than making generic programming more accessible, "concepts" were becoming yet another tool in the hands of experts (only). Over the last half year or so, I had been examining C++0x from a user's point of view, and I worried that even use of libraries implemented using "concepts" would put new burdens on programmers. I felt that the design of "concepts" and its use in the standard library did not adequately reflect our experience with "concepts" over the last few years.

接著,幾個月以前,Alisdair Meredith (一位極具洞察力的 UK committee)和 Howard Hinnant (the head of the standard library working group)問了幾個很好的問題,問題是關於:

  • 誰應該直接使用到 concepts、
  • 使用 concepts 哪個部份、
  • 如何使用

「原文節錄」:who should directly use which parts of the "concepts" facilities and how

這問題導引出各方考量以及不同角度出發對於 usability 的討論。最後,在經過多次令人混淆的討論後,我把我的結論放在 [BS2009]。

幾個可能有點過度簡化的結論:

  • 現行定義的 concepts 難以使用,並將導致 concepts 不被使用(disuse),這可能是 template 不被使用或是 C++0x 不被公開採納。
  • 一些簡化方法[BS2009]仍舊可以描述 concepts ,使得 C++0x 可以出貨或是僅須稍稍的修改。

請注意到:這只是個非常簡略、囫圇吞棗的結論,standards committee 在討論時是非常有 polite 的,我們有著同樣的目標,總是避免直接的針鋒相對、對質詢問。不幸的是,當時的(內部)討論實在過於龐雜(許許多多牽涉到細節或沒有牽涉到細節的訊息)、令人困惑,在對於問題的定位及如何處理沒有浮現共識下,我在法蘭克福會議裡頭報告了幾項替代方案:

  • "fix and ship"
    • Remaining work: remove explicit "concepts," add explicit refinement, add "concept"/type matching, handle "concept" map scope problems
    • Risks: no implementation, complexity of description
    • Schedule: no change or one meeting
  • "Yank and ship"
    • Remaining work: yank (core and standard library)
    • Risks: old template problems remain, disappointment in "progressive" community ("seven year's work down the drain")
    • Schedule: five years to "concepts" (complete redesign needed) or never
  • "Status quo"
    • Remaining work: details
    • Risks: unacceptable programming model, complexity of description (alternative view: none)
    • Schedule: no change

我和一些其他的人贊同第一個方案("fix and ship")並認為這是可行的。然而,大多數的 committee 不是這麼認為,他們選擇了第二個方案("yank and ship," renaming it "decoupling")。在我看來兩者都比第三個方案("status quo")好,我對於投票結果的解讀是這樣的:(這段怕有情緒性字眼,也保留原文)

  • 對於 concepts 的支持者而言,他們沒有一個共識,整個想法看起來太過爭議
  • 一些人則是擔心 C++0x 雄心勃勃的時程表開始(ㄜ,在我不公正地看來,開始指責 concepts)
  • 一些人則是從頭到尾對於 concepts 就是興致缺缺

「原文節錄」:My interpretation of that vote is that given the disagreement among proponents of "concepts," the whole idea seemed controversial to some, some were already worried about the ambitious schedule for C++0x (and, unfairly IMO, blamed "concepts"), and some were never enthusiastic about "concepts."

有鑑於此,"fixing concepts"不再是一個迫於現實的選則了,本質來說,所有對於 concepts 的支持都將是更久之後的事("later" and "eventually")。我對於現在把 concepts 移除這件事也提出了會有無可避免的延遲的警告, 因為在沒有時程的壓力下,所有的設計抉擇都將被重新評估(譯注:我想是對於 concepts 的設計抉擇)。

「原文節錄」:I warned that a long delay was inevitable if we removed "concepts" now because in the absence of schedule pressures, essentially all design decisions will be re-evaluated.

令人驚訝的(或許吧),在法蘭克福的會議上沒有關於 concepts 的技術報告和討論。整個討論都只著重在時間問題上,我想這投票結果主要反應時間考量吧~

請不要譴責 committee 的謹慎,這不是 "Bjarne vs. the committee fight", 而是試著在大多數人的考量中取得平衡點。我跟其他人會失望,是因為我們沒有抓住"fix and ship"這個機會,而且 C++ 不是一個學院派、實驗性質的語言,除非成員們相信這麼做對於程式碼撰寫上帶來的風險非常低,否則他們就得、也必須拒絕接受它。整體來說,committee 代表的是數十億行程式碼,舉例來說,如果 C++0x 無法被公開採納或是無法在有 concepts 的情況下讓 unconstrained templates 得到長期的使用,C++ 社群將會分崩離析。因此,一個很虛(poor)的 concepts 設計可能會比沒有 concepts 帶來更糟的後果。兩難之間,我也選擇了移除 concepts ,我寧願選擇挫敗也不要一個災難來臨。

Technical Issues

懸而未解的 concepts,其問題在於,當把焦點放到 distinction between explicit and implicit "concept" maps 時(參考 [BS2009]):

  1. Should a type that meets the requirements of a "concept" automatically be accepted where the "concept" is required (e.g. should a type X that provides +, -, *, and / with suitable parameters automatically match a "concept" C that requires the usual arithmetic operations with suitable parameters) or should an additional explicit statement (a "concept" map from X to C) that a match is intentional be required? (My answer: Use automatic match in almost all cases).
  2. Should there be a choice between automatic and explicit "concepts" and should a designer of a "concept" be able to force every user to follow his choice? (My answer: All "concepts" should be automatic).
  3. Should a type X that provides a member operation X::begin() be considered a match for a "concept" C<T> that requires a function begin(T) or should a user supply a "concept" map from T to C? An example is std::vector and std::Range. (My answer: It should match).

我的建議和在"status quo before Frankfurt" 提到的解法(answer)是完全不同的。很明顯地,在這裡我必須忽略大部份的細節和設計理念、簡化一下我的解釋。

我無法在這裡重現整個技術討論,但是下面是我的結論:在 "status quo" 的設計裡頭, "concept" maps 被用來做到兩件事:

  • To map types to "concepts" by adding/mapping attributes and
  • To assert that a type matches a "concept."

不知何故(Somehow),後者未被視作不幸的、少見的必要性,反而被視為基本的功能。當兩個 concepts 有著語意上的差別時,我們需要的不是一個用來說明這個 type 符合這個 concept 但不符合那個 concept 的 assertion (這充其量,只是種 workaround,一種不直接接、用說明回擊問題本身的手法,原文:this is, at best, a workaround -- an indirect and elaborate attack on the fundamental problem),而是一個 assertion 可以說明這 type 帶有與這 concept 相同的語意,但沒有另外一個  concept 的語意。(fulfills the axiom(s) of the one and not the other "concept")

「原文節錄」:Somehow, the latter came to be seen an essential function by some people, rather than an unfortunate rare necessity. When two "concepts" differ semantically, what is needed is not an assertion that a type meets one and not the other "concept" (this is, at best, a workaround -- an indirect and elaborate attack on the fundamental problem), but an assertion that a type has the semantics of the one and not the other "concepts" (fulfills the axiom(s) of the one and not the other "concept").

舉例來說, STL 的 input iterator 和 forward iterator 有著關鍵性的語意差別:

You can traverse a sequence defined by forward iterators twice, but not a sequence defined by input iterators;

像是,在 input stream 上施行 multi-pass algorithm 不是個好主意!在 "status quo" 解法中,會強迫每個使用者說明:

What types match a forward iterator and what types match an input iterator

而我的建議的解決方式是:

若且唯若(If (and only if))

  1. 你想使用的語意並不是兩個 concepts 的共同部份,
  2. 而且 compiler 無法幫你推導出哪個 concept 才是較好的 metch 時,

你必須說明 type 的語意,像是說:

"my type supports multi-pass semantics."

其他人則可能是這麼說:

"When all you have is a 'concept' map, everything looks like needing a type/'concept' assertion."

在法蘭克福的會議上,我是這樣做結論的:

  • Why do we want "concepts"?
    • To make requirement on types used as template arguments explicit
      • Precise documentation
      • Better error messages
      • Overloading

不同的人們有不同的出發點以及排出不同的優先順序,然而,站在這高階的角度來看,可能會有些混淆,但應該是極少或不相衝突的。每個合理的、才走一半的 concept design 都提供了這些特性。

  • What concerns do people have?
    • Programmability
    • Complexity of formal specification
    • Compile time
    • Run time

我個人關注的是 programmability (ease of use, generality, teachability, scalability) ,其次是正式規格書的 complexity (40 頁的標準文件),再其他則關於 compiler time 和 run time 的考量。然而,我覺得實驗性質的實作(ConceptGCC [Gregor2006])中,constrained templates (使用 concepts)的 run time 可以做的跟 nonconstrained templates 一樣好、甚至更好。ConceptGCC 實際上非常慢,但我並未將它視為根本考量,當它用來驗證一個想法時,我們陷入了傳統上的兩難。這裡描述一下有點過度簡化的兩難問題:

  • "Don't standardize without commercial implementation"
  • "Major implementers do not implement without a standard"

各方面來說,細節設計和實驗實作構成了基本的妥協。

我對 concepts 的原則是:

  • Duck typing
    • The key to the success of templates for GP (compared to OO with interfaces and more)
  • Substitutability
    • Never call a function with a stronger precondition than is "guaranteed"
  • "Accidental match" is a minor problem
    • Not in the top 100 problems

我對於 concepts 的"minimal fixes"寫在 pre-Frankfurt working paper:

  • "Concepts" are implicit/auto
    • To make duck typing the rule
  • Explicit refinement
    • To handle substitutability problems
  • General scoping of "concept" maps
    • To minimize "implementation leakage"
  • Simple type/"concept" matching
    • To make vector a range without redundant "concept" map

細節請參考 [BS2009]。

No C++0x, Long Live C++1x

即使在 concepts 已經被移除後,下一版的 C++ standard 仍可能延遲推出。悲慘地說,將不會有 C++0x 了(除非你把 C++0x 這個小改版算進去)。我們一定得等到 C++1x,希望這個 x 是個很小的數字。希望還是在的,因為 C++1x 已經 feature complete 了(除非標準對於一些在 formal proposal for the standard 還有所堅持)。 "所有" 剩下、懸而未決的都只是龐雜的技術問題和意見了。

在我的 C++0x FAQ 中你可以看到一些 features 和討論,這裡僅是列出部份:

和 libraries:

  • Improvements to algorithms
  • containers
  • duration and time_point
  • function and bind
  • forward_list a singly-liked list
  • future and promise
  • garbage collection ABI
  • hash_tables; see unordered_map
  • metaprogramming and type traits
  • random number generators
  • regex a regular expression library
  • scoped allocators
  • smart pointers; see shared_ptr, weak_ptr, and unique_ptr
  • threads
  • atomic operations
  • tuple

    即使沒有了 concepts,C++1x 仍將會是個基於 C++98 大量改善的版本,尤其當你注意到這些 features 都讓你可以在最大的表達力(expressiveness)和彈性(flexibility)間的互動的。我希望我們會在新版的 C++ (或許五年後)中看到 concepts ,也或許我們應該稱呼 C++1y 或是 C++y!

    心得

    該看書了 >__<

  • 7 則留言:

    fr3@K 提到...

    http://cpp-next.com/archive/2009/08/what-happened-in-frankfurt/

    Keiko 提到...

    呵呵,手上的資訊太封閉了,謝謝資訊分享啊!這個網頁字好大,看得還挺舒服的! Doug Gregor 的現身說法,讓只看 B.S ddj 的文章的疑點也澄清了 :)

    Keiko 提到...

    引述 Dave Abrahams 的回應:
    It’s pretty hard to bootstrap significant usage experience for a language feature as big as concepts. Compiler vendors are generally not eager to invest resources in implementation until the feature is very likely to be standardized. Users are generally not eager to use non-standard language features in production code, especially without many implementations out there to reduce the risk of vendor tie-in. So while it would be great to gather lots of data, I wouldn’t expect to be able to find that data much before the language feature is at least blessed by a TR.

    External beta 的重要?! XD 可是 committee 可沒有錢請人來 beta

    C++ 的 compiler 不好寫,一個 buggy 的實作,會讓人望之卻步、有不好的第一印象,即使有一個美好的 POC 完成了,能否得到廣泛的使用和迴響呢?即使可以,但與此同時也產生了“既有的程式碼”,當 POC 要變成 standard ,這些“既有的程式碼”可能得面臨修改的命運,多少人力和資源願意投注在這上面呢?語言和產品相比,似乎更多了一份不可回溯性。

    這應該也就是 B.S 提到的 dilemma 吧?!
    * Don't standardize without commercial implementation
    * Major implementers do not implement without a standard

    Keiko 提到...

    Update:
    Doug Gregor: What Happened in Frankfurt?

    Bjarne Stroustrup Expounds on Concepts and the Future of C++

    D. N. A. 提到...

    現在才看到這篇 大lag XD

    直覺的部分會想到如果移除concepts那generic programming不就沒辦法有更好的進展了嗎

    沒想到他們在討論是否引入這個新觀念的時候意外地保守

    總之 真是有失落的感覺/ \

    Keiko 提到...

    @ D.N.A

    是啊,哭哭了,雖然這保守其來有因,但我還忍不住想到考汽車駕照筆試,答案選了就不能改…

    Evan 提到...

    其實筆試選了還是可以改阿...

    Windows + Visual Studio + VSCode + CMake 的疑難雜症

    Environment Windows 10 Visual Studio 2019 CMake 3.27.7 VSCode VSCode CMake Tools 1. CMAKE_BUILD_TYPE 是空的 參考一下 這篇 的處理。 大致上因為 Visual...