Я пытаюсь сгенерировать объявление функции с помощью макроса
/* goal: generate int f(int a, float b) */
template<typename P>
struct ptype;
template<typename P>
struct ptype<void(P)> { typedef P type; };
#define NAMEe
#define COMMAe
#define COMMA ,
#define NAME(N) N PARAMS
#define PARAMS(P, ...) COMMA ## __VA_ARGS__ P NAME ## __VA_ARGS__
#define PARAM_ITER(P) P NAME
#define PROTO(R, N, P) \
ptype<void R>::type N (PARAM_ITER P (,e))
PROTO((int), f, (int)(a)(float)(b));
Он будет итеративно обрабатывать следующие (name)
или (type)
на NAME
или PARAMS
соответственно, с ...
, имеющим пустой аргумент макроса. Но GCC жалуется с
* * 1010
И лязг жалуется на
ptype<void (int)>::type f (int aprototype.hpp:20:1: warning: varargs argument missing, but tolerated as an extension [-pedantic]
Я думаю, что это происходит из-за следующего
#define FOO(X, ...)
FOO(A);
Потому что я не передаю аргумент для ...
или каждого из них (name)
или (type)
. Есть ли какая-нибудь простая работа, которую я могу применить?
Теперь я использовал технику, похожую на технику, которую использовал @James, чтобы найти длину списка параметров. Если в качестве второго аргумента вместо O
будет передано ONT
, я выведу запятую и NAME
. Ниже приводится окончательное решение:
/* goal: generate void f(int a, float b) */
template<typename P>
struct ptype;
template<typename P>
struct ptype<void(P)> { typedef P type; };
#define TYPE_DO(X) X
#define TYPE_DONT(X)
#define TYPE_MAYBE(X, A, ...) TYPE_D ## A (X)
#define COMMA_DO ,
#define COMMA_DONT
#define COMMA_MAYBE(A, B, ...) COMMA_D ## B
#define NAME_DO NAME
#define NAME_DONT
#define NAME_MAYBE(A, B, ...) NAME_D ## B
#define NAME(N) N PARAMS
#define PARAMS(...) COMMA_MAYBE(__VA_ARGS__,O,O) TYPE_MAYBE(__VA_ARGS__,O,O) \
NAME_MAYBE(__VA_ARGS__,O,O)
#define PARAM_ITER(P) P NAME
#define PROTO(R, N, P) \
ptype<void R>::type N (PARAM_ITER P (D,ONT))
Тест:
#define STR1(X) #X
#define STR(X) STR1(X)
int main() {
// prints correctly
std::cout << STR(PROTO((int), f, (int)(a)(float)(b)));
}