これは、新しいバージョンのコンパイラにアップグレードするときに遭遇した落とし穴です。
トークン貼り付け演算子 ( ##
) を不必要に使用すると、移植性がなくなり、望ましくない空白、警告、またはエラーが生成される可能性があります。
トークン貼り付け演算子の結果が有効なプリプロセッサ トークンでない場合、トークン貼り付け演算子は不要であり、有害である可能性があります。
たとえば、トークン貼り付け演算子を使用して、コンパイル時に文字列リテラルを構築しようとする場合があります。
#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 ドキュメントの章には、トークン貼り付け演算子に関するより有用な情報があります。