新しいバージョンのコンパイラにアップグレードするときに遭遇した落とし穴は次のとおりです。
トークン貼り付け演算子(##
)を不要に使用すると移植性がなくなり、不要な空白、警告、またはエラーが生成される可能性があります。
トークン貼り付け演算子の結果が有効なプリプロセッサトークンでない場合、トークン貼り付け演算子は不要であり、有害である可能性があります。
たとえば、トークン貼り付け演算子を使用して、コンパイル時に文字列リテラルを作成しようとする場合があります。
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a##+##b)
#define NS(a, b) STRINGIFY(a##::##b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
一部のコンパイラでは、これは期待される結果を出力します。
1+2 std::vector
他のコンパイラでは、これには不要な空白が含まれます。
1 + 2 std :: vector
GCCのかなり新しいバージョン(> = 3.3程度)では、このコードをコンパイルできません。
foo.cpp:16:1: pasting "1" and "+" does not give a valid preprocessing token
foo.cpp:16:1: pasting "+" and "2" does not give a valid preprocessing token
foo.cpp:16:1: pasting "std" and "::" does not give a valid preprocessing token
foo.cpp:16:1: pasting "::" and "vector" does not give a valid preprocessing token
解決策は、プリプロセッサトークンをC / C ++演算子に連結するときに、トークン貼り付け演算子を省略することです。
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a+b)
#define NS(a, b) STRINGIFY(a::b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
連結上のGCC CPP文書の章では、トークン貼り付けるオペレータのより有用な情報を持っています。
std::wstring BuildDate = WIDEN(__DATE__) L" " WIDEN(__TIME__);
文字列全体を一度に暗黙的に構築できます。