誰かが同じことをしたい場合の答えは次のとおりです。
#define _PP_0(_1, ...) _1 // (a,b,c,d) => a
#define _PP_X(_1, ...) (__VA_ARGS__) // (a,b,c,d) => (b,c,d)
//for each a in __VA_ARGS__ do f(a,x)
//where x is some parameter passed to PP_TRANSFORM
#define PP_TRANSFORM(f,x,...) \
PP_JOIN(PP_TRANSFORM_,PP_NARG(__VA_ARGS__))(f,x,(__VA_ARGS__))
#define PP_TRANSFORM_0(...)
#define PP_TRANSFORM_1( f,x,a) f(_PP_0 a,x) PP_TRANSFORM_0( f,x,_PP_X a)
#define PP_TRANSFORM_2( f,x,a) f(_PP_0 a,x) PP_TRANSFORM_1( f,x,_PP_X a)
...
#define PP_TRANSFORM_51(f,x,a) f(_PP_0 a,x) PP_TRANSFORM_50( f,x,_PP_X a)
...
#define PP_TRANSFORM_99(f,x,a) f(_PP_0 a,x) PP_TRANSFORM_98(f,x,_PP_X a)
#define PP_TRANSFORM_100(f,x,a)f(_PP_0 a,x) PP_TRANSFORM_99(f,x,_PP_X a)
ここPP_NARG
で、 は引数の数をカウントするPP_JOIN
マクロで、 はトークンを結合するマクロ (つまりPP_JOIN(a,b) => ab
) です。PP_NARG
64 個を超える引数を処理できるようにする場合は、パッチを適用する必要もあります。
さて、元の質問に戻ります。を使用したソリューションPP_TRANSFORM
は次のとおりです。
#define FUNCTION(name, dummy) void name();
#define FUNCTION_TABLE(...) PP_TRANSFORM(FUNCTION,dummy,__VA_ARGS__)
C++ 実装関数を生成する場合は、次の不透明な x パラメータを使用できますPP_TRANSFORM
。
#define FUNCTION_CPP(name, class) void class::name(){}
#define FUNCTION_TABLE_CPP(...) PP_TRANSFORM(FUNCTION_CPP,MyClass,__VA_ARGS__)
これらはすべて、GCC および MSVC プリプロセッサでも同じように機能します。__VA_ARGS__
PP_TRANSFORM_NN は、GCC と MSVC の 100 定義の個別の実装を回避するために使用されません