tags:

views:

167

answers:

2

Possible Duplicate:
c++ var-arg macro, NOT template

I have to do with Macros (it's macros calling macros; so templates are out of the question).

Here's what I want:

foo(3, a, b1, c1) --> foo1(a, b1, c1);
foo(5, a, b1, c1, b2, c2) -> foo2(a, b1, c1, b2, c2);
foo(7, a, b1, c1, b2, c2, b3, c3) -> foo3(a, b1, c1, b2, c2, b3, c3);

So basically, what I want is to be able to execute the "function" n -> (n-1)/2 at macro expansion time. Is this possible?

Thanks!

[PS, if you dislike my questions; I support your right to downvote; my worst question so far is only -17, so maybe we can break that record; however, please let me know why my question is technically invalid.]

Thanks

EDIT:

Foo takes a variable # of arguments, of the form:

foo(N, a1, b1, a2, b2, ... a_N, b_N) -> foo##N(a1, b1, a2, b2, ... a_N, b_N);

EDIT:

To all the closers. This is a very different question. The former is about "how do I count the # of arguments in a Macro." (to which there was a good response on the mailing list).

This question is a matter of: given I've counted the # of arguments, how do I dispatch on it?

+3  A: 

I haven't tested this, but should work:

#define SUBSTFOO3( a, b1, c1 ) foo1(a, b1, c1)
#define SUBSTFOO5( a, b1, c1, b2, c2 ) foo2(a, b1, c1, b2, c2)
/* ad nauseam */

#define foo( N, ... ) SUBSTFOO ## N ( __VA_ARGS__ )

This might also work:

#define SUBSTFOO3 foo1 /* no arguments needed */
#define SUBSTFOO5 foo2 /* "( __VA_ARGS__)" already the correct substitution */

#define foo( N, ... ) SUBSTFOO ## N ( __VA_ARGS__ )
Potatoswatter
Might want to change to `#define foo3( a, b1, c1 ) (foo1)(a, b1, c1)` a) leave off the semicolon b) put parenthesis around the function name to prevent inadvertent macro expansion (in the case of `foo3`) or similar errors.
Chris Lutz
You're right about semicolons, but I don't think the parentheses would halt macro expansion. The way to be paranoid here would be to introduce your own `#define foo3 foo3`.
Potatoswatter
@Potatoswatter - The `(foo1)(a, b, c)` is to prevent `foo(7, ...)` from simplifying to `foo7(a, b, c, d, e)` to `foo3(a, b, c, d, e)` to `error: macro "foo3" passed 7 arguments, but takes just 3` (which is what I get when I use GCC).
Chris Lutz
@Chris: ah, I see. I think the better solution is to avoid aliasing the names of the intermediate steps in the first place. Correcting my answer.
Potatoswatter
very nice; thanks :-)
anon
+1  A: 

I'm not sure I understand your question, but it reminds me of this trickery I saw in the GCC source. Maybe you'll spot something applicable.

#if GCC_VERSION >= 3000 || __STDC_VERSION__ >= 199901L
/* Use preprocessor trickery to map "build" to "buildN" where N is the
   expected number of arguments.  This is used for both efficiency (no
   varargs), and checking (verifying number of passed arguments).  */
#define build(code, ...) \
  _buildN1(build, _buildC1(__VA_ARGS__))(code, __VA_ARGS__)
#define _buildN1(BASE, X)   _buildN2(BASE, X)
#define _buildN2(BASE, X)   BASE##X
#define _buildC1(...)       _buildC2(__VA_ARGS__,9,8,7,6,5,4,3,2,1,0,0)
#define _buildC2(x,a1,a2,a3,a4,a5,a6,a7,a8,a9,c,...) c
#endif
Dan Olson