최근 비슷한 문제가 발생했으며 해결책이 있다고 생각합니다.
핵심 아이디어는 매크로 NUM_ARGS
를 작성 하여 가변성 매크로가 제공되는 인수의 수를 세는 방법이 있다는 것 입니다. 당신의 변형을 사용할 수있는 NUM_ARGS
빌드로 NUM_ARGS_CEILING2
가변 인자 매크로가 1 개 인자 또는 2 또는-이상의 인수가 주어집니다 여부를 알 수있다. 그런 다음 Bar
매크로 를 작성하여 인수를 사용 NUM_ARGS_CEILING2
하여 CONCAT
두 개의 도우미 매크로 중 하나에 인수를 보낼 수 있습니다. 하나는 정확히 1 개의 인수를 예상하고 다른 하나는 1보다 큰 인수를 기대합니다.
여기 매크로 작성이 트릭을 사용하는 예입니다 UNIMPLEMENTED
매우 유사하다 BAR
:
1 단계:
/**
* A variadic macro which counts the number of arguments which it is
* passed. Or, more precisely, it counts the number of commas which it is
* passed, plus one.
*
* Danger: It can't count higher than 20. If it's given 0 arguments, then it
* will evaluate to 1, rather than to 0.
*/
#define NUM_ARGS(...) \
NUM_ARGS_COUNTER(__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, \
12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define NUM_ARGS_COUNTER(a1, a2, a3, a4, a5, a6, a7, \
a8, a9, a10, a11, a12, a13, \
a14, a15, a16, a17, a18, a19, a20, \
N, ...) \
N
1.5 단계 :
/*
* A variant of NUM_ARGS that evaluates to 1 if given 1 or 0 args, or
* evaluates to 2 if given more than 1 arg. Behavior is nasty and undefined if
* it's given more than 20 args.
*/
#define NUM_ARGS_CEIL2(...) \
NUM_ARGS_COUNTER(__VA_ARGS__, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 1)
2 단계:
#define _UNIMPLEMENTED1(msg) \
log("My creator has forsaken me. %s:%s:%d." msg, __FILE__, \
__func__, __LINE__)
#define _UNIMPLEMENTED2(msg, ...) \
log("My creator has forsaken me. %s:%s:%d." msg, __FILE__, \
__func__, __LINE__, __VA_ARGS__)
3 단계 :
#define UNIMPLEMENTED(...) \
CONCAT(_UNIMPLEMENTED, NUM_ARGS_CEIL2(__VA_ARGS__))(__VA_ARGS__)
CONCAT가 일반적인 방식으로 구현되는 곳. 빠른 힌트로, 위의 내용이 혼란스러워 보이는 경우 : CONCAT의 목표는 다른 매크로 "호출"로 확장하는 것입니다.
NUM_ARGS 자체는 사용되지 않습니다. 여기에 기본 트릭을 설명하기 위해 포함 시켰습니다. 멋진 처리 방법은 Jens Gustedt의 P99 블로그 를 참조하십시오 .
두 가지 메모 :
NUM_ARGS는 처리하는 인수의 수가 제한되어 있습니다. 숫자는 완전히 임의적이지만 광산은 최대 20 개까지만 처리 할 수 있습니다.
그림과 같이 NUM_ARGS에는 0 개의 인수가 주어지면 1을 반환한다는 함정이 있습니다. 요점은 NUM_ARGS가 기술적으로 인수가 아닌 [쉼표 + 1]을 세는 것입니다. 이 특별한 경우에는 실제로 우리에게 유리합니다. _UNIMPLEMENTED1은 빈 토큰을 잘 처리하여 _UNIMPLEMENTED0을 쓰지 않아도됩니다. Gustedt도 그에 대한 해결 방법을 가지고 있지만 사용하지는 않았지만 우리가 여기서하는 일에 효과가 있는지 확실하지 않습니다.
BAR
대신FOO
처음부터?