続・定義済みのプリプロセッサ定数による判断
C/C++ 定義済みのプリプロセッサ定数による判断、推論方法 - 檜山正幸のキマイラ飼育記 メモ編 の続き。次のような定義を共通ヘッダファイルに入れて、それをどのソースでもインクルードするようにする。
#if !defined(_WIN32) || defined(_POSIX_SOURCE) || defined(_ANSI_SOURCE) # define NO_WIN32 1 #endif #if defined(NO_WIN32) || !defined(_MSC_VER) || !defined(_MFC_VER) # define NO_MFC 1 #endif
そうすれば、ソース内では NO_WIN32 と NO_MFC を頼りに#ifdef分岐すればいい。
プリプロセッサ定数がどうなっているか調べるプログラムを書いてみた。なんかうまい方法でコピペを減らせるかと思ったがダメだった。多少は工夫したが、基本はコピペと目視確認だった。ソースの生成プログラムを書けばいいが、それもバカらしい。単純配列の代わりに、文字列をキーとするハッシュマップを使えば、多少は楽になっただろうが、なんかのコンテナライブラリが必要になる。
[追記]ガーン、これ全然ダメじゃん。アホか。
定数が定義されていれば、その名前が展開されてしまって無茶苦茶だ。nm接頭辞はそれを避けるために付けたのだが、他で名前そのものを使っているから、これじゃダメ。[/追記]
#include <stdio.h> // 興味あるマクロ定数の名前を列挙 // 名前の前にnm接頭辞を付ける。 enum MacroName { nmNDEBUG = 0, nm_WIN32, nm_POSIX_SOURCE, nm_ANSI_SOURCE, nm_MSC_VER, nm_MFC_VER, nmNO_WIN32, nmNO_MFC }; // 興味あるマクロ定数の個数 #define NAME_COUNT (static_cast<int>(nmNO_MFC) + 1) int name_flags[NAME_COUNT]; #define SET_FLAG(name, val) name_flags[nm##name] = (val) #define STR(name) #name #define VAL(name) name_flags[nm##name] void set_flags() { #if defined(NDEBUG) SET_FLAG(NDEBUG, 1); #else SET_FLAG(NDEBUG, 0); #endif #if defined(_WIN32) SET_FLAG(_WIN32, 1); #else SET_FLAG(_WIN32, 0); #endif #if defined(_POSIX_SOURCE) SET_FLAG(_POSIX_SOURCE, 1); #else SET_FLAG(_POSIX_SOURCE, 0); #endif #if defined(_ANSI_SOURCE) SET_FLAG(_ANSI_SOURCE, 1); #else SET_FLAG(_ANSI_SOURCE, 0); #endif #if defined(_MSC_VER) SET_FLAG(_MSC_VER, 1); #else SET_FLAG(_MSC_VER, 0); #endif #if defined(_MFC_VER) SET_FLAG(_MFC_VER, 1); #else SET_FLAG(_MFC_VER, 0); #endif #if defined(NO_WIN32) SET_FLAG(NO_WIN32, 1); #else SET_FLAG(NO_WIN32, 0); #endif #if defined(NO_MFC) SET_FLAG(NO_MFC, 1); #else SET_FLAG(NO_MFC, 0); #endif } int main() { set_flags(); printf("%s = %d\n", STR(NDEBUG), VAL(NDEBUG)); printf("%s = %d\n", STR(_WIN32), VAL(_WIN32)); printf("%s = %d\n", STR(_POSIX_SOURCE), VAL(_POSIX_SOURCE)); printf("%s = %d\n", STR(_ANSI_SOURCE), VAL(_ANSI_SOURCE)); printf("%s = %d\n", STR(_MSC_VER), VAL(_MSC_VER)); printf("%s = %d\n", STR(_MFC_VER), VAL(_MFC_VER)); printf("%s = %d\n", STR(NO_WIN32), VAL(NO_WIN32)); printf("%s = %d\n", STR(NO_MFC), VAL(NO_MFC)); return 0; }