トライグラフが廃止だって??!


C++17で、「トライグラフ」(trigraph)という言語機能が廃止されます。

言語機能が廃止になる意味

ふつう、プログラミング言語で一度用意した機能を廃止するということは、そう多くはありません(Javaでも、多くはdeprecatedで生き残っています)。

廃止される機能というのには、いくつかのパターンがありますが、

  1. 文法上の加減で発生してしまった、全く役に立たない機能だった(PHPでのbreak 0;(unset)キャストなど)
  2. 省略可能で、誰も使っていなかったキーワードの廃止(「自動変数」から「型推論」に転用されたautoなど)
  3. もとの仕様が危険であるために、廃止するしかなかった(C言語のgetsなど)
  4. 利用者が少ないので、廃止しても問題ないと判断された

のようにいくつか考えられますが、トライグラフの廃止理由としては4に当たります。

そもそも、トライグラフって?

この記事を読む人の90%以上は、実用的な目的でトライグラフを書いたことがないであろうし、「トライグラフ」が何だか知らない人も多いと思います。

トライグラフの説明をするために、歴史の針を1970年代まで戻してみます。当時はUnicodeどころか、ラテンアルファベット圏では文字コードが7ビットしかありませんでした1。そのため、英語ならともかく他の国ではアクセント付きのアルファベットを入れるために、ASCIIの記号領域を削って詰め込むような事態となっていました。これらをまとめた文字コードがISO 646で、今で言うASCIIのうち、記号領域の何文字かが可変となっていました。

ところが、C言語では使う文字コードに指定がなかった2上に、可変な記号領域まで使うので、文字がない、という事態が発生してしまうわけです。そこで生まれたのがトライグラフでした。

機能

変換前 変換後
??= #
??( [
??/ \
??) ]
??' ^
??< {
??! |
??> }
??- ~

ソースコードに「変換前」の文字を書くと、「変換後」のように認識される、それだけの仕組みです。

問題点

「ソースコードの表記を書き換える」という性質上、これらのトライグラフはプリプロセッサ処理より前という、かなり早いレベルで発動してしまいます。なので、文字列中にあったものも、お構いなしで変えていくので、「そこで文字列を2つに分ける」「\?という、?に変換されるだけのエスケープシーケンスを使って、"?\?!"のように書く」といった対策が必要となってしまいます(参考)。

終焉(したけどあまり変わらないかも)

ISO 646しかなかったために7ビットに無理やり詰め込む状況もISO 8859では解消されて、さらにはUnicodeも導入される環境では、トライグラフは無用の長物となっていき、「コードに入っていたら警告が出る」「動作させるのにオプションがいる」ような状況となっていて、実質余計なもの扱いとなっていました。

C++11の制定にあたっても非推奨化の提案が出たのですが、EBCDIC環境でC++を使うIBMからの反対があり、いったんは流れてしまいました。C++17では非推奨を通り越して廃止となったのですが、オプションとして実装するのは妨げない、という流れになったので、IBMもそのまま使い続けて、ASCII/Unicode環境ではオプションで召喚 or 完全廃止、ということで、結局はそう変わらない気もしています。

関連リンク

脚注


  1. 今はだいぶ改善していますが、メール配信のSMTPも、7ビットしか通らないことになっています。 

  2. JavaやJavaScriptでは、コードセットもUnicodeが前提となっています。