2010-10-04

C++0xの落とし穴を埋める改良

聡明なC++0xプログラマである読者諸君ならば、もう、以下のコードは、C++0xでは、疑いようもなくwell-formedであることを知っているだろう。

// C++03ではill-formed
// C++0xではwell-formed
vector<vector<int>> v ;

従来、連続した>は、>>演算子と、文法上曖昧であるので、かならず>>演算子だと解釈されるようになっていた。C++0xでは、このような場合、演算子と解釈されることはなくなった。もちろん、分かりやすさから言えば、空白文字を挟んだ方が分かりやすいだろう。

vector< vector< int > > v ;

何にしても、このようなちょっとした落とし穴は、初心者を無用に混乱させる。、C++0xでは、このようなちょっとした落とし穴がいくつも塞がれている。

さて、ここまでが前振りで、ここからが本番である。以下のコードは、C99では、ill-formedである。C++03ではundefined behaviorである。C++0xではwell-formedである。ただし、[EOF]は、ソースファイルの終りを表す。実際の文字ではない。

int main()
{

}[EOF]

何故か。C99は、空ではないソースファイルは、必ず改行文字で終わらなければならないと定めているからだ。C++03では、空ではないソースファイルが、改行文字で終わっていない場合は、挙動は未定義と定めているからだ。したがって、上記のコードは、C99やC++03といった、前時代の旧言語では、動かない。

しかし、この仕様は、ユーザーの立場になって考えると、馬鹿げている。ソースファイルの終りが改行でなければならないというのは、ユーザー側からすれば、意味が分からない。ユーザー側からすれば、ソースファイルはそこで終わっているのだから。C++0xでは、このような馬鹿げた制限を取り払った。C++0xでは、空ではないソースファイルが、改行文字で終わっていない場合は、改行文字が補われると定めている。したがって、上記のコードは、C++0xという最高にクールな新言語では、well-formedである。

実は、このC++0xの制限緩和は、実に最近の変更である。いつドラフトに入ったのかというと、FCDからである。何と、今年に入ってからの変更だ。

ちなみに、この制限に関する文面は、
C99(TC3)の5.1.1.2 Translation phases paragraph 1.2
C++03の2.1 Phases of translation paragraph 1.2
C++の最新ドラフトN3126の2.2 Phases of translation paragraph 1.2
に書いてある。

2 comments:

齊藤 said...

POSIX 的にはテキストファイルは改行で終わることになっています。
・テキストは行の集合である
・行は改行で終わる
という理屈だそうです。
これが制約の由来でしょう。
言語の制約としては無意味ですが、 C の制定当時はツール類との協調を考えてそうしたのかなと想像します。

江添亮 said...

POSIX由来ですか。
テキストは行の集合という前提すら、現代人である私からすると、もう理解できませんね。