「次の」クラスを作成する再帰マクロを作成したいと思います。
例:
#define PRINTME(indexNum) class m_##(indexNum+1) { }
はindexNum + 1
として評価されint
、クラス名に連結されません。
連結する前に、コンパイラにそれを評価させるにはどうすればよいですか?
「次の」クラスを作成する再帰マクロを作成したいと思います。
例:
#define PRINTME(indexNum) class m_##(indexNum+1) { }
はindexNum + 1
として評価されint
、クラス名に連結されません。
連結する前に、コンパイラにそれを評価させるにはどうすればよいですか?
が呼び出されるたびに一意のクラス名を生成する場合PRINTME
は、次の1つの方法があります。
#define CONCATE1(X,Y) X##Y
#define CONCATE(X,Y) CONCATE1(X,Y)
#define PRINTME class CONCATE(m_,__COUNTER__) {}
__COUNTER__
はgccの拡張機能であり、他のコンパイラに存在するかどうかはわかりません。このマクロが呼び出されるたびに、コンパイラーが1を追加することが保証されています。
(この場合、__LINE__
または__FILE__
効果的に使用することはできません。)
デモ。
簡単な答えは、できないということです。プリプロセッサは通常、テキストとトークンを扱います。算術演算が実行される唯一の場所は in#if
および#elif
ディレクティブです。
また、マクロ展開は再帰的ではありません。展開中、展開中のマクロは無効になり、それ以上代用することはできません。
醜いコードに耐えるモチベーションと能力に基づいて、それは実行可能です。まず、増分マクロを定義します。
#define PLUS_ONE(x) PLUS_ONE_##x
#define PLUS_ONE_0 1
#define PLUS_ONE_1 2
#define PLUS_ONE_2 3
#define PLUS_ONE_3 4
#define PLUS_ONE_4 5
#define PLUS_ONE_5 6
#define PLUS_ONE_7 8
#define PLUS_ONE_8 9
#define PLUS_ONE_9 10
// and so on...
PLUS_ONE(x)
プリプロセッサは連結操作を拡張しないため、連結操作で使用することはできません。ただし、方法はあります。プリプロセッサが可変個引数を展開するという事実を悪用することができます。
// pass to variadic macro to expand an argument
#define PRINTME(indexNum) PRINTME_PRIMITIVE(PLUS_ONE(indexNum))
// do concatenation
#define PRINTME_PRIMITIVE(...) class m_ ## __VA_ARGS__ { }
終わり!
PRINTME(1); // expands to class m_2 { };
代わりにテンプレートの使用を検討しましたか?