プリプロセス時のユーザ定義リテラルについて

C++0x で新しく追加されるユーザ定義リテラルはアンダースコアから始まってないとダメという制約がありますが、これがコンパイル時に問題にならないということは hito さんが書いています(本の虫: user defined literalが予約語の制約を無視できる理由)。


でもコンパイル時じゃなくてプリプロセス時ならどうなるの?という話です。
アンダースコア二つから始まる名前と、アンダースコアひとつに大文字から始まる名前は、当然プリプロセス時にも影響してきます。
ということは、

#define __hoge hage

というのをコンパイラが予約していた場合、

"bjarne"__hoge

というのをユーザが書いた場合、プリプロセス時に __hoge が置換されてしまって、意図しない結果になりそうです。


これは問題だなーとか思っていて、ぼけーっと仕様書を眺めていたのですが、こんなのを見つけました。

italic;">preprocessing-token::header-name
identifier
header-name
identifier
pp-number
character-literal
user-defined-character-literal
string-literal
user-defined-string-literal
preprocessing-op-or-punc

each non-white-space character that cannot be one of the above
N3035 §2.5

preprocessiong-token は置換の対象となるトークンのことなのですが、この中に user-defined-charactor-literal と user-defined-string-literal が入っているのが分かります。
つまり

"bjarne"__hoge

は user-defined-string-literal と認識されるため、置換されないのです。
プリプロセスの仕様は C99 の追加部分を入れるだけだと思っていたのですが、意外なところが変更されてて驚きでした。


これで安心してアンダースコアを付けまくってユーザ定義リテラルを作ることができそうです。