CS の学生にグループ番号を変更させてから、その番号に関連するものを生成させる必要があります。学生にはあまり変更してほしくありませんが、どこかで定義された 1 つのグループ番号だけを
#define GROUP_NUM 0
ただし、その MACRO から残りを生成する方法が見つかりません。例えば:
#include <iostream>
using namespace std;
// string troubles
#define STR(x) #x
#define XSTR(x) STR(x)
// the trouble
#define GROUP_NUM 0
#define CLASS_NAME Group GROUP_NUM
#define CLASS_STR XSTR(CLASS_NAME)
int main()
{
cout << "CLASS_NAME = " << CLASS_STR << endl;
return 0;
}
悲しいことに出力
CLASS_NAME = Group 0
ここでの問題は、次のようなクラスを作成するために CLASS_NAME を使用する必要があるため、 Groupと0の間にそのスペースが必要ないことです。
class CLASS_NAME : public .... { ... }
使ってみた
#define CLASS_NAME Group##GROUP_NUM
しかし、その後 GROUP_NUM は展開されず、出力されます
CLASS_NAME = GroupGROUP_NUM
私が見つけた唯一の解決策は、これらの CLASS_NAME と CLASS_STR を、引数としてグループ番号を渡されるマクロ関数として定義することです (別のマクロではなく、呼び出しサイトで!):
// the trouble
#define GROUP_NUM 0
#define CLASS_NAME(g) Group ## g
#define CLASS_STR(g) XSTR(CLASS_NAME(g))
int main()
{
cout << "CLASS_NAME = " << CLASS_STR(GROUP_NUM) << endl;
return 0;
}
より良い解決策はありますか?以下が展開されないのはなぜですか?
#define CLASS_STR XSTR(CLASS_NAME(GROUP_NUM))
上記のXSTRの定義は、チェーンされたマクロを使用できることを示しているように見えるので、ここで展開されない理由がわかりません。
更新: ヘルパー マクロ関数のトリックが解決策です。ただし、解決策を明確にしたいと思います。
- マクロ展開トリックはどのように機能しますか? 直接完全に拡張するのか、それとも 1 ラウンドだけ拡張するのか? (つまり、複雑なマクロを使用している場合、ヘルパー関数のレイヤーが複数必要になるということでしょうか?)
- ## による展開は、私にはまだ少し不思議です。
私の完全な問題は、nori フレームワーク、特にthisに関係していました。そのマクロを使用すると、つまり
#define NORI_REGISTER_CLASS(cls, name) \
cls *cls ##_create(const PropertyList &list) { \
return new cls(list); \
} \
static struct cls ##_{ \
cls ##_() { \
NoriObjectFactory::registerClass(name, cls ##_create); \
} \
} cls ##__;
NORI_REGISTER_CLASS(CLASS_NAME, "mystring") を使用すると、誤って部分的に展開されてしまいます
Group0 * CLASS_NAME_create (const PropertyList &list) { return new Group0 (list); } ...
しかし、1 つのラッパー マクロを使用してそのマクロを呼び出すと、機能します。ここでのマクロ展開のルールは何ですか? 最初の cls が展開され、2 番目の cls が名前を保持するのはなぜですか?