プリプロセス時のユーザ定義リテラルについて
C++0x で新しく追加されるユーザ定義リテラルはアンダースコアから始まってないとダメという制約がありますが、これがコンパイル時に問題にならないということは hito さんが書いています(本の虫: user defined literalが予約語の制約を無視できる理由)。
でもコンパイル時じゃなくてプリプロセス時ならどうなるの?という話です。
アンダースコア二つから始まる名前と、アンダースコアひとつに大文字から始まる名前は、当然プリプロセス時にも影響してきます。
ということは、
#define __hoge hage
というのをコンパイラが予約していた場合、
"bjarne"__hoge
というのをユーザが書いた場合、プリプロセス時に __hoge が置換されてしまって、意図しない結果になりそうです。
これは問題だなーとか思っていて、ぼけーっと仕様書を眺めていたのですが、こんなのを見つけました。
N3035 §2.5
- 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
preprocessiong-token は置換の対象となるトークンのことなのですが、この中に user-defined-charactor-literal と user-defined-string-literal が入っているのが分かります。
つまり
"bjarne"__hoge
は user-defined-string-literal と認識されるため、置換されないのです。
プリプロセスの仕様は C99 の追加部分を入れるだけだと思っていたのですが、意外なところが変更されてて驚きでした。
これで安心してアンダースコアを付けまくってユーザ定義リテラルを作ることができそうです。