2010-08-14

後の世では、何とでも言える

人生を書き換える者すらいた。: C++は何を間違えたのか

ムーブコンストラクタなぞとても使いこなせる自信がない。

ムーブの概念とC++の型システムの詳細が分からないユーザーは、別にムーブを使う必要はない。ムーブはライブラリ実装者のための機能である。なぜなら、明示的に使わなくても、関数の戻り値などのrvalueは、勝手にムーブされるからだ。

これが方向性の歴史的誤りだったよな。
 C++はこういうのではなく、2パスコンパイルにしてヘッダファイルを不要にしたり、GCを言語レベルでサポートしたりすれば今頃の情勢は違うものになったかもしれないのに、結局JavaやC#の外見的な言語仕様のベースになっただけなのはちょっとさびしい。

後の世では、何とでも言える。C++が作られた当時は、到底そんなことは現実的ではなかった。歴史の話をする。

Bjarne Stroustrupが博士号をとるべく研究していた時、彼はSimulaを使っていた。Simulaには、GCがあった。しかし問題は、Simulaの実装は遅すぎたのだ。当時はまだGCのアルゴリズムが洗練されておらず、ハードウェアも、現代では信じられないくらい遅かったからだ。したがって、GCは不可能であった。

当時のハードウェアは、実に遅かった。CPU速度、メモリ、ディスク容量と速度、あらゆるハードウェアが、絶望的に遅かった。そのようなハードウェア上でのコンパイラの実装も、当然、かなり制限を受けた。当時の多くのC言語コンパイラは、ソースコードから一文読み込み、解釈して、すぐに目的のコードを生成し、さてまた次の文の読み込みをしたものである。前後の文脈を考慮した上での最適化など、望むべくもない。C++がregisiterやinlineといった機能を付け加えたのにも、理由があったのだ。

そのような状況であったから、単なるテキストを、その場に流しこむという、愚直な#includeの機能は、実に効率的な方法だったのだ。果たして、当時のハードウェアで、2パスコンパイルして、ソースコードに必要なシンボルテーブルをメモリ上に保持できたかどうか。その辺は、あやしいものである。

この当時、C++は時代の最先端をゆく理想主義な言語であった。もちろん、今でもだいぶ理想主義が入って入るものの、当時に比べたら、非常に現実的である。

C言語には、そもそも、関数の前方宣言などなかった。プログラマーは、特に宣言もせず外部で定義されている関数名を使った。コンパイラーは、プログラマーのコードを信用して、未知の関数を呼び出すオブジェクトコードを生成した。C++が、名前は、かならず使う前に宣言されていなければならないと決めたとき、多くのプログラマが反対した。ある者は、コンパイル時間が極端に長くなることを恐れた。またある者などは、実行時のパフォーマンスに影響が出ることをさえ、恐れた。

今、C言語の文法が、いくらかまともになっているのは、まったくC++のおかげだと言える。当時のC言語がどんな惨状であったかは、改訂されていない、当時のK&Rを読めば分かる。

後の世から、物事を批判することは簡単だが、そんなことは、当時は不可能であるし、もし、当時に現代の常識で物事を決めていれば、その仕組は、現代に残ることはなかっただろう。これはC++に限る話ではない。

例えば文字コードだ。当時は、文字コードに8ビット費やすことすら、無駄が多かったのだ。7ビット、いや、6ビットでも十分足りたのだ。とすれば、何故文字ごときに8ビットも浪費する必要があるというのか。

一文字に8ビットは贅沢すぎるという話を、現代において行えば、世の笑いとなるであろう。しかし、当時としては、切実な問題だったのだ。

9 comments:

Anonymous said...

> 当時のK&Eを読めば分かる。

K&R の間違え?

Anonymous said...

市寝かす

Anonymous said...

registerってC++で追加されたんでしたっけ? K&R 1stではすでにregisterに言及されていたみたいなんですが。
http://books.google.com/books?ei=tsFnTOSfHZG2vQP80fztBw&ct=result&hl=ja&id=va1QAAAAMAAJ&dq=C+Programming+Language+1978&q=register#search_anchor

Anonymous said...

昔のCコンパイラが1パスだったかのような書き方ですが、昔こそオンメモリでコード生成までできなかったためにプリプロセスだけで1パス、構文解析で1パス、コード生成で1パス、Unixなら更にアセンブルでも1パスと、マルチパスだったはずですが。

それはともかく。

AT&TのC++2.0あたりでC++は一度ほぼ完成したと言えます。それがMS-DOSパソコンでさえそこそこの速度でコンパイルできるようになり、Windowsの開発といえばC++ばかりになり。しかし規格はfixせずにテンプレートの比重がどんどん増え、ライブラリもテンプレートベースに全面改定され。

リンク先の記事は、その辺りからの発展が問題だと言っているので、Bjarneの初版の頃のハード状況・設計判断の事を言っても関係ないのでは。それに、テンプレートがチューリング完全なのは、当時のハードが貧弱だからではないでしょう。むしろテンプレートこそコンパイラには重かった。

GCの是非はともかく、規格の言語仕様を適度に制限して理解し易さ・使い易さとのバランスを取るという舵取りは十分できる状況だったと思いますが。

江添亮 said...

一体、規格の何をfixする必要があったのですか。
C++は古典的なコンパイラで実装できるべく設計されていたので、賢い#includeの代替機能などということは、到底無理でした。
テンプレートの比重が増えていったのは、意図通りです。

その後の発展とはどういう意味でしょう。
C++のドラフトは、1998年に変更が止められ、正式な規格としてリリースされました。
言語が広く実装されて、使われるようになるためには、変更されることのない、正式な規格が、是非とも必要だったのです。

Anonymous said...

>その後の発展とはどういう意味でしょう。
>C++のドラフトは、1998年に変更が止められ、

1989年のCfront 2.0リリースからISO/IEC 14882:1998までの9年間に追加・変更された諸々。

Anonymous said...

> 一体、規格の何をfixする必要があったのですか。

上のAnonymousさんが言いたかったのは、規格そのもののことだと思います。

「しかし規格はfixせずに」とありますので。

規格制定に向けてC++のISO部会ができましたが、その後実際に制定されるまで時間が掛かりすぎだと思います。

今回のC++0Xも同じですね。委員会の方々は頑張っていらっしゃるのでしょうけど、カヤの外にいる部外者には時間が掛かりすぎに見えます…。

それにこのブログではC++機能面の記事が多いのですが、実装面から記事は頓珍漢な記事もちらほらある気が…(すみません。)

C++の機能の説明はできても、実際に実装できる技術者が減っている気がしますね。かつては日本にもそれなりにいたのですが…

江添亮 said...

むしろ、現代の方が実装経験は豊富です。

当時は、コンパイラを自前で実装できるというのが、最先端の技術であったので、実行環境を提供する多くの企業が、それぞれ独自に自前コンパイラをも実装していたのです。

現代では、単にコンパイラの実装技術だけでは成り立たなくなっています。
だから今では、実行環境を提供する企業は、C++コンパイラには、GCCやEDGなどの、すでによく知られたフロントエンドを使い、バックエンド部分だけ独自に開発しているのです。

規格制定が遅いということですが、C++の規格は、どの個人や団体も、独占的な権利を持っておらず、C++の規格自体で商業的な利益をあげているわけでもないので、仕方がないのです。

もしC++規格が、JavaやC#のように、一社独裁で開発されていれば、もっと発展も早くなったのかもしれません。
しかし、下位互換性は、遠慮無く切り捨てられていたでしょうし、広く様々な環境で使われることもなかったでしょう。

Anonymous said...

> むしろ、現代の方が実装経験は豊富です。

ごく一部の人達の実装経験は豊富になったでしょうね。

私が言いたいのは実装経験の多さ少なさではなく、その実装経験をもつ人の数です。(もちろん理解の程度も深いにこしたことはありませんが。)

> すでによく知られたフロントエンドを使い、バックエンド部分だけ独自に開発しているのです。

私は言語分野は専門ではありませんが、その現状は承知しています。

で、そのことと、C++規格作りに関わる方々の力量(実装しようと思えば実装できるくらいの知識・経験)があるかどうかと、関係が無いと思いますが。

> 規格制定が遅いということですが、C++の規格は、どの個人や団体も、独占的な権利を持っておらず

これは規格制定が遅れた原因の一つかもしれませんが、最大の原因ではないと思いますが。

おそらく日本だけでなく世界的に言語実装の経験の無い方々が標準化委員会の中にもそれなりに多数いて、自分たちの希望(こういう機能が欲しいとか、こうあるべき、などのC++ユーザ視点の希望)を発言するものの、実際にそれを実現するのにどんな実装が必要か考えられるわけではないのでは?

だから、無知な委員から無責任に沸いて出てきた意見を、ごく一部の実装できる人間(GCC, EDGなどの実装者)が苦労して正しい方向へ補正しているのでは?

海外のネットニュースで遅々として進んでいない様子を伝える記事を見るにつけ、行間から上で述べたような印象を受けるのですが、実際のところどうなのでしょうか?

標準化委員会の方なんですよね?(本当かどうかわかりませんが、、、自称じゃないですよね^^)実際の国際会議ではどんな感じで進められてきたのですか?