私のコードが使用している Boost のバージョンを調べようとしています。次のようなことをしたいです:
#error BOOST_VERSION
しかし、プリプロセッサはBOOST_VERSIONを展開しません。
プログラムの実行時にそれを印刷できることはわかっていますし、プリプロセッサの出力を見て答えを見つけることもできることもわかっています。コンパイル中にこれを行う方法があれば便利だと思います。
ベストアンサー1
これは元のクエリからかなり時間が経っていることは承知していますが、まだ役に立つかもしれません。
これは、GCC で文字列化演算子「#」を使用して実行できますが、最初に 2 つの追加ステージを定義する必要があります。
#define XSTR(x) STR(x)
#define STR(x) #x
マクロの値は次のように表示できます。
#pragma message "The value of ABC: " XSTR(ABC)
参照: gcc オンライン ドキュメントの 3.4 文字列化。
使い方:
プリプロセッサは引用符で囲まれた文字列を理解し、通常のテキストとは異なる方法で処理します。文字列の連結は、この特別な処理の例です。メッセージ プラグマには、引用符で囲まれた文字列である引数が必要です。引数に複数のコンポーネントがある場合、文字列の連結を適用できるように、それらはすべて文字列である必要があります。プリプロセッサは、引用符で囲まれていない文字列を引用符で囲まれているものとして扱うことを想定することはできません。その場合、次のようになります。
#define ABC 123
int n = ABC;
コンパイルされません。
ここで考えてみましょう:
#define ABC abc
#pragma message "The value of ABC is: " ABC
これは次の式と同等である。
#pragma message "The value of ABC is: " abc
abc (引用符なし) は前の文字列と連結できないため、プリプロセッサ警告が発生します。
ここで、プリプロセッサの stringize (以前は stringification と呼ばれていましたが、ドキュメント内のリンクは改訂された用語を反映するように変更されています。 (ちなみに、どちらの用語も同じように嫌悪すべきものです。正しい用語は、もちろん stringifaction です。リンクを更新する準備をしてください。)) 演算子について考えてみましょう。これはマクロの引数にのみ作用し、展開されていない引数を二重引用符で囲まれた引数に置き換えます。つまり、次のようになります。
#define STR(x) #x
char *s1 = "abc";
char *s2 = STR(abc);
s1 と s2 に同じ値を割り当てます。gcc -E を実行すると、出力でこれを確認できます。おそらく、STR は ENQUOTE のような名前にしたほうがよいでしょう。
これにより、引用符で囲まれていない項目を引用符で囲む問題は解決されますが、引数がマクロの場合、マクロは展開されないという問題があります。これが、2 番目のマクロが必要な理由です。XSTR は引数を展開し、次に STR を呼び出して、展開された値を引用符で囲みます。