最近プリプロセッサの話しかしてないような気がするから、今日はちょっとプリプロセッサの話でもする

巷では、やれ「プリプロセッサ名前空間を台無しにする」だの「foo(n++)とかしたらn++が二回評価されて結果が云々」だの、「定義のときにカッコがどうたら」とかボロクソ言われてますが、まぁ正しいです。ですがプリプロセッサを見るにつけて、帰りに一杯やったマスオさんを見るサザエさんのような態度をとるのはいかがなもんですか。そこはまさにプリプロセッサを使うべきところかも知れないでしょう。そんなものに頼るなら標準化委員会に要望だせっていうのはちょっと思考が短絡的すぎます。短絡的なのは組み込み型に対する論理演算だけにしてください。C++は既に広く広くひろーく実用されている言語で、そう簡単には規格変更できないですし、何よりC++の規格の関係者がそんな適当なことはしません。彼らは「こういう機能が欲しい」という要求は腐るほど受けていますが、本当は別にそういう機能がなくてもよくて、単に既存のアレを利用してコレコレすればいいか、もしくは全く別の手段のほういいとか、ちゃんとそういうことを議論しています。だいたい、クライアントの要求をよく聞いて思案した結果、実は全然違う手法のほうがよかったりするとか、この業界ではしょっちゅうあることぐらい知ってるでしょう。上流工程とかよく知らないですが、クライアントが本当に求めているのは何かを考えるとかするのは普通ですし、プログラミング言語の規格でも同じです。だから本当に必要なものは何なのかをずっと議論して、必要であると判断したものについては規格として取り入れてますし、あと取り入れるだけが仕事ではないです。既存のコードに影響が出ないように言語のルールを変更しないといけません。それを分かってあげてください。それはとても大変なのです。そこらへんに転がっているような、後方互換を無視してどんどん既存のコードをただのゴミデータに変えるような変更を入れられる数多のマイナー言語とはワケが違うのです。
話が逸れました。プリプロセッサさんです。例えば、C++iteratorを使ってコンテナを走査しますが、for文にしてもfor_eachにしても、

struct fun_obj { void operator() const { ... } };
for_each(cont.begin(), cont.end(), fun_obj());

for (Container::iterator iter = cont.begin, end = cont.end();
     iter != end;
     ++iter)
{
    ...
}

と、どのみち面倒で破壊したくなります。そこで他の言語でいうforeachのようなものが欲しいのですが、C++03にはないです。なので、Boost.Foreachというライブラリができました。

BOOST_FOREACH (Container::value_type x, cont) {
    ...
}

これはとても読みやすく、分かりやすいです。このようにプリプロセッサは使いようですし、プリプロセッサなしで書けないようなものにプリプロセッサを使わないというのは頭がおかしいです。プリプロセッサなしにはやってられないようなことをするな、という意見はありだと思いますが、人間が読みにくいソースコードは高級なプログラミング言語で書かれているということの価値を5割ほど失っていると思うので、やっぱりだめですかっこよく書きましょう。必要なら例えそれがアセンブリだろうがプリプロセッサだろうが、規格でアリだと言っているものは何でも利用の選択肢に入っているべきです。ただ感情から否定するというのはプログラマとしての姿勢を疑います。あなた本当にプログラマですか?もちろんあやしい技術を使うなら、それにあたっての問題は解決しましょう。それができない場合は、残念ながらどこかを妥協するか、諦めるかしかありません。無念です。嫌いというだけで選択肢から外してはいけません。お母さんも好き嫌いするなと言っていたはずです。プリプロセッサも、必要であるなら使いましょう。C++よりは簡単です。